Caching Metadata Headers

Caching metadata headers allows clients and caching proxies quickly determine if a resource was modified since the last time it was read. With alias objects, caching headers allow clients to verify the previous read is the current revision before writing an update to it. 

See https://perifery.atlassian.net/wiki/spaces/public/pages/2443820996.

HTTP defines several header mechanisms for clients and caching proxies to quickly determine whether a resource was modified since the last time the data was read. In the Swarm context, caching headers make proxies more effective by extending the caching period to its maximum value, essentially telling the proxies that the resource does change for immutable objects.

To maintain compatibility with a wide variety of browsers and proxies, Swarm implements the caching mechanisms for both HTTP/1.0 and HTTP/1.1.

Note

Swarm returns an HTTP 412 response if it cannot find the bucket or domain associated with a request. This can be distinguished from a cache response by the lack of the current ETag in the response headers and a response body that denotes that the bucket or domain cannot be located.

HTTP 1.1 Caching Headers

The newer HTTP/1.1 cache coherency mechanism does not use dates or timestamps and thus avoids the granularity and synchronization problems of the HTTP/1.0 headers. Instead, it uses entity tags (or ETags) that can be compared for exact equality.

In Swarm, ETag values are opaque, variable length, case-sensitive strings enclosed in quotes. Any characters preceding or following the quoted string are ignored. If the header value has no quoted string, the entire header is ignored. The value of each date header adheres to the Full Date specification (RFC 7232) and dates in that format are recognized by Swarm on incoming requests.

Swarm supports the following HTTP 1.1 caching headers:

Cache-Control

Cache-Control can be used on READ and WRITE requests to determine whether data retrieved from the content cache is acceptable for this request or whether a specific object can ever be stored in the content cache. Swarm supports the Cache-Control: no-cache and Cache-Control: max-age parameters as discussed in RFC 7234 5.2.

Swarm also supports the Cache-Control: no-cache-context extension that instructs Swarm not to use cached contexts. (A context is a container; for example, the context of a named object is a bucket.) Cache-Control: no-cache-context can be used on any SCSP READ or WRITE request to instruct Swarm to ignore the content cache when looks up the bucket and domain for a named object. Use it in a READ request to prevent Swarm from returning "stale" bucket and domain data from the cache.

See https://perifery.atlassian.net/wiki/spaces/public/pages/2443820846 for when Swarm may return "stale" data.

ETag

Swarm returns the ETag header for all POST, PUT, COPY, APPEND, GET, and HEAD operations. Swarm uses "strong" ETags (as defined in RFC 7232 2.3) that can be compared for exact (case-sensitive) equality.

Example of an ETag response header:

ETag: "508941dc9b52243f64d964b058354b76"

The ETag of an immutable unnamed object does not change during the entire lifecycle of the object, whereas mutable named and unnamed object ETags change each time the object is mutated by a PUT.

Note

SCSP operations (Update, Delete, etc.) cannot be performed for an existing object using the ETag.

If-Match

A Swarm client or proxy can include the If-Match header with the PUTCOPYAPPENDGET, and HEAD methods. The value of the header is either a single quoted string (possibly with some ignored flags outside the quotation marks), a comma-separated list of quoted strings, or a single asterisk. Any additional strings are ignored.

Below are examples of If-Match request headers:

If-Match: "508941dc9b52243f64d964b058354b76"  If-Match: "508941dc9b52243f64d964b058354b76", "fe3233d3c6881d5e8b654117b829d26c"  If-Match: W/"508941dc9b52243f64d964b058354b76"  If-Match: *

Swarm performs the requested method as if the If-Match header field did not exist if the entity tags match the primary UUID of the object returned in the response to a similar GET request (without the If-Match header) on that resource or if "*" is given. The If-Match header is ignored if the request results in anything other than a 2xx status without the If-Match header field.

Swarm does not perform the requested method, and instead return an HTTP 412 Precondition Failed response with a current ETag header if none of the entity tags match. This behavior is most useful when the client wants to prevent an updating method (such as PUT) from modifying an aliased object that changed since the client last retrieved it.

Swarm does not return a response status of HTTP 412 Precondition Failed unless it is consistent with all conditional header fields in the request if Swarm receives a conditional request that includes both a Last-Modified date (for example, in an If-Modified-Since or If-Unmodified-Since header field) and one or more entity tags as cache validators (for example, in an If-Match header field).

If-None-Match

A Swarm client or proxy can include this header with the PUTCOPYAPPENDGET, and HEAD methods to make it conditional. This feature allows efficient cached information updates with a minimum amount of transaction overhead. The header value is either a single quoted string (possibly with some ignored flags outside the quotation marks), a comma-separated list of quoted strings, or a single asterisk, anything after which is ignored.

Examples of If-None-Match request headers:

If-None-Match: "508941dc9b52243f64d964b058354b76"  If-None-Match: "508941dc9b52243f64d964b058354b76", "fe3233d3c6881d5e8b654117b829d26c"  If-None-Match: W/"508941dc9b52243f64d964b058354b76"  If-None-Match: */

