WSGI

The goal of this example is to show you how to use WSGIResource , another existing Resource subclass, to serve WSGI applications in a Twisted Web server.

Note that WSGIResource is a multithreaded WSGI container. Like any other WSGI container, you can’t do anything asynchronous in your WSGI applications, even though this is a Twisted WSGI container.

The first new thing in this example is the import of WSGIResource :

from twisted.web.wsgi import WSGIResource

Nothing too surprising there. We still need one of the other usual suspects, too:

from twisted.internet import reactor

You’ll see why in a minute. Next, we need a WSGI application. Here’s a really simple one just to get things going:

def application(environ, start_response):
    start_response('200 OK', [('Content-type', 'text/plain')])
    return [b'Hello, world!']

If this doesn’t make sense to you, take a look at one of these fine tutorials . Otherwise, or once you’re done with that, the next step is to create a WSGIResource instance, as this is going to be another rpy script example:

resource = WSGIResource(reactor, reactor.getThreadPool(), application)

Let’s dwell on this line for a minute. The first parameter passed to WSGIResource is the reactor. Despite the fact that the reactor is global and any code that wants it can always just import it (as, in fact, this rpy script simply does itself), passing it around as a parameter leaves the door open for certain future possibilities - for example, having more than one reactor. There are also testing implications. Consider how much easier it is to unit test a function that accepts a reactor - perhaps a mock reactor specially constructed to make your tests easy to write - rather than importing the real global reactor. That’s why WSGIResource requires you to pass the reactor to it.

The second parameter passed to WSGIResource is a ThreadPool . WSGIResource uses this to actually call the application object passed in to it. To keep this example short, we’re passing in the reactor’s internal threadpool here, letting us skip its creation and shutdown-time destruction. For finer control over how many WSGI requests are served in parallel, you may want to create your own thread pool to use with your WSGIResource , but for simple testing, using the reactor’s is fine.

The final argument is the application object. This is pretty typical of how WSGI containers work.

The example, sans interruption:

from twisted.web.wsgi import WSGIResource
from twisted.internet import reactor

def application(environ, start_response):
    start_response('200 OK', [('Content-type', 'text/plain')])
    return [b'Hello, world!']

resource = WSGIResource(reactor, reactor.getThreadPool(), application)

Up to the point where the WSGIResource instance defined here exists in the resource hierarchy, the normal resource traversal rules apply: getChild will be called to handle each segment. Once the WSGIResource is encountered, though, that process stops and all further URL handling is the responsibility of the WSGI application. This application does nothing with the URL, though, so you won’t be able to tell that.

Oh, and as was the case with the first static file example, there’s also a command line option you can use to avoid a lot of this. If you just put the above application function, without all of the WSGIResource stuff, into a file, say, foo.py , then you can launch a roughly equivalent server like this:

$ twistd -n web --wsgi foo.application

Previous topic

Access Logging

Next topic

HTTP Authentication

This Page