StreamHacker Weotta be Hacking

10Jan/105

Far Future Expires Header with django-storages S3Storage

One way to decrease your site's load time is to set a far future Expires header on all your static content. This doesn't help first-time visitors, but can greatly improve the experience of returning visitors. And you get to decrease your bandwidth needs at the same time, because all your static content will be cached by their browser.

S3

weotta puts all of its awesome plan images in Amazon's S3 using django-storages S3Storage backend, which by default does not set any Expires header. To remedy this, I set AWS_HEADERS in settings.py like so

from datetime import date, timedelta
tenyrs = date.today() + timedelta(days=365*10)
# Expires 10 years in the future at 8PM GMT
AWS_HEADERS = {
	'Expires': tenyrs.strftime('%a, %d %b %Y 20:00:00 GMT')
}

Now every uploaded file gets an Expires header set to 10 years in the future.

upload_to

One potential drawback to using a far future Expires header is that if you change the file content without also changing the file name, no one will notice because they'll keep using the old cached version of the file. Luckily, Django makes it easy to create (mostly) unique new file names by letting you include strftime formatting codes in a FileField or ImageField upload_to path, such as upload_to='images/%Y/%m/%d'. This way, every uploaded file automatically gets stored by date, which means it would take some deliberate effort to change the contents of a file without also changing the file name.

  • http://www.gnegg.ch/ Philip Hofstetter

    According to RFC 2616 (HTTP), section 14.21, you should not set Expires more than a year into the future.

    Considering that invalid dates will be treated as “already expired”, it might even be very unwise to set it to 10 years from now:

    “To mark a response as “never expires,” an origin server sends an Expires date approximately one year from the time the response is sent. HTTP/1.1 servers SHOULD NOT send Expires dates more than one year in the future.”

    Philip

  • http://www.gnegg.ch Philip Hofstetter

    According to RFC 2616 (HTTP), section 14.21, you should not set Expires more than a year into the future.

    Considering that invalid dates will be treated as “already expired”, it might even be very unwise to set it to 10 years from now:

    “To mark a response as “never expires,” an origin server sends an Expires date approximately one year from the time the response is sent. HTTP/1.1 servers SHOULD NOT send Expires dates more than one year in the future.”

    Philip

  • http://streamhacker.com/ Jacob Perkins

    Thanks Philip, I didn’t know about that. Though apparently I’m not the only one since most of the recommendations I’ve read say to use access time + 10 years. Or for nginx, to set expires to max, which translates to the year 2037.

  • Jacob

    Thanks Philip, I didn’t know about that. Though apparently I’m not the only one since most of the recommendations I’ve read say to use access time + 10 years. Or for nginx, to set expires to max, which translates to the year 2037.

  • avances123

    Hi, I am seeing that ETag causes this post not to work. Can you confirm?

%d bloggers like this: