apiresthttpetaghttp-status-code-304

Can I use E-tag for a user specific REST API in order to not send the same data back every time?


Let us say we have an API that retrieves user-specific data. For some reason, I don't want the server to send data back to clients every time is the data is unchanged.

For example, I have a mobile app. Every time it starts, it will show data from the local cache but also retrieves some user-specific data from the server in the background. What I want to do is hoping the server can just return 304 if the data is unchanged.

It seems E-tag can do this kind of thing but I am not sure if it is a good choice here since it is a user-specific API.


Solution

  • HTTP is a request/response protocol. For each of the requests sent by a client the server will respond. The response can either be a failure or a success case. Unless there is an internet drop, there should never be a case where a server does not respond!

    ETag in particular is typically a hash value of the resources current status or a predefined string value i.e. of a version counter (as Evert correctly mentioned) that is returned as HTTP header in responses so a client can use it in scenarios where it wants to alter that particular state and does not want the server to update it if that resource got modified in the meantime (= optimistic locking).

    The second case where ETags are used are for checking whether the state the client has is still the current one known by the server where the server either responds with a 304 Not Modified or a 412 Precondition failed response depending on whether the resource still has the same ETag value or not. Here idealy you should issue a HEAD request to the server to minimize the payload being sent back and forth as all you are probably interested in is whether the current version known by the client is still the one also the server holds.

    ... but I am not sure if it is a good choice here since it is a user-specific API.

    ... I read some articles about E-tag but they all didn't mention anything about user-specific data. ...

    As Jim Webber pointed out, at its heart HTTP is just a transfer protocol whose domain is the transfer of documents over the Web. You better think of it as document management system where you can put new files to some location, delete or retrieve them or process them according to the server's own semantics through POST requests. HTTP is nothing more basically. Hence, any HTTP client that adheres to the rules of HTTP is able to utilize conditional requests as specified in RFC 7232 so should HTTP servers as well. Therefore there is no difference whether the data stemms from some HTTP Web server or some API backed by some Java, .Net or whatever middleware or framework as long as they adhere to the same HTTP protocol. Whether a particular framework or implementation does support that kind of "feature", if you will, is a different story unfortunately.

    In regards to whether it is a good choice to use conditional requests what alternatives do you have? If a client wants to know whether it has the most-recent state of a resource it either needs to ask the server politely whether the version the client knows is still the most recent one or simply retrieve the whole state (again). Some might argue that in a case where the versions differ due to an intermediary update by an other client multiple messages need to be exchanged. This is a valid argument though you need to estimate which might occur more often. In a scenario where a client rarely checks whether its version is still the the most-current one or where updates to that resource occur frequently by various clients, probably retrieving the whole state of that resource again might be less bytes exchanged in total and thus a bit more efficient in the end. Though HTTP offers HEAD requests which you can utilize to minimize the payload size exchanged between client and server as HTTP defines HEAD as

    ... the server MUST NOT send a message body in the response (i.e., the response terminates at the end of the header section). The server SHOULD send the same header fields in response to a HEAD request as it would have sent if the request had been a GET, except that the payload header fields (Section 3.3) MAY be omitted. This method can be used for obtaining metadata about the selected representation without transferring the representation data ...

    A payload within a HEAD request message has no defined semantics; sending a payload body on a HEAD request might cause some existing implementations to reject the request. (Source)

    In essence, HEAD requests and responses to such requests only contain the HTTP headers but no further message body which helps to bring the byte size of the exchanged messages down significantly. In best case, where both versions are equal, you minimized the bytes exchanged notably. In the worst case, where they differ, the additional overhead is probably neglectable unless you are really in a high-performance edge cage. Thus, in cases where you are interested whether your current knowledge of some resource is still the most-recent one, conditional requests via HEAD are a good choice IMO.