[Web-SIG] Pre-PEP: Python Web Container Interface v1.0

Phillip J. Eby pje at telecommunity.com
Wed Dec 10 13:17:36 EST 2003


At 04:48 PM 12/10/03 +0100, Paul Boddie wrote:
>Gregory (Grisha) Trubetskoy wrote:
> >
> > The approach this spec takes is modeled after CGI, which was designed with
> > shell scripts in mind and condenses things down to the UNIX primitives of
> > stdin, stdout, stderr, environ (and cwd).
>
>I would have thought that this kind of interface would have been more
>suitable between the environment and the container, or possibly between
>components within the container.

I'm guessing that for mod_python, the proposed interface isn't as suitable, 
doubtless prompting some of Grisha's concerns.  From a mod_python point of 
view, the proposed interface is "lossy", at least from a performance point 
of view, and probably also from a power/flexibility point of view.

But the flip side is that if this "lossy" interface were available in 
mod_python, it would actually bring many more users to mod_python, since 
they'd be able to use a wider variety of frameworks with it.  If those 
users then came to want things that weren't available through the narrow 
"runCGI" interface, then they could consider doing additional work to use 
mod_python's native interface.

I know that I, for one, would be more likely to experiment with other 
mod_python capabilities once I had my "foot in the door" via the simple 
interface.



> > On the surface this appears fine, but consider setting an HTTP header.
> > Headers do not fit into the above-mentioned primitives, so CGI requires
> > the application to send them to stdout. Writing headers to stdout is much
> > more cumbersome than passing them in a mapping object of some sort.
>
>And I can imagine that for many applications in many of the current
>frameworks, they would need some kind of "insulating wrapper" to comply with
>this interface. Certainly, I don't recall Webware, mod_python, Twisted or
>Zope applications sending headers to the same output stream as the data (or
>even using an output stream for the headers at all).

Zope definitely does, and from Andrew's comments, so does Quixote.  Twisted 
is a web server, so it won't, but I believe it already has a CGI interface 
for running external programs, that could be used for this purpose 
(presumably by running the application in a separate thread).

Here are example wrappers for Zope 2 and Zope 3 (untested, but based on 
existing code I use in production (Z2) and dev (Z3)):

class Zope2App:

     def __init__(self, modulename):
         self.moduleToPublish = modulename

     def runCGI(self,input,output,errors,environ):
         from ZPublisher.Publish import publish_module
         publish_module(
             self.moduleToPublish, stdin=input, stdout=output,
             stderr=errors, environ=environ
         )

class Zope3App:

     _browser_methods = 'GET','HEAD','POST

     def __init__(self, publication):
         self.policy = publication

     def runCGI(self,input,output,errors,environ):

         from zope.publisher import http, browser, xmlrpc, publish

         method = environ.get('REQUEST_METHOD', 'GET').upper()

         if method in self._browser_methods:
             if (method == 'POST' and
                 env.get('CONTENT_TYPE', '').lower().startswith('text/xml')
                 ):
                 request_type = xmlrpc.XMLRPCRequest
             else:
                 request_type = browser.BrowserRequest
         else:
             request_type = http.HTTPRequest

         request = request_type(input, output, environ)

         request.setPublication(self.policy)
         publish.publish(request)



>This pre-PEP seems to serve an important purpose: it attempts to make a
>certain part of the Web request handling "stack" explicit. I'd certainly be
>interested in trying to make other parts of that "stack" more obvious, too.
>For example, it would be nice to consider the resolution of requests
>according to information contained within them, and the dispatching of such
>requests to resources. Right now, each framework seems to have its own
>ideology which states that requests using particular paths must get resolved
>in a particular way - it would be great if an API appeared that let
>developers rewire frameworks without resorting to external hacks to get the
>desired behaviour.

The proposed interface actually allows that too; in fact, it's why environ 
must be modifiable by the "app".  It should be easy to create a "router" 
app that accepts a runCGI call and forwards it to other application objects 
implementing the interface.  Thus, multiple frameworks, apps, or other 
objects can be "mounted" within a container even at a single virtual "mount 
point".




More information about the Web-SIG mailing list