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-Match
andIf-None-Match
can be used to test if the resource exists or not. - The ETag forms of
If-None-Match
andIf-Match
can be used to test if a resource has been modified or not. - If none of the above tests are specified,
If-Modified-Since
andIf-Unmodified-Since
tests that the resource has or has not been modified since the given timestamp. If-None-Match
takes precedence overIf-Modified-Since
; andIf-Match
takes 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: etag
is used if the server has provided anETag
in 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-Modified
response 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.