Forums

Expires Header

Hey there, is there a way to dynamically set an expires header on content (scripts and images) via Flask/Python?

A "far future expires header" should reduce traffic and increase loading speed. And to deploy a new version of a file (e.g. script) one would simply add a version number and use that on the page (so this new version gets cached).

http://developer.yahoo.com/blogs/ydn/high-performance-sites-rule-3-add-expires-header-7181.html

Thanks, Mike

Firstly, you should use care with long Expires headers, since you're making an absolute guarantee to the client that the content will not change for the time you specify. Personally I'd prefer to support conditional requests and ETags - these still require a request round trip, but don't need to transfer any content in the case that the resource hasn't changed. Note that if you do use long Expires times then when the resources do change, you'll need to change their URL, which is a pain.

There are two cases for serving content from PA - content returned directly from your Flask script and files in directories specified by the Static Files section of the Web tab on your Dashboard.

In the former case, you can easily write some Python code to add an appropriate Expires header. There may be an extension or snippet that can help you, but it's really easy to do manually. For example, the Flask app below returns a fixed response and indicates to the browser it will expire in 100 days:

import datetime
import flask

app = flask.Flask(__name__)

@app.route('/')
def hello():
    expiry_time = datetime.datetime.utcnow() + datetime.timedelta(100)
    response = flask.make_response("Hello from flask!")
    response.mimetype = "text/plain"
    response.headers["Expires"] = expiry_time.strftime("%a, %d %b %Y %H:%M:%S GMT")
    return response

Note that the format of the date string in the Expires header is defined in the RFC 2616.

Anything you declare as static content and allow PA to serve on your behalf gets served directly by nginx, and I suspect most of the time you can rely on it to get things right. It probably won't use an Expires header, but it should support conditional requests and ETags. If you really want to support Expires headers on these files, you'll probably have to stop using PA's static file support and serve everything through Flask.

EDIT

As an aside, nginx does have a module for setting an Expires header, so it's possible that the PA devs would consider adding a feature to allow users to specify a custom expiry time for their static content. However, I wouldn't have thought this would be regarded as particularly high priority, especially given the stability improvements underway at present.

Thanks, as always, Cartroo :-)

I don't think there's a Flask extension to set expiry headers automatically (though I'm not a Flask expert and might be missing something) -- so I agree, your way is probably best. With a bit of work perhaps one could write a decorator to add to view functions that were meant to have a long expiry date.

Agreed, again, we probably won't expose the expiry stuff in nginx (or uwsgi, which also supports it) in the short term. But I'll add it to the list.

Thank you Cartroo and Giles.I am overwhelmed how quick the reaction was, I didn't expect that. Thanks again! I will keep your points in mind Catroo.