List Info

Thread: Another WSGI gotcha to be aware of




Another WSGI gotcha to be aware of
country flaguser name
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
fumanchuaminus.org

Re: Another WSGI gotcha to be aware of
user name
2007-08-25 04:24:42
On 25/08/07, Robert Brewer <fumanchuaminus.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-SIGpython.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
country flaguser name
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-SIGpython.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
country flaguser name
United States
2007-08-25 16:09:41

Phillip J. Eby wrote:
&gt; At 11:45 PM 8/24/2007 -0700, Robert Brewer wrote:
&gt; >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&quot;; we might want to make
>; >that a MUST in future versions. Alternately, we could
&gt; >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.
>
&gt; I don't see a problem here to solve.&nbsp; If the application
> didn't return a response, the middleware naturally isn't
&gt; 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):
&nbsp; &nbsp; try:
&nbsp; &nbsp; &nbsp;   return self.respond(environ, start_response)
&nbsp; &nbsp; except:
  ; &nbsp; &nbsp;  self.cleanup()
&nbsp; &nbsp; &nbsp; &nbsp; 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&quot; to "clarify the language in the spec"
to different conversation models in future specs.


Robert Brewer
fumanchuaminus.org

[1-4]

about | contact  Other archives ( Real Estate discussion Medical topics )