1 #!/usr/bin/env python 2 3 """ 4 Twisted adapter. 5 6 Copyright (C) 2004, 2005 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.Twisted 24 from WebStack.Generic import EndOfResponse 25 import twisted.web.resource 26 import twisted.web.server 27 import twisted.internet.reactor 28 29 class Dispatcher(twisted.web.resource.Resource): 30 31 "A class dispatching requests to WebStack resources." 32 33 isLeaf = 1 34 35 def __init__(self, resource, authenticator=None, handle_errors=1): 36 37 """ 38 Initialise the root application-specific 'resource' and optional 39 'authenticator'. The optional 'handle_errors' parameter (if true) causes 40 handlers to deal with uncaught exceptions cleanly. 41 """ 42 43 twisted.web.resource.Resource.__init__(self) 44 self.webstack_resource = resource 45 self.webstack_authenticator = authenticator 46 self.handle_errors = handle_errors 47 48 def getChild(self, path, request): 49 raise NotImplementedError, "getChild" 50 51 def render(self, request): 52 53 "Dispatch the given 'request' to the root application-specific resource." 54 55 trans = WebStack.Twisted.Transaction(request) 56 try: 57 if self.webstack_authenticator is None or self.webstack_authenticator.authenticate(trans): 58 try: 59 self.webstack_resource.respond(trans) 60 except EndOfResponse: 61 pass 62 except: 63 if self.handle_errors: 64 trans.set_response_code(500) # Internal error 65 else: 66 raise 67 else: 68 trans.set_response_code(401) # Unauthorized 69 trans.set_header_value("WWW-Authenticate", '%s realm="%s"' % ( 70 self.webstack_authenticator.get_auth_type(), self.webstack_authenticator.get_realm())) 71 72 finally: 73 trans.commit() 74 75 request.finish() 76 return twisted.web.server.NOT_DONE_YET 77 78 default_address = ("", 8080) 79 80 def deploy(resource, authenticator=None, address=None, handle_errors=1): 81 82 """ 83 Deploy the given 'resource', with the given optional 'authenticator', at the 84 given optional 'address', where 'address' is a 2-tuple of the form 85 (host_string, port_integer). 86 87 NOTE: Twisted only makes use of the port number provided in the 'address'. 88 89 The optional 'handle_errors' flag (true by default) specifies whether error 90 conditions are handled gracefully. 91 """ 92 93 address = address or default_address 94 95 top_level = Dispatcher(resource, authenticator, handle_errors) 96 site = twisted.web.server.Site(top_level) 97 twisted.internet.reactor.listenTCP(address[1], site) 98 twisted.internet.reactor.run() 99 100 # vim: tabstop=4 expandtab shiftwidth=4