1.1 --- a/WebStack/Resources/ResourceMap.py Fri Aug 19 20:20:58 2005 +0000
1.2 +++ b/WebStack/Resources/ResourceMap.py Mon Aug 22 11:49:11 2005 +0000
1.3 @@ -26,14 +26,48 @@
1.4
1.5 "A resource mapping names to other resources."
1.6
1.7 - def __init__(self, mapping, directory_redirects=1):
1.8 + def __init__(self, mapping, pass_through=0, directory_redirects=1):
1.9
1.10 """
1.11 Initialise the resource with a 'mapping' of names to resources. The
1.12 'mapping' should be a dictionary-like object employing simple names
1.13 - without "/" characters; the special value None is used where no name
1.14 - corresponds to that used in the request path and may be used to map to
1.15 - a "catch all" resource.
1.16 + without "/" characters; the special value None is used to specify a
1.17 + "catch all" resource which receives all requests whose virtual path
1.18 + info does not match any of the names in the mapping. For example:
1.19 +
1.20 + mapping is {"mammals" : ..., "reptiles" : ..., None : ...}
1.21 +
1.22 + /mammals/cat -> matches "mammals"
1.23 + /reptiles/python -> matches "reptiles"
1.24 + /creatures/goblin -> no match, handled by None
1.25 +
1.26 + When this resource matches a name in the virtual path info to one of the
1.27 + names in the mapping, it removes the section of the virtual path info
1.28 + corresponding to that name before dispatching to the corresponding
1.29 + resource. For example:
1.30 +
1.31 + /mammals/dog -> match with "mammals" in mapping -> /dog
1.32 +
1.33 + By default, where the first part of the virtual path info does not
1.34 + correspond to any of the names in the mapping, the first piece of the
1.35 + virtual path info is removed before dispatching to the "catch all"
1.36 + resource. For example:
1.37 +
1.38 + /creatures/unicorn -> no match -> /unicorn
1.39 +
1.40 + However, the optional 'pass_through' parameter, if set to a true value
1.41 + (which is not the default setting), changes the above behaviour in cases
1.42 + where no matching name is found: in such cases, no part of the virtual
1.43 + path info is removed, and the request is dispatched to the "catch all"
1.44 + resource unchanged. For example:
1.45 +
1.46 + /creatures/unicorn -> no match -> /creatures/unicorn
1.47 +
1.48 + With 'pass_through' set to a true value, care must be taken if this
1.49 + resource is set as its own "catch all" resource. For example:
1.50 +
1.51 + map_resource = MapResource(...)
1.52 + map_resource.mapping[None] = map_resource
1.53
1.54 The optional 'directory_redirects' parameter, if set to a true value (as
1.55 is the default setting), causes a redirect adding a trailing "/"
1.56 @@ -41,6 +75,7 @@
1.57 """
1.58
1.59 self.mapping = mapping
1.60 + self.pass_through = pass_through
1.61 self.directory_redirects = directory_redirects
1.62
1.63 def respond(self, trans):
1.64 @@ -74,15 +109,23 @@
1.65 resource = self.mapping.get(name)
1.66 if resource is None:
1.67 resource = self.mapping.get(None)
1.68 + catch_all_resource = 1
1.69 + else:
1.70 + catch_all_resource = 0
1.71
1.72 # If a resource was found, change the transaction's path info.
1.73 # eg. "/this/next" -> "/next"
1.74 # eg. "/this/" -> "/"
1.75 # eg. "/this" -> ""
1.76 + # Such changes are not made if the resource is in "pass through" mode
1.77 + # and where the "catch all" resource is being used. In such situations
1.78 + # this resource just passes control to the "catch all" resource along
1.79 + # with all the path information intact.
1.80
1.81 - new_path = parts[0:1] + parts[2:]
1.82 - new_path_info = "/".join(new_path)
1.83 - trans.set_virtual_path_info(new_path_info)
1.84 + if not (catch_all_resource and self.pass_through):
1.85 + new_path = parts[0:1] + parts[2:]
1.86 + new_path_info = "/".join(new_path)
1.87 + trans.set_virtual_path_info(new_path_info)
1.88
1.89 # Invoke the transaction, transferring control completely.
1.90