This is about a web app that serves images. Since the same request will always return the same image, I want the accessing browsers to cache the images as aggressively as possible. I pretty much want to tell the browser
Here's your image. Go ahead and keep it; it's really not going to change for the next couple of days. No need to come back. Really. I promise.
I do, so far, set
Cache-Control: public, max-age=86400 Last-Modified: (some time ago) Expires: (two days from now)
and of course return a 304 not modified
if the request has the appropriate If-Modified-Since
header.
Is there anything else I can do (or anything I should do differently) to get my message across to the browsers?
The app is hosted on the Google App Engine, in case that matters.
There is a very important value on cache header that you have not mentioned here:
Read this article about this topic (and search for more):
http://www.rdlt.com/cache-control-post-check-pre-check.html
I don't know that it'll help beyond what solutions others have offered, but you could use the HTML5 offline web apps facilities to more explicitly ask the browser to store a local copy.
A few days cache age is very low. You should set it to one year or even more. Of course this might raise problems when the image actually changes but you can solve that by adding a version number to the image and changing the page that references the image to include the path to the new image.
I wrote more about web application caching here: http://patchlog.com/web/7-methods-to-cache-web-applications/
You may be interested in checking out the following Google Code article:
In a nutshell, all modern browsers should be able to cache your images appropriately as instructed, with those HTTP headers.
Try .htaccess like
You could add an
ETag
representation for each image and then compare it to theIf-None-Match
header on inbound requests (see "Why isn’t my custom delivered image caching in the browser?"). This is redundant when using the preferredLast-Modified
header and it's just another way to say 304 anyway. (I think GAE does this automatically for static files, not sure though.)Gravatar sets very old
Last-Modified
dates -- the default seems to be "Wed, 11 Jan 1984 08:00:00 GMT". The 5-minute expiration causes browsers to check for updated images frequently. In other words, I think they're inviting 304s, not trying to convince browsers to just use the local cache. Their headers look like this:The big difference is the expiration time -- you want two days, they want five minutes. So if you want browsers to just use the cached image for 48 hours, do what you're doing, only set
Cache-Control: max-age=172800
(86400 is 24 hours).