Skip to content

Instantly share code, notes, and snippets.

@amcgregor
Created January 9, 2011 03:38
Show Gist options
  • Save amcgregor/771398 to your computer and use it in GitHub Desktop.
Save amcgregor/771398 to your computer and use it in GitHub Desktop.
Examples of minimal PEP 444 / WSGI 2 async-capable middleware, helpers, etc.
def null_middleware(app):
def middleware(environ):
generator = app(environ)
result = None
while True:
result = generator.send(result)
try: result = (yield result)
except: generator.throw(*sys.exc_info())
return middleware
class NullMiddleware(object):
def __init__(self, app):
self.app = app
def __call__(environ):
# ACTION: pre-application environ mangling
generator = self.app(environ)
response = None
while True:
response = generator.send(response)
# Response may be one of:
# * a 2-tuple of (status_str, header_list)
# * bytestring body chunks (after a 2-tuple)
# * futures instances
# ACTION: capture and mangle 2-tuples and bytestrings
# This can create an alternate 'response' value, consumed below.
# Exceptions can be sent from the server, pass them along.
try: response = ( yield response )
except: app_gen.throw(*sys.exc_info())
class FileWrapper(object):
"""Provides a file-like interface for wsgi.input.
If wsgi.input is defined as returning futures, this will allow
access via a more standard blocking interface.
"""
def __init__(self, wsgi_input):
self.input = wsgi_input
def __iter__(self):
return self.input.__iter__()
def read(self, size=-1):
return self.input.read(size).result()
def readline(self, size=-1):
return self.input.readline(size).result()
def readlines(self, size=-1):
return self.input.readlines(size).result()
@amcgregor
Copy link
Author

Updated the class version; the NullMiddleware now omits exception handling of the request to the application. I think this is the 'correct' behaviour for most (non error handling) middleware as the exception will bubble up to the server and result in a 500. If the server pushes an exception to the application, we happily push it up. Wrap the while loop in a try:finally: pair to have cleanup code.

@amcgregor
Copy link
Author

In the current version, StopIteration and GeneratorExit are both handled by simple bubbling.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment