Better caching with fewer false positives

Etag

Preliminaries

This note documents how Etags are created and processed by the server. Use of Etag headers is encouraged for reliable caching with fewer false positives.

The use of timestamps for conditional requests is not perfect, because the server and browser may not have their clocks precisely synchronized. The preferred solution to this problem is the use of etag headers. An etag is a hashed value used as an identifier for a resource version. Whenever a resource is changed, its hashed value results in a new etag.

The protocol for using etags is similar to the protocol for conditional timestamps: 1) the original server response sends the resource together with an etag header; 2) the browser saves the etag in its cache together with the resource; 3) conditional requests from the browser are sent with either a if-match or if-none-match header containing the saved etag value; 4) the server compares the resource's hashed value against the conditional etag value and responds with 304 and no payload if they match, or 200 and the resource in the payload if they differ.

See the note on Timestamps for the earlier protocol that does not use etags.

Etags are only applicable to HEAD, GET and PUT requests. During a PUT request, if the special header value '*' is sent by the requestor, it means that the uploaded file should only be accepted if it doesn't already exist.

Configuration

The use of etags by the server is configured by setting the etag entry to on in the module section. There are no other configuration settings required for its use.

Etag values are computed as an SHA1 hash of the file's modification time and file size. The full value is shortened to just the first six and last six hex digits of the hash to look something like "a1b2c3...8d9e0f".

Information Headers

If a PUT request fails due to unmatched etags, a rw-if-match or rw-if-none-match information header is added to the response and a status code of 412 is returned.

EBNF

SP ::= U+20
CR ::= U+0D
LEFT-CURLY-BRACKET ::= U+7B
RIGHT-CURLY-BRACKET ::= U+7D
etag-module-entry ::= 'etag' SP ('on' | 'off') CR
modules-section ::= 'modules' SP LEFT-CURLY-BRACKET CR
etag-module-entry
RIGHT-CURLY-BRACKET CR

† Other modules omitted for brevity.

Cookbook

Example 1: etags disabled, fallback to timestamps
server {
modules {
etag off
}
}
Example 2: etags enabled, timestamps not used
server {
modules {
etag on
}
}

Review

Key points to remember:

  • Etags are hashed values that uniquely identify a file's version.
  • Etags are used for conditional requests.
  • The use of etags is preferred over the use of conditional timestamps.

Better caching with fewer false positives