HTTP Caching - HTTP 1.0 vs HTTP 1.1
Caching is one of the key optimisation methods in HTTP. It can reduce both network overhead and page load times, resulting in an improved experience for the client. Within this article we will look the various headers and options available in both HTTP 1.0 and HTTP 1.1.
The caching mechanism within HTTP 1.0 is simple in design. The client requests a resource, the resource is then returned by the origin server along with the following HTTP headers,
- Expires - the date that the resource will expire and therefore should be deemed invalid by the cache.
- Last-Modified - when the resource was last modified.
The client can then instruct the origin server to only send the resource if it has a newer copy by using the If-Modified-Since header. Otherwise the origin will send a HTTP 304 - Not Modified response. This is also known as a Conditional Request.
However the client can also request the resource is not served from cache by using the Pragma: no-cache header.
The main issue with caching within HTTP 1.0 was due to its simplest nature, there were instances where the resource was incorrectly cached.
HTTP 1.1 extends the caching functionality from HTTP 1.0.
In HTTP 1.1 a cached entry is considered fresh. At the point the expiry time is reached it is deemed stale. Should the cache entry be considered stale it must be revalidated with the origin server. However both client and origin are able to override this requirement.
Due to the If-Modified-Since header using absolute timestamps (with a one-second-resolution) there was a potential for caching issues due to inconsistencies with time synchronization. To solve this issue a new cache validator string was introduced called an ETag (entity tag). Entity tags are provided with the cached response within the ETag header.
In addition to If-Modified-Since HTTP 1.1 introduces the following conditional request-headers,
- If-None-Match : <entitiy tag>- Instructs the server to send the resource if the entity DOES NOT exist of the server. If the entity does exist on the server a 304 (Not Modified) is returned.
- If-Match : <entitiy tag> - Instructs the server to send the resource if the entity DOES exists on the server.
- If-Unmodifed-Since : <date> - Instructs the server to send the resource if the resource has NOT been modified since the date provided.
- If-Range (entity_tag | date) - Used along with the Range header. This follows the same principle as above but is instead works a a byte range level rather then a resource level.
2 further headers that were also added to HTTP 1.1 are the headers - cache-control and vary.
- Cache-control was introduced within HTTP 1.1 and can be included in either the HTTP request or response. Further details of the various options can be found within the 'Cache-Control Options' section below.
- Vary is sent within the servers response to the client and instructs any intermediary caches to cache a separate instance based on the headers specified within the vary header.
Within the HTTP Cache-Control header there are a number of options. These are shown below,
|max-age=[seconds]||Number of seconds that the resource is considered valid.|
|s-maxage=[seconds]||The same as max-age but only for public/shared caches. Ignored by private caches.|
|public||Marks the resource as cacheable by any cache. If HTTP auth is required the resource is marked as private.|
|private||Marks the resource as cacheable except for public/shared caches.|
|no-cache||Revalidate the resource with the server before it serves it from its cache.|
|no-store||The cache must not store a copy of the resource.|
|must-revalidate||Cache must revalidated expired resource. i.e not serve if expired.|
|proxy-revalidate||Same as must-revalidate header excluding private caches.|
|no-transform||Instructs cache not to transform body of message. Transformation is sometimes performed to optimize performance on slow links (i.e reduce images etc).|