1 #!/usr/bin/env python 2 3 """ 4 WSGI adapter. 5 """ 6 7 import WebStack.WSGI 8 from WebStack.Generic import EndOfResponse 9 10 class WSGIAdapter: 11 12 "A WSGI adapter class." 13 14 def __init__(self, resource, authenticator=None, handle_errors=1): 15 16 """ 17 Initialise the adapter with the given WebStack 'resource' and the 18 optional 'authenticator'. The optional 'handle_errors' parameter (if 19 true) causes handlers to deal with uncaught exceptions cleanly. 20 """ 21 22 self.resource = resource 23 self.authenticator = authenticator 24 self.handle_errors = handle_errors 25 26 def __call__(self, environ, start_response): 27 28 """ 29 Dispatch to the root application-specific 'resource'. Return a list of 30 strings comprising the response body text. 31 """ 32 33 # NOTE: It would be best to give start_response to the transaction so 34 # NOTE: that the underlying response's write method can be used by the 35 # NOTE: transaction directly. Unfortunately, WebStack doesn't provide 36 # NOTE: any means of declaring when the headers have been set and when 37 # NOTE: response body output is the only thing to be subsequently 38 # NOTE: produced. 39 40 trans = WebStack.WSGI.Transaction(environ) 41 42 try: 43 if self.authenticator is None or self.authenticator.authenticate(trans): 44 try: 45 self.resource.respond(trans) 46 except EndOfResponse: 47 pass 48 except: 49 if self.handle_errors: 50 trans.set_response_code(500) # Internal error 51 else: 52 raise 53 else: 54 trans.set_response_code(401) # Unauthorized 55 trans.set_header_value("WWW-Authenticate", '%s realm="%s"' % ( 56 self.authenticator.get_auth_type(), self.authenticator.get_realm())) 57 finally: 58 trans.commit() 59 60 # NOTE: Provide sensible messages. 61 # NOTE: Ignoring the write method returned by start_response. 62 63 start_response( 64 "%s WebStack status" % trans.get_response_code(), 65 trans.get_wsgi_headers() 66 ) 67 return [trans.get_wsgi_content()] 68 69 # vim: tabstop=4 expandtab shiftwidth=4