Hi, I have been looking at WSGI for only a few weeks, but had some ideas similar (I hope) to what is being discussed that I'll put down here. I'm new to this so I beg your indulgence if this is heading down the wrong track or wildly offtopic :)
It seems to me that a major drawback of WSGI middleware that is preventing flexible configuration/chain paths is that the application to be run has to be determined at init time. It is much flexible if we were able to specify what application to run and configuration information at call time - the middleware would be able to approximate a service of sorts. An example: I have an WSGI application simulating a file-server, and I wish to authenticate users and gzip served files where application. In a middleware chain it would probably work out to be: application = authmiddleware(gzipmiddleware(fileserverapp)) For example, a simplified gzipping middleware consists of: class gzipmiddleware: def __init__(self, application, configparam): self._application = application .... def __call__(self, environ, start_response): do start_response call self._application(environ, start_response) as iterable get each iterator output and zip and yield it. and the fileserverapp, with doGET, doPUT, doPOST subapplications that do the actual processing: def fileserverapp(environ, start_response): if(GET): return doGET(environ, start_response) if(POST): return doPOST(environ, start_response) if(PUT): return doPUT(environ, start_response) Now, the application-server is specific on what it wishes to gzip (usually only on GET or POST entity responses and only if the mimetype allows it). But this level of logic is not to be placed in the gzipping middleware, since its configurable on the webserver. So in order to tell the gzipmiddleware whether to gzip or not: (a) Add a key in environ, say environ[gzip.do_gzip] = True or False to inform the gzipmiddleware to do gzip or not. This does mean that gzipmiddleware remains in the chain, irregardless of whether it is needed or not. (b) Have chain application = authmiddleware(fileserverapp) Use Handlers, as Ian suggested, and in the fileserverapp's init: Handlers( IfTest(method=GET,MimeOkForGzip=True, RunApp=gzipmiddleware(doGET)), IfTest(method=GET,MimeOkForGzip=False, RunApp=doGET), IfTest(method=POST,MimeOkForGzip=True, RunApp=gzipmiddleware(doPOST)), IfTest(method=POST,MimeOkForGzip=False, RunApp=doPOST), IfTest(method=PUT, RunApp=doPOST) ) (c) Make gzipmiddleware a service in the following form: class gzipmiddleware: def __init__(self, application=None, configparam=None): self._application = application .... def __call__(self, environ, start_response, application=None, configparam=None): if application and configparam is specified, use them instead of the init values do start_response call self._application(environ, start_response) as iterable get each iterator output and zip and yield it. This "middleware" is still compatible with PEP-333, but can also be used as: #on main application initialization, create a gzipservice and put it in environ without #specifying application or configparams for init(): environ['service.gzip'] = gzipmiddleware() Modify fileserverapp to: def fileserverapp(environ, start_response): if(GET): if(mimetype ok for gzip): gzipservice = environ['service.gzip'] return gzipservice(environ, start_response, doGET, gzipconfigparams) else: return doGET(environ, start_response) if(POST): if(mimetype ok for gzip): gzipservice = environ['service.gzip'] return gzipservice(environ, start_response, doPOST, gzipconfigparams) else: return doPOST(environ, start_response) if(PUT): doPUT(environ, start_response) The main difference here is that you don't have to initialize full application chains for each possible middleware-path for the request. This would be very useful if you had many middleware in the chain with many permutations as to which middleware are needed You could also instead put a service factory object into environ, it will return the gzipmiddleware object as a service if already exist, otherwise it will create it and then return it. _______________________________________________ Web-SIG mailing list Web-SIG@python.org Web SIG: http://www.python.org/sigs/web-sig Unsubscribe: http://mail.python.org/mailman/options/web-sig/archive%40mail-archive.com