Introduction to WSGI

The Web Server Gateway Interface (WSGI) is a universal interface between web servers and web applications for Python. Universal means there is no more need to design your application for a specific API interface of a web server like CGI, FastCGI, mod_python, etc. - implementing WSGI support in your application gives you opportunity to use it with any web server which in it’s turn has WSGI support.

I highly recommend reading PEP333 with full specification, here is just a bare minimum:

  • the WSGI interface has two sides: the server/gateway and the application side; beside this strict distinction there are so called “middleware” components which implement server and application sides at the same time;
  • WSGI application is a callable object (a function, method, class, or an instance with a __call__ method) that accepts two positional arguments: WSGI environment variables and a callable with two required positional arguments which starts the response;
  • the server side invokes the callable object which returns response.

Basic example

Here is a simple example.

from urlparse import parse_qs

class Greetings:
def __call__(self, environ, start_response):
params = parse_qs(environ.get('QUERY_STRING'))
name = 'Alex'
if 'name' in params:
name = params.get('name')[0]
start_response('200 Ok', [('Content-type', 'text/plain')])
return ['My name is {0}'.format(name)]

This application greets someone called Alex (me actually) or a person whose name is specified via url. The Greetings class is our callable object with two required positional arguments which is invoked by a server side. Pay attention to the fact that there are other variants of implementing a callable object: we could create a class with __iter__ method which would yield the result, or, simply, create a function without any classes. Regardless of your choice of a callable object it’s first parameter is an environment dictionary object. As the second parameter it accepts a callable which starts response and is invoked with two parameters: status string and a list of tuples with headers information.

In order to test this application we can use any web server with WSGI support. For tests purposes there is a wsgiref module from standard Python library. At the end of our file:

if __name__ == "__main__":
from wsgiref.simple_server import make_server
httpd = make_server('', 8005, Greetings())

After starting the app and pointing your browser to http://localhost:8005/?name=John you will see a request log in the console.

$ python - - [01/Mar/2013 21:36:40] "GET /?name=Jonh HTTP/1.1" 200 15

What is a middleware?

Middleware applications play the role of a server for their contained applications and, at the same time, look like an application to their containing server. They can be used to:

  • routing to a different URL based on environ parameters;
  • logging;
  • handling exceptions;
  • perform any kind of preprocess/postprocess operations.

Middleware application acts like a wrapper around another application, which in it’s turn can could be a middleware for another application and so on. In this case you create a so called “middleware stack”. Let’s have a look at the example - our application will add to the result of it’s underlying application a string with information about the size of the result.

class ResultMiddlware:
def __init__(self, app): = app

def __call__(self, environ, start_response):
# the size of the result returned by
size = 0

# call the application
appiter =, start_response)
for r in appiter:
size += len(r)
yield r

yield '\n\nResult length: ' + str(size)

# the application might define a close method
# which must be called
if hasattr(appiter, 'close'):

And change the invoking part:

if __name__ == "__main__":
from wsgiref.simple_server import make_server
application = ResultMiddlware(Greetings())
httpd = make_server('', 8005, application)


WSGI is no doubt a great piece of technology which brings some standardization to a zoo of existing technologies in Python web area. But as it is rightly mentioned in PEP333 WSGI is a tool for frameworks and server developers, and is not intended to directly support application developers. Thus consider using existing libraries and frameworks with WSGI support for your applications. Have a look at Werkzeug and Flask, it’s a good point to start from (or maybe stop at).