|
List Info
Thread: Another WSGI gotcha to be aware of
|
|
| Another WSGI gotcha to be aware of |
  United States |
2007-08-25 01:45:03 |
|
|
Hi all,
I just found another corner case in the WSGI spec
that I thought I'd share so you all can check your
WSGI components for similar problems. Basically,
it comes down to error handling. Here's a simple
example:
class Middleware(object):
def __init__(self, nextapp, environ, start_response):
try:
self.response = nextapp(environ, start_response)
self.iter_response = iter(self.response)
return
except SomeException:
self.close()
def close(self):
if hasattr(self.response, "close"):
self.response.close()
def __iter__(self):
return self
def next(self):
try:
return self.iter_response.next()
except AnotherException:
self.close()
raise StopIteration
As you know, all WSGI middleware (that doesn't just pass
through the response from "nextapp") must itself possess
a "close" method so that the response from "nextapp" can
have *its* close method called. In this example, that
would be "self.response.close".
However, and here's the rub, if nextapp() raises an
exception, **self.response is never bound**, and
therefore we have no handle to the object we need
to close. Note that this is not a middleware-only
problem; servers can run into this too.
The spec says, "In general, applications *should* try to
trap their own, internal errors"; we might want to make
that a MUST in future versions. Alternately, we could
require that every application provide its resource-
releasing endpoint via some means other than a successful
response. I'm sure you all can come up with other solutions.
Robert Brewer
fumanchu aminus.org
|
| Re: Another WSGI gotcha to be aware of |

|
2007-08-25 04:24:42 |
On 25/08/07, Robert Brewer <fumanchu aminus.org> wrote:
>
>
>
> Hi all,
>
> I just found another corner case in the WSGI spec
> that I thought I'd share so you all can check your
> WSGI components for similar problems. Basically,
> it comes down to error handling. Here's a simple
> example:
>
>
> class Middleware(object):
>
> def __init__(self, nextapp, environ,
start_response):
> try:
> self.response = nextapp(environ,
start_response)
> self.iter_response = iter(self.response)
> return
> except SomeException:
> self.close()
>
> def close(self):
> if hasattr(self.response, "close"):
> self.response.close()
>
> def __iter__(self):
> return self
>
> def next(self):
> try:
> return self.iter_response.next()
> except AnotherException:
> self.close()
> raise StopIteration
A question related to this example. In what ways is using
__iter__/yield better or worse than defining next() in terms
of
performance, compatibility with different Python versions
etc. For
example:
class Generator:
def __init__(self, generator, callback, environ):
self.__generator = generator
self.__callback = callback
self.__environ = environ
def __iter__(self):
for item in self.__generator:
yield item
def close(self):
if hasattr(self.__generator, 'close'):
self.__generator.close()
self.__callback(self.__environ)
class ExecuteOnCompletion:
def __init__(self, application, callback):
self.__application = application
self.__callback = callback
def __call__(self, environ, start_response):
try:
result = self.__application(environ,
start_response)
except:
self.__callback(self.__environ)
raise
return Generator(result, self.__callback, environ)
Just curious.
Graham
_______________________________________________
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/bo
nd%40yahoo.com
|
|
| Re: Another WSGI gotcha to be aware of |
  United States |
2007-08-25 11:34:25 |
At 11:45 PM 8/24/2007 -0700, Robert Brewer wrote:
>However, and here's the rub, if nextapp() raises an
>exception, **self.response is never bound**, and
>therefore we have no handle to the object we need
>to close. Note that this is not a middleware-only
>problem; servers can run into this too.
>
>The spec says, "In general, applications *should*
try to
>trap their own, internal errors"; we might want to
make
>that a MUST in future versions. Alternately, we could
>require that every application provide its resource-
>releasing endpoint via some means other than a
successful
>response. I'm sure you all can come up with other
solutions.
I don't see a problem here to solve. If the application
didn't
return a response, the middleware naturally isn't obligated
to call
close() on 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/bo
nd%40yahoo.com
|
|
| Re: Another WSGI gotcha to be aware of |
  United States |
2007-08-25 16:09:41 |
|
|
Phillip J. Eby wrote:
> At 11:45 PM 8/24/2007 -0700, Robert Brewer wrote:
> >However, and here's the rub, if nextapp() raises an
> >exception, **self.response is never bound**, and
> >therefore we have no handle to the object we need
> >to close. Note that this is not a middleware-only
> >problem; servers can run into this too.
> >
> >The spec says, "In general, applications *should* try to
> >trap their own, internal errors"; we might want to make
> >that a MUST in future versions. Alternately, we could
> >require that every application provide its resource-
> >releasing endpoint via some means other than a successful
> >response. I'm sure you all can come up with other solutions.
>
> I don't see a problem here to solve. If the application
> didn't return a response, the middleware naturally isn't
> obligated to call close() on it.
Sorry; I didn't mean to imply that WSGI server interfaces
need to be fixed in an way.
As the author of a WSGI application interface, it means
you have to call your own resource cleanup code if an
exception is raised while you're being called (as opposed
to having the response iterated over):
def __call__(self, environ, start_response):
try:
return self.respond(environ, start_response)
except:
self.cleanup()
raise
Some applications don't do this, so my primary message
is to authors of WSGI application interfaces (including
all middleware) to check your code and make sure you do
it, rather than just let errors propagate out.
Some application authors may have chosen to not do this
because the spec says, "should try", not "must". So I'm
thinking of ways to improve that situation, all the way
from "do nothing" to "clarify the language in the spec"
to different conversation models in future specs.
Robert Brewer
fumanchu aminus.org
|
[1-4]
|
|