1 #!/usr/bin/env python 2 3 "Mapping from names to resources." 4 5 import WebStack.Generic 6 7 class MapResource: 8 9 "A resource mapping names to other resources." 10 11 def __init__(self, mapping): 12 13 """ 14 Initialise the resource with a 'mapping' of names to resources. The 15 'mapping' should be a dictionary-like object employing simple names 16 without "/" characters; the special value None is used where no name 17 corresponds to that used in the request path and may be used to map to 18 a "catch all" resource. 19 """ 20 21 self.mapping = mapping 22 23 def respond(self, trans): 24 25 """ 26 Using the path information from the given transaction 'trans', invoke 27 mapped resources. Otherwise return an error condition. 28 """ 29 30 # Get the path info. 31 32 parts = trans.get_virtual_path_info().split("/") 33 34 # The first part should always be empty, and there should always be a 35 # second part. 36 37 name = parts[1] 38 39 # Get the mapped resource. 40 41 resource = self.mapping.get(name) 42 if resource is None: 43 resource = self.mapping.get(None) 44 45 # If a resource was found, change the transaction's path info. 46 # eg. "/this/next" -> "/next" 47 # eg. "/this/" -> "/" 48 # eg. "/this" -> "/" 49 50 new_path = parts[0:1] + (parts[2:] or [""]) 51 new_path_info = "/".join(new_path) 52 trans.set_virtual_path_info(new_path_info) 53 54 # Invoke the transaction, transferring control completely. 55 56 if resource is not None: 57 resource.respond(trans) 58 return 59 60 # Otherwise, signal an error. 61 62 self.send_error(trans) 63 64 def send_error(self, trans): 65 66 "Send the error using the given 'trans'." 67 68 trans.set_response_code(404) 69 trans.set_content_type(WebStack.Generic.ContentType("text/plain")) 70 out = trans.get_response_stream() 71 out.write("Resource '%s' not found." % trans.get_path_info()) 72 73 # vim: tabstop=4 expandtab shiftwidth=4