Conditional Requests
Conditional requests allow a client to request that an HTTP request be filled only when certain criteria are met. There are two classes of uses for conditional headers: freshining a cache, and preventing lost updates.
Conditional requests are defined by RFC 7232: HTTP/1.1 Conditional Requests. Handling can be summarized into the following rules:
- When using GET/HEAD to request a resource that is already cached, test that the resource has been modified. When updating a resource with other requests (e.g. PUT/PATCH/DELETE), test that the resource has not been modified. When creating a resource, test that it does not exist.
- For GET and HEAD, a condition test failure will return 304 (Not Modified). Other methods will return 412 (Precondition Failed)
- The
*forms ofIf-MatchandIf-None-Matchcan be used to test if the resource exists or not. - The ETag forms of
If-None-MatchandIf-Matchcan be used to test if a resource has been modified or not. - If none of the above tests are specified,
If-Modified-SinceandIf-Unmodified-Sincetests that the resource has or has not been modified since the given timestamp. If-None-Matchtakes precedence overIf-Modified-Since; andIf-Matchtakes precedence overIf-Unmodified-Since. Multiple headers may be specified in the event the server has not implemented one or the other (however, servers are typically required to implement all conditional headers).
Freshining a cache
If a client has previously requested a resource that is currently cached, but needs to be freshened from the origin server, the client may use a If-None-Match and/or a If-Modified-Since header instructing the server to omit the response body if no newer version is available.
Headers
- If-None-Match
- Sent if the client has a stored ETag for the resource
- If-Modified-Since
- Sent if the client has a stored Modified-Time for the resource
- If-Range
- Used if the client is making a Range request, but wishes for the entire resource if there's been any changes since the previous request.
Methods
GET and HEAD are the only requests that return 304 Not Modified. Most requests will use GET; HEAD is technically permitted, but is not very useful, as you would only see if the resource changed, without seeing the new contents.
Response codes
- 304 (Not Modified)
- The resource has not been modified from the client's version.
Lost Updates
A "lost update" is a situation where two users request a resource, make changes, then submit the changes by uploading the entire document. The second document uploaded will overwrite the changes made by the first: the "lost update". Lost updates are avoided by making the update conditional on the resource having not changed; if the resource did change, the server will indicate as such, and the client may merge in the new changes as appropriate.
There are other ways to avoid lost updates, for example, breaking apart resources into multiple documents that can be edited independently, or using a method that allows server-directed conflict resolution, e.g. PATCH.
Headers
- If-Match
If-Match: etagis used if the server has provided anETagin a previous response.- If-None-Match
If-None-Match: *is used if the client is creating a resource and does not wish to overwrite an existing one.- If-Unmodified-Since
- Used if the client does not wish to overwrite changes made since the provided date (the
Last-Modifiedresponse header from a previous request).
Methods
Requests must be a nonsafe method, such as PUT, PATCH, DELETE, POST, etc. The condition is tested just before changes are committed.
Response codes
- 412 (Precondition Failed)
- Used in unsafe requests; the server will not apply the requested action because the condition varies from the client's version.
- 428 (Precondition Required)
- Used in unsafe requests; the server will not apply the requested action because it lacks a conditional header, and as such might overwrite another party's changes.
Server Evaluation
Evaluation order
The evaluation order for testing the conditional headers should not impact the status code, however HTTP suggests an evaluation order for performance purposes:
ETag Validation
The If-Match and If-None-Match are compared against the resource's ETag using a comparison function.
If-Match compares using the strong validation function: the ETags must be exactly the same.
If-None-Match compares using the weak validation function: the ETag Weak flag (the leading W/ ) is ignored, if any, then the rest of the ETag is compared.
Weak validators allow multiple different representations of a resource to share an ETag, for example: a cache applying JPEG compression to an image would add the W/ flag while doing so; or a server providing realtime data may serve a weak ETag that only changes when the data changes by some threshold.