How do you force browsers to revalidate static content like an swf, xml, txt, … files? We often have this problem with customers and advise them to clear their cache. Not a very good solution don’t you think?
So how do you solve this? We could append the version of our product to the static files, so that with a new release, browsers wouldn’t hit their cache loading the file. A condition for this to work would be that the home page (default page) should always be the latest version from the server. This page would have references to the static files with version appended to them.
What about browsers asking the server if a newer version is available. In comes the must-revalidate header.
First of all, how does web cache work?
Either the protocols (HTTP 1.0 and 1.1) or the one reponsible for the cache (user of browser or proxy admin) determine when to get a file from the cache (if it’s there is one off course. You could have cleared the cache for instance).
- A file is fresh (cache can send it to client without checking the origin) when
- the file is still within the fresh period (Expires header, age header)
- the file is in cache and brower has been set to check once a session
- the file is in proxy cache and modified long ago
- File is stale –> origin will be asked to validate the file (like this, if the file hasn’t changed, it doesn’t need to be sent over again)
- If no validator can be found, it won’t be cached.
- If the file is authenticated or secure, it won’t be cached.
- If the HTTP headers specify not to cache the file, then it won’t.
HTML Meta Tags vs HTTP Headers
Expires HTTP Header (HTTP 1.0 protocol)
Cache-Control HTTP Headers (HTTP 1.1 protocol)
The Expires HTTP Header is usefull, but quite limited. That’s why HTTP 1.1 introduced a new set of headers, the Cache-Control Response Headers. Most interesting are:
public: Indicates that the response MAY be cached by any cache, even if it would normally be non-cacheable or cacheable only within a non- shared cache.
private: Indicates that all or part of the response message is intended for a single user and MUST NOT be cached by a shared cache. This allows an origin server to state that the specified parts of theresponse are intended for only one user and are not a valid response for requests by other users. A private (non-shared) cache MAY cache the response.
no-cache: If the no-cache directive does not specify a field-name, then a cache MUST NOT use the response to satisfy a subsequent request without successful revalidation with the origin server. This allows an origin server to prevent caching even by caches that have been configured to return stale responses to client requests.If the no-cache directive does specify one or more field-names, then a cache MAY use the response to satisfy a subsequent request, subject to any other restrictions on caching. However, the specified field-name(s) MUST NOT be sent in the response to a subsequent request without successful revalidation with the origin server. This allows an origin server to prevent the re-use of certain header fields in a response, while still allowing caching of the rest of the response.
max-age: Indicates that the client is willing to accept a response whose age is no greater than the specified time in seconds. Unless max- stale directive is also included, the client is not willing to accept a stale response.
s-maxage: If a response includes an s-maxage directive, then for a shared cache (but not for a private cache), the maximum age specified by this directive overrides the maximum age specified by either the max-age directive or the Expires header. The s-maxage directive also implies the semantics of the proxy-revalidate directive, i.e., that the shared cache must not use the entry after it becomes stale to respond to a subsequent request without first revalidating it with the origin server. The s- maxage directive is always ignored by a private cache.
must-revalidate: When the must-revalidate directive is present in a response received by a cache, that cache MUST NOT use the entry after it becomes stale to respond to asubsequent request without first revalidating it with the origin server.
proxy-revalidate: The proxy-revalidate directive has the same meaning as the must- revalidate directive, except that it does not apply to non-shared user agent caches.
Last-Modified vs ETag
When a cache has a file stored including a Last-Modified header, it can use that to ask the server if the file has changed since the last time it was seen, with an if-Modified-Since request.
HTTP 1.1 introduced ETag. ETags are unique identifiers generated by a server for each file and changed if the file changes. Because the server generates the ETags, this system is more reliable.
Almost all caches support Last-Modified, more and more caches also use ETag.
Adding must-revalidate to the header response in Asp.NET
This is done with the static Content configuration setting in IIS7(.5). There are some settings you should check at the given url.
I just added these lines to my web.config
1 2 3
<staticContent> <clientCache cacheControlCustom="public,must-revalidate" /> </staticContent>
In one of my next posts, I’ll handle the caching and profiles tag. A lot of things in there do not seem to make sense.