[Web-SIG] WSGI start_response exc_info argument

Ian Bicking ianb at colorstudy.com
Wed Mar 30 18:57:34 CEST 2005


Phillip J. Eby wrote:
> That's not the use case.  The parameter exists so error handling code 
> doesn't have to care whether start_response has already been called.  
> Thus, applications and middleware can be simpler because they don't need 
> to track that bit of state information that the server is already 
> tracking.  So, calling start_response when it has already been called 
> causes the error handler to abort and fall back to the next higher error 
> handler, all the way up to the "real" server.  IOW, it's a way of 
> guaranteeing immediate request termination if an error occurs once the 
> response has begun.
> 
> Of course, any logging or notification error handlers in the stack will 
> receive the error in the normal way; it's just that if they also try to 
> start a response, they'll be aborted and the error will bubble up to the 
> next handler.  Does that make more sense now?

I guess, but it seems to complicate most middleware for the benefit of a 
small number of middlewares.  My current middleware (all of which is 
written ignorant of this argument) does something like:

class ErrorMiddleware(object):

     def __init__(self, application, show_exceptions=True,
                  email_exceptions_to=[], smtp_server='localhost'):
         self.application = application
         self.show_exceptions = show_exceptions
         self.email_exceptions_to = email_exceptions_to
         self.smtp_server = smtp_server

     def __call__(self, environ, start_response):
         # We want to be careful about not sending headers twice,
         # and the content type that the app has committed to (if there
         # is an exception in the iterator body of the response)
         started = []

         def detect_start_response(status, headers):
             started.append(True)
             return start_response(status, headers)

         try:
             app_iter = self.application(environ, detect_start_response)
             return self.catching_iter(app_iter, environ)
         except:
             if not started:
                 start_response('500 Internal Server Error',
                                [('content-type', 'text/html')])
             # @@: it would be nice to deal with bad content types here
             dummy_file = StringIO()
             response = self.exception_handler(sys.exc_info(), environ)
             return [response]


It really should capture the headers, and maybe buffer them itself (in 
which case it would also have to intercept the writer), so that it can 
deal more gracefully with a case where content type is set or something. 
  But all that annoying stuff is better kept to this one piece of 
middleware, instead of making everything more difficult with that extra 
argument to start_response.

-- 
Ian Bicking  /  ianb at colorstudy.com  /  http://blog.ianbicking.org


More information about the Web-SIG mailing list