WSGI demystified

One of the most exciting things to come out of PyCon 2005 was the WSGI spec. WSGI is a standard that specifies a common interface for Python Web frameworks.

For a full understanding of the interface there’s no substitute for reading the spec. But in my experience, many people are too busy to read specs. So here’s an executive summary of how WSGI works.

WSGI actually specifies two interfaces, one for the server to talk to the application, and one for the application to talk to the server. For the server to talk to the application, it calls a function (which the application supplies) which should accept two arguments, environ and start_response. The environ argument will be a dictionary containing the HTTP environment (including variables like REQUEST_METHOD and PATH_INFO), and the start_response argument will be a function.

For the application to talk to the server, it should first prepare any headers it wants to send, then call the start_response function that it was handed, with a status code and a set of headers. Then it should prepare the body of the response as a list of strings. (An iterator can be used instead of a list). To pass the response body back to the server, it should simply return it.

Once the server receives the list (or iterator) from the application, it simply sends those strings, one at a time, to the client (i.e., the user’s Web browser).

Got that? Here’s what it looks like in Python code:

def simple_app(environ, start_response):
    status = '200 OK'
    response_headers = [('Content-type','text/plain')]
    start_response(status, response_headers)
    return ['Hello world!n']

There you have it — the WSGI interface in a nutshell. The server invokes the application by calling a function, then sends the function’s return value(s), one at a time, back to the client. Pretty simple, eh?

There are a lot of subtleties that I haven’t covered, of course, such as the contents of the environ dictionary, or the fact that the application doesn’t have to be a function, but can be any callable object (such as a class). To grasp those, you’ll have to read the spec. But just understanding the concepts presented here is a good jumping-off point to make the spec a lot less mysterious.

Update, 2005-08-15: There’s a simpler way to write my simple_app example: as a generator. In fact, that’s probably a simpler way to write any WSGI app. Instead of building a list of strings and returning the list, simply use yield statements, thus:

def simple_app(environ, start_response):
    status = '200 OK'
    response_headers = [('Content-type','text/plain')]
    start_response(status, response_headers)
    yield 'Hello world!n'
    yield 'Second line goes heren'

Simple, eh?

Comments are closed.