Swarm does not perform the requested method if the entity tags match the primary object UUID that is returned in the response to a similar GET request (without the If-None-Match header) on that object or if "*" is given and the object does exist. Swarm responds with an HTTP 304 Not Modified response, including a current ETag header for the object if the request method was GET or HEAD. Swarm responds with a response of HTTP 412 Precondition failed with the same current ETag as the GET or HEAD response for all other request methods. The object was modified if none of the previously recorded and supplied entity tags match. The requested method proceeds as if the If-None-Match header field did not exist.

Swarm does not return a response status of HTTP 304 Not Modified or HTTP 412 Precondition failed unless it is consistent with all conditional header fields in the request if Swarm receives a conditional request that includes both a Last-Modified date (for example, in an If-Modified-Since or If-Unmodified-Since header field) and one or more entity tags (for example, in an If-None-Match header field) as cache validators.

If-Range

A Swarm client or proxy can include the If-Range header with a GET request method to obtain an additional specified portion of the object if it has not changed or the entire object if it has changed. The value of the header can be either a single quoted string (possibly with some ignored flags outside the quotation marks) or an HTTP-date string (unquoted).

Examples of If-Range request headers:

If a client has a partial copy of an object in its cache and wishes to have an up-to-date copy of the entire object in its cache, it can use the Range request-header with a conditional GET using either or both of If-Unmodified-Since and If-Match headers. If the condition fails because an aliased object was updated, the client must make a second request to obtain the entire current object. The If-Range header allows a client to "short-circuit" the second request; "if the object is unchanged, send the missing part(s); otherwise, send the entire object."

If the client has no entity tag for an object but has a Last-Modified date, it can use that date in an If-Range header. Swarm can distinguish between a valid HTTP-date and any form of entity-tag by looking for double quotes. The If-Range header should be used together with a Range header, and is ignored if the request does not include a Range header.

If the entity tag given in the If-Range header matches the current primary object UUID or the HTTP-date given is not before the Last-Modified date of the object, Swarm provides the specified sub-range of the object using an HTTP 206 Partial content response. If the entity tag does not match, Swarm returns the entire object using an HTTP 200 OK response.

HTTP 1.0 Caching Headers

In the first version of HTTP, the cache coherency mechanism used time stamps with one-second granularity to decide if a resource was modified and, therefore, required invalidating the cached copy. In addition to the course time granularity that can mask changes made in the same second (to aliased objects for example), this approach also requires the client and/or proxy clocks to be reasonably well synchronized with the server clocks.

Warning

Although Swarm supports this coherency method for compatibility reasons, it is not the preferred mechanism because of these issues and is not supported for rapid update use cases. ETag comparisons are recommended for cache coherency on objects that are rapidly updated. The value of each date header adheres to the Full Date Section 3.3.1 of the HTTP/1.1 specification and dates in that format are recognized by Swarm on incoming requests.

Swarm supports the following HTTP/1.0 caching headers:

  • Last-Modified

  • If-Modified-Since

  • If-Unmodified-Since

  • Expires

Last-Modified

Swarm returns the Last-Modified header for all POST, PUT, COPY, APPEND, GET, and HEAD operations. The value of the header is exactly the same as the Castor-System-Created header for both ordinary objects and aliased objects.

  • This is the original object time stamp for ordinary objects.

  • This is the server time when the alias was last updated for aliased objects.

If-Modified-Since

A Swarm client or proxy can include the If-Modified-Since header with a GET or HEAD method request. All other methods ignore the header when present in the request. The If-Modified-Since request header field is used with a GET to make it conditional.

An entity is not returned from the server if the requested object was not modified since the time specified in the If-Modified-Since header. Instead, an HTTP 304 Not Modified response is returned without any message-body.

See Section 14.25 in the HTTP 1.1 specification for details.

If-Unmodified-Since

A Swarm client or proxy can include this header with a GET, PUT, or DELETE method. All other methods ignore this header when present in the request. The If-Unmodified-Since request header field is used with a method to make it conditional.

  • Swarm performs the requested method as if the If-Unmodified-Since header is not present if the requested object is not modified since the time specified in this field.

  • Swarm does not perform the requested method, and instead, returns an HTTP 412 Precondition failed if the requested object is modified since the specified time.

  • The header is ignored if the specified date is invalid.

Expires

Swarm returns an Expires header if it is persisted with the content. Swarm does not generate an Expires header.

The Expires header field provides the final date and time when the response is considered stale. A stale cache entry may not normally be returned by a cache (either a proxy cache or a user agent cache) unless it is first validated with Swarm (or with an intermediate cache that has a fresh copy of the object). Since Swarm has no information about when an aliased object may be updated and little information about when an object may be deleted, Swarm does not generate an Expires header for any object. Expires are added to the list of persisted headers so applications can supply a hint to caching proxies and clients as to when an object may become stale.

© DataCore Software Corporation. · https://www.datacore.com · All rights reserved.