1. HTTP (Hypertext Transfer Protocol)

  1. Conditional Requests
    1. Freshining a cache
      1. Headers
      2. Methods
      3. Response codes
    2. Lost Updates
      1. Headers
      2. Methods
      3. Response codes
    3. Server Evaluation
      1. Evaluation order
      2. ETag Validation

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 of If-Match and If-None-Match can be used to test if the resource exists or not.
  • The ETag forms of If-None-Match and If-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 and If-Unmodified-Since tests that the resource has or has not been modified since the given timestamp.
  • If-None-Match takes precedence over If-Modified-Since; and If-Match takes precedence over If-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 an ETag 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:

  1. If-Match
  2. If-Unmodified-Since
  3. If-None-Match
  4. If-Modified-Since
  5. If-Range

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.