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