Web Cache

Forcing browsers to revalidate static content in IIS – Asp.NET

Web CacheHow 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).

Common scenarios:

  • 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

Are being put in the HEAD section of a document. It’s easy to use but only browsers will look at it. Proxy caches never look into the HTML of a document, so they will ignore those meta tags. Many use the Pragma: no-cache meta tag without knowing that most proxy/shared caches will ignore it. HTTP headers give you all the control you need. They aren’t as simple to use as Meta Tags, but they will always be followed by proxy caches and browser caches.
HTTP Headers appear before the HTML.

Controlling freshness

Expires HTTP Header (HTTP 1.0 protocol)

Tells all caches how long the file is fresh. After that time, the cache will always check the origin to see if the file has changed. Only a GMT HTTP Date is valid, everything else will be seen as in the past and uncacheable. If a response includes a Cache-Control field with the max-age directive, that directive overrides the Expires field.
Format : Expires = “Expires” “:” HTTP-date
Example: Expires: Thu, 01 Dec 1994 16:00:00 GMT

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.

Some usefull link:
HTTP/1.0
HTTP/1.1
Caching tutorial
Caching Tutorial for Web Authors and Webmasters

3 thoughts on “Forcing browsers to revalidate static content in IIS – Asp.NET

  1. Bart

    The solution mentioned works nicely on Chrome and FF, IE needs some extra work (surprise…),
    see http://stackoverflow.com/questions/5017454/make-ie-to-cache-resources-but-always-revalidate

    So the correct setting for web.config is:

    You might need an extra step when there are clients around that have an old version cached
    from before you added these new caching settings. Just add “?forceUpdate” or something like
    that to the URL of the swf. See http://www.newtriks.com/2008/08/07/prevent-a-swf-from-caching-in-browser/

    Nice to know: clicking on the addressbar in IE and then pressing will never cause a
    server request when the page is already in the cache. Clicking the refresh button will…

    For PHP you can add the headers through the .htaccess file by adding something like:

    Header set Cache-Control “public, must-revalidate”
    Header set Expires “Sat, 01 Jan 2011 00:00:00 GMT”

    or you can do it in an individual PHP file by adding following lines at the top of the PHP file:

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>