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