Download Install Tutorial Docs FAQ Tools WikiLicense Team IRC Planet Involvement Shop Book

WSGI

WSGI is a specification for connecting HTTP servers (like Apache, IIS, or CherryPy's builtin HTTP server) with web applications and frameworks (like CherryPy), so you can mix and match them. We'll start by discussing how to connect CherryPy to various HTTP servers, which is rather mundane. The interesting parts come later, where we play with answers to the question, what is an "application"?

WSGI Servers and CherryPy

CherryPy has had support for WSGI since at least 2004; in June 2005, Peter Hunt added a WSGI HTTP server to CherryPy, and in February 2006, that server became the default. So currently, you don't have to do anything to "enable WSGI"--CherryPy takes care of it for you, using configuration entries you supply like "server.socket_port" and "server.thread_pool".

If you want to use an HTTP server other than the default, you can probably find a WSGI adapter for it on the 'Net somewhere. Here are some of the ones we know about and have documented. Any good search engine will help you find others.

Using CherryPy as a WSGI application

Whenever you create a CherryPy application, you're creating a WSGI application, probably without even knowing it. That's because each cherrypy.Application object is usable as a WSGI application automatically--just by calling it. Now, you may not even know that you have a cherrypy.Application, but you do if you've used cherrypy.tree.mount:

>>> import cherrypy
>>> class Root:
...     def index(self):
...         return "Hello, World!"
...     index.exposed = True
...     
>>> cherrypy.tree.mount(Root(), "/users/robvious/")
<cherrypy._cptree.Application object at 0x010A1FD0>
>>> _.root, _.script_name
(<__main__.Root instance at 0x011E65A8>, '/users/robvious')

As you can see, not only has tree.mount created an Application for you, but it's attached your root object and script_name to it, and then returned it to you (so you can do other things to it before starting up the server, if you desire).

If you want to use your CherryPy application with someone else's WSGI server-or-gateway, just hand your Application object to it wherever that foreign API asks for the "WSGI application object" or "WSGI callable".

Using CherryPy as a WSGI dispatcher

If you have more than one WSGI application that you want to run on the same server, then you need some sort of WSGI dispatcher that picks the correct application based on the URL. Some WSGI servers (like CherryPy's) have this feature built in. Most do not; instead, they call a WSGI dispatcher.

If you are running multiple CherryPy applications via WSGI, then you can use the cherrypy.tree object as a WSGI dispatcher. Hand it to the WSGI server-or-gateway wherever that foreign API asks for the "WSGI application object" or "WSGI callable", and it will select the correct CherryPy application based on the URL. For example, if you mounted RootA at "/" and RootB at "/users/robvious", then a request for the resource at "/admin" will be dispatched to the RootA app and a request for "/users/robvious/about.htm" will be dispatched to the RootB app.

You can also use cherrypy.tree to dispatch to other, non-CherryPy, WSGI applications. Instead of tree.mount, call tree.graft(wsgiapp, script_name). The same Tree can dispatch to both CherryPy and foreign WSGI apps simultaneously.

Using WSGI middleware with CherryPy

You probably read the previous section and didn't even notice that a "WSGI dispatcher" is a "WSGI application". But it is; and it is this re-use of the exact same interface that makes WSGI doubly powerful.

"WSGI middleware" refers to another benefit of WSGI; not only are WSGI applications mountable (so multiple apps can respond at different URL's), they are also chainable (so a request at a single URL might pass through several WSGI apps). When a WSGI application is designed to receive a request, perform some work, and then hand off the request to another WSGI application, that "app in the middle" (between the WSGI server and the next WSGI app) is called middleware. The dispatchers we mentioned above are examples of middleware, but there are also WSGI middleware applications for handling sessions, gzip, exception debugging, and many other needs.

As long as CherryPy has had WSGI functionality, you could use middleware with CherryPy: instead of handing CherryPy's WSGI application to the server, you would give it to the middleware (which wraps it) and then provide the middleware to the server instead.

However, wrapping middleware by hand can be tedious. CherryPy 3 allows you to declare middleware in your config file like so:

[/]
wsgi.pipeline = [('evalexc', paste.evalexception.EvalException)],
wsgi.evalexc.global_conf = {}
wsgi.evalexc.xmlhttp_key = "_xml"

The 'pipeline' defines an ordered sequence of WSGI middleware classes; when your cherrypy.Application object is called via WSGI, each class in the pipeline is instantiated, passing the 'next app' and the appropriate config. Note in the example above that the config for the 'evalexc' middleware is all in the 'wsgi.evalexc' namespace.

Using CherryPy Tools with WSGI apps

When you graft foreign WSGI apps onto cherrypy.tree, they exist outside of the CherryPy request process, which means they won't benefit from any of CherryPy's builtin Tools. This can be remedied by hosting the foreign app inside the CherryPy request; tools.wsgiapp does this. Just add it to your config like so:

[/another/path]
tools.wsgiapp.on = True
tools.wsgiapp.app = nextapp

Since it's a HandlerTool?, you can also use it in code like this:

class Another:
    path = cherrypy.tools.wsgiapp.handler(nextapp)

WSGI Environ

If your CherryPy application runs within a WSGI context and is wrapped in WSGI middlewares it can retrieve valus of the environ dictionary described by the PEP 333 as follow:

cherrypy.request.wsgi_environ

Note also that modification your application will make to that dictionary will then populated back to any wrapped WSGI middleware.

See also

Visual model

http://www.cherrypy.org/attachment/wiki/WSGI/cp3wsgi.gif?format=raw

Older versions

2.2

CherryPy 2.2 didn't have an Application object, and cherrypy.tree wasn't callable as a WSGI application, either. Instead, there was a single cherrypy._cpwsgi.wsgiApp function which did what the Tree does now (CherryPy apps only; not other WSGI apps or middleware).

It is possible to mount non-CP WSGI applications on the cherrypy.tree using cherrypy.lib.cptools.WSGIApp. You can also run CP in conjunction with other WSGI apps on a third-party server.

2.1

The builtin CherryPy WSGI server didn't have a builtin dispatcher; it only took one WSGI application as an argument.

Attachments

Hosted by WebFaction

Log in as guest/cpguest to create tickets