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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 if self.webstack_authenticator is None or self.webstack_authenticator.authenticate(trans): 57 try: 58 self.webstack_resource.respond(trans) 59 except EndOfResponse: 60 pass 61 except: 62 if self.handle_errors: 63 trans.set_response_code(500) # Internal error 64 else: 65 raise 66 else: 67 trans.set_response_code(401) # Unauthorized 68 trans.set_header_value("WWW-Authenticate", '%s realm="%s"' % ( 69 self.webstack_authenticator.get_auth_type(), self.webstack_authenticator.get_realm())) 70 71 trans.commit() 72 request.finish() 73 return twisted.web.server.NOT_DONE_YET 74 75 default_address = ("", 8080) 76 77 def deploy(resource, authenticator=None, address=None, handle_errors=1): 78 79 """ 80 Deploy the given 'resource', with the given optional 'authenticator', at the 81 given optional 'address', where 'address' is a 2-tuple of the form 82 (host_string, port_integer). 83 84 NOTE: Twisted only makes use of the port number provided in the 'address'. 85 86 The optional 'handle_errors' flag (true by default) specifies whether error 87 conditions are handled gracefully. 88 """ 89 90 address = address or default_address 91 92 top_level = Dispatcher(resource, authenticator, handle_errors) 93 site = twisted.web.server.Site(top_level) 94 twisted.internet.reactor.listenTCP(address[1], site) 95 twisted.internet.reactor.run() 96 97 # vim: tabstop=4 expandtab shiftwidth=4