[Web-SIG] PEP 444 (aka Web3)

jason kirtland jek at discorporate.us
Thu Sep 16 16:41:14 CEST 2010

On Thu, Sep 16, 2010 at 5:48 AM, Tarek Ziadé <ziade.tarek at gmail.com> wrote:
> On Thu, Sep 16, 2010 at 2:40 PM, Armin Ronacher
> <armin.ronacher at active-4.com> wrote:
>> Hi,
>> On 9/16/10 2:38 PM, Tarek Ziadé wrote:
>>> True... I don't know what's the best option here.. I guess we need to
>>> provide all children so one may visit the whole graph.
>> Another gripe I have with WSGI is that if you attempt to combine
>> applications together with a dispatcher middleware, the inner application
>> does not know the URL of the outer one.  It's SCRIPT_NAME points to itself
>> and there is no ORIGINAL_SCRIPT_NAME.
>>> Do you have a list of middleware that does this ?
>> I know that Paste has a cascade middleware and I think it also has one that
>> maps applications to specific prefixes.
> Ah yes, the composite thing IIRC - I didn't know this was a middleware.
> Should those be middlewares ? ISTM that they should in the front of
> the stack instead, and that a stack of middleware should be dedicated
> to a single application -- for the griefs you mentioned and probably
> other problems.
> I mean, one call does not visit several application, and this is some
> kind of dynamic rewriting of the stack..
> Another possibility would be to define a
> "get_application(environ=None)" method so the middleware is able to
> return the right app at the right moment

The 'pegboard' middleware composes a result out of an arbitrary graph
of WSGI apps, with one request visiting many applications. The graph
can be built at runtime in application code, so it would be very
difficult to report all of the '.app's applicable for a given environ
until after the request.  Also, it is quite reasonable in practice to
have middleware both in front of such a composer and also in the
stacks of the apps it composes.

A concern with "should have .app" is that a single closure middleware
breaks the chain.  For example:

   def unproxy(app):
       def middleware(environ):
           environ['HTTP_HOST'] = environ['HTTP_X_FORWARDED_FOR_HOST']
           return app(environ)
       return middleware

For the use case of "original_app = self.app.app.application.app",
I've had great success with a pattern I first saw in Zine: applying
the middleware internally to the application instance, not wrapping
the instance.  It seems fairly robust against closures and middleware
that can't or won't play along with .app.  Unlike .app, this isn't
generically traversable, but in cases where I need this kind of
cross-talk between middleware/apps I haven't had any problems getting
the right instances into scope at runtime.

    class MyApp:
        def apply_middleware(self, factory, *args, **kw):
            self.dispatch_wsgi = factory(self.dispatch_wsgi, *args, **kw)

        def dispatch_wsgi(self, environ):
            return [b'hi'], b'200 OK', [(b'Content-type', b'text/plain')]

        def __call__(self, environ):
            return self.dispatch_wsgi(environ)

    app = MyApp()
    app.apply_middleware(StaticContent, 'static/')

More information about the Web-SIG mailing list