1 #!/usr/bin/env python 2 3 """ 4 BaseHTTPRequestHandler adapter. 5 6 Copyright (C) 2004, 2005, 2006 Paul Boddie <paul@boddie.org.uk> 7 8 This library is free software; you can redistribute it and/or 9 modify it under the terms of the GNU Lesser General Public 10 License as published by the Free Software Foundation; either 11 version 2.1 of the License, or (at your option) any later version. 12 13 This library is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 Lesser General Public License for more details. 17 18 You should have received a copy of the GNU Lesser General Public 19 License along with this library; if not, write to the Free Software 20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA 21 """ 22 23 import WebStack.BaseHTTPRequestHandler 24 import BaseHTTPServer 25 from WebStack.Generic import EndOfResponse 26 from WebStack.Adapters.Helpers.Error import ErrorResource 27 28 class HandlerFactory: 29 30 "A factory class creating WebStack dispatcher objects." 31 32 def __init__(self, resource, authenticator=None, handle_errors=1, error_resource=None): 33 34 """ 35 Initialise the root application-specific 'resource' and optional 36 'authenticator'. The optional 'handle_errors' parameter (if true) causes 37 handlers to deal with uncaught exceptions cleanly, and the optional 38 'error_resource' specifies an alternative error message generation 39 resource. 40 """ 41 42 self.webstack_resource = resource 43 self.webstack_authenticator = authenticator 44 self.handle_errors = handle_errors 45 self.error_resource = error_resource or ErrorResource() 46 47 def __call__(self, request, client_address, server): 48 49 "Act as a factory for the server objects." 50 51 handler = Handler(request, client_address, server, self.webstack_resource, 52 self.webstack_authenticator, self.handle_errors, self.error_resource) 53 return handler 54 55 class Handler(BaseHTTPServer.BaseHTTPRequestHandler): 56 57 "A class dispatching requests to WebStack resources." 58 59 def __init__(self, request, client_address, server, resource, authenticator, handle_errors, error_resource): 60 61 """ 62 Initialise the root application-specific 'resource' and 'authenticator'. 63 Where 'handle_errors' is true, uncaught exceptions are dealt with by the 64 handler and reported using the 'error_resource' provided. 65 """ 66 67 self.webstack_resource = resource 68 self.webstack_authenticator = authenticator 69 self.handle_errors = handle_errors 70 self.error_resource = error_resource 71 BaseHTTPServer.BaseHTTPRequestHandler.__init__(self, request, client_address, server) 72 73 def handle(self): 74 75 "Dispatch the request to the root application-specific resource." 76 77 # NOTE: Overriding and trimming back the method's functionality. 78 79 self.raw_requestline = self.rfile.readline() 80 if not self.parse_request(): # An error code has been sent, just exit 81 return 82 83 trans = WebStack.BaseHTTPRequestHandler.Transaction(self) 84 try: 85 if self.webstack_authenticator is None or self.webstack_authenticator.authenticate(trans): 86 try: 87 self.webstack_resource.respond(trans) 88 except EndOfResponse: 89 pass 90 except: 91 if self.handle_errors: 92 trans.rollback() 93 trans.set_response_code(500) # Internal error 94 self.error_resource.respond(trans) 95 else: 96 raise 97 else: 98 trans.set_response_code(401) # Unauthorized 99 trans.set_header_value("WWW-Authenticate", '%s realm="%s"' % ( 100 self.webstack_authenticator.get_auth_type(), self.webstack_authenticator.get_realm())) 101 102 finally: 103 trans.commit() 104 105 default_address = ("", 8080) 106 107 def deploy(resource, authenticator=None, address=None, handle_errors=1, error_resource=None): 108 109 """ 110 Deploy the given 'resource', with the given optional 'authenticator', at the 111 given optional 'address', where 'address' is a 2-tuple of the form 112 (host_string, port_integer). 113 114 The optional 'handle_errors' flag (true by default) specifies whether error 115 conditions are handled gracefully, and the optional 'error_resource' 116 specifies an alternative error message generation resource, if desired. 117 """ 118 119 handler = HandlerFactory(resource, authenticator, handle_errors, error_resource) 120 server = BaseHTTPServer.HTTPServer(address or default_address, handler) 121 server.serve_forever() 122 123 # vim: tabstop=4 expandtab shiftwidth=4