[Web-SIG] Standardized configuration
Phillip J. Eby
pje at telecommunity.com
Sun Jul 17 20:23:46 CEST 2005
At 03:28 AM 7/17/2005 -0500, Ian Bicking wrote:
>Phillip J. Eby wrote:
>>What I think you actually need is a way to create WSGI application
>>objects with a "context" object. The "context" object would have a
>>method like "get_service(name)", and if it didn't find the service, it
>>would ask its parent context, and so on, until there's no parent context
>>to get it from. The web server would provide a way to configure a root
>>or default context.
>
>I guess I'm treating the request environment as that context. I don't
>really see the problem with that...?
It puts a layer in the request call stack for each service you want to
offer, versus *no* layers for an arbitrary number of services. It adds
work to every request to put stuff into the environment, then take it out
again, versus just getting what you want in the first place.
>In many cases, the middleware is modifying or watching the application's
>output. For instance, catching a 401 and turning that into the
>appropriate login -- which might mean producing a 401, a redirect, a login
>page via internal redirect, or whatever.
And that would be legitimate middleware, except I don't think that's what
you really want for that use case. What you want is an "authentication
service" that you just call to say, "I need a login" and get the login
information from, and return its return value so that it does
start_response for you and sends the right output.
The difference is obliviousness; if you want to *wrap* an application not
written to use WSGI services, then it makes sense to make it
middleware. If you're writing a new application, just have it use
components instead of mocking up a 401 just so you can use the existing
middleware.
Notice, by the way, that it's trivial to create middleware that detects the
401 and then *invokes the service*. So, it's more reusable to make
services be services, and middleware be wrappers to apply services to
oblivious applications.
>I guess you could make one Uber Middleware that could handle the services'
>needs to rewrite output, watch for errors and finalize resources, etc.
Um, it's called a library of functions. :) WSGI was designed to make it
easy to use library calls to do stuff. If you don't need the
obliviousness, then library calls (or service calls) are the Obvious Way To
Do It.
> This isn't unreasonable, and I've kind of expected one to evolve at
> some point. But you'll have to say more to get me to see how "services"
> is a better way to manage this.
I'm saying that middleware can use services, and applications can use
services. Making applications *have to* use middleware in order to use the
services is wasteful of both computer time and developer brainpower. Just
let them use services directly when the situation calls for it, and you can
always write middleware to use the services when you encounter the
occasional (and ever-rarer with time) oblivious application.
>>Really, the only stuff that actually needs to be middleware, is stuff
>>that wraps an *oblivious* application; i.e., the application doesn't know
>>it's there. If it's a service the application uses, then it makes more
>>sense to create a service management mechanism for configuration and
>>deployment of WSGI applications.
>
>Applications always care about the things around them, so any convention
>that middleware and applications be unaware of each other would rule out
>most middleware.
Yes, exactly! Now you understand me. :) If the application is what wants
the service, let it just call the service. Middleware is *overhead* in
that case.
>>I hope this isn't too vague; I've been wanting to say something about
>>this since I saw your blog post about doing transaction services in WSGI,
>>as that was when I first understood why you were making everything into
>>middleware. (i.e., to create a poor man's substitute for "placeful"
>>services and utilities as found in PEAK and Zope 3.)
>
>What do they provide that middleware does not?
Well, some services may be things the application needs only when it's
being initially configured. Or maybe the service is something like a
scheduler that gives timed callbacks. There are lots of non-per-request
services that make sense, so forcing service access to be only through the
environment makes for cruftier code, since you now have to keep track of
whether you've been called before, and then do any setup during your first
web hit. For that matter, some service configuration might need to be
dynamically determined, based on the application object requesting it.
But the main thing they provide that middleware does not is simplicity and
ease of use. I understand your desire to preserve the appearance of
neutrality, but you are creating new web frameworks here, and making them
ugly doesn't make them any less of a framework. :)
What's worse is that by tying the service access mechanism to the request
environment, you're effectively locking out frameworks like PEAK and Zope 3
from being able to play, and that goes against (IMO) the goals of WSGI,
which is to get more and more frameworks to be able to play, and give them
*incentive* to merge and dissolve and be assimilated into the primordial
soup of WSGI-based integration, or at least to be competitors for various
implementation/use case niches in the WSGI ecosystem.
See also my message to Chris just now about why a WSGI service spec can and
should follow different rules of engagement than the WSGI spec did; it
really isn't necessary to make services ugly for applications in order to
make it easy for server implementors, as it was for the WSGI core spec. In
fact, the opposite condition applies: the service stack should make it easy
and clean for applications to use WSGI services, because they're the things
that will let them hide WSGI implementation details in the absence of an
existing web framework.
More information about the Web-SIG
mailing list