Subsections


3.3.1 Multiple Responders

The Multiple responder implements a hybrid website. It is a meta-responder: it enables you to tie together multiple responders into a coherent website, using the filesystem for hierarchical organization. It also gives you site-wide in- and outbound hooks via a "framework" abstraction. The Multiple responder is the most complicated part of httpy to explain in reference, but almost everything is optional, and it is fundamentally intuitive.

Multiple translates URI paths literally to the filesystem, rooting them in root. For example, if root is:

/usr/local/www

Then Multiple would translate a request for:

http://localhost:8080/foo

To the path:

/usr/local/www/foo

3.3.1.1 Responder Discovery

When Multiple is instantiated, it searches the tree under root for responders. If a directory contains a file named responder.py, then Multiple tries to import a responder from that file, and uses that responder to serve all requests for resources at or below that directory. If responder.py defines a class named Responder, then that is used as the responder. Otherwise Multiple uses the module itself. In either case, the responder must provide the IResponder interface, at least implicitly.

So if you define a responder in:

/usr/local/www/foo/responder.py

Then Multiple would route requests for all of the following to that responder:

http://localhost:8080/foo
http://localhost:8080/foo/
http://localhost:8080/foo/bar

There must be at least one responder, associated with the root of the site. If none is defined, then Multiple uses the Static responder.

3.3.1.2 Special Directories

Furthermore, Multiple adds exactly one path to sys.path for each responder it finds. First it looks for a subdirectory named site-packages, then one named lib. The first one found is used.

If a directory contains a subdirectory named __ (double-underscore, referred to as a magic directory), then Multiple will use any responder defined there to serve requests for the parent directory, and the sys.path addition logic uses the magic directory as its base. If both a magic directory and its parent define a responder, then the parent's wins. If the responder comes from the parent, then any magic directory is considered for inclusion in sys.path, after site-packages and lib.

3.3.1.3 API Additions

Multiple adds the following data attributes to each responder as it is discovered. Existing attributes are not overriden. For class responders, these are added before instantiation, so they are available during construction.

name value
__ the filesystem path of the responder's magic directory, or None if it does not exist [that's two underscores]
pkg the path added to sys.path for this responder
root the responder's filesystem path
site___ the filesystem path of the magic directory in the publishing root, or None if it does not exist [that's three underscores]
site_root the filesystem path of the publishing root
path the URI path below which requests will go to this responder

3.3.1.4 Frameworks

Responders are mini Python applications scattered about your site hierarchy. In order to unify these responders into a coherent website, Multiple provides a framework abstraction. Multiple looks for a file named framework.py in root and in root's magic directory, in that order. The first found is used. Frameworks have no required API, but they may hook into the HTTP transaction process by defining some or all of the following callables. These are listed in the order they are called.

get_responder( request)
request is an httpy.Request object. This routine must return a provider of IResponder. The default implementation chooses a responder based on the path attribute as described above. It then removes that portion of the path from Request.path, ensuring that Request.path is never less than '/'. get_responder checks that the paths named in root, __ and pkg still exist, and raises 500 Internal Server Error otherwise. If the client is requesting a resource in __ or pkg, then get_responder raises 403 Forbidden.

wrap_request( responder, request)
responder is the result of the call to get_responder; request is the same Request object. This routine may return any object that is meaningful to responder's respond routine. It is not implemented by default.

unwrap_response( response, responder, request)
response is the object raised by responder.respond. Note that this object must be a subclass of httpy.Response, or it will be interpreted as a 500 Internal Server Error. request is the same Request object. This method is not implemented by default.

stop( )
This method is called when the application terminates normally. It is not implemented by default.

Note that because request is passed to each hook, and then discarded following the transaction, you can safely store state there between hooks.

As with responders, Multiple adds the following data attributes to your framework if they are not already present. If your framework is a class, these are added immediately before instantiation.

name value
__ the filesystem path of the site's magic directory [that's two underscores]
root the filesystem path of the site's publishing root
httpy is Zeta software. It is copyright © 2006 by Chad Whitacre, and is offered free of charge, warranty, and restrictions.