1.1 --- a/README.txt Fri Aug 19 20:20:58 2005 +0000
1.2 +++ b/README.txt Mon Aug 22 11:49:11 2005 +0000
1.3 @@ -62,8 +62,9 @@
1.4 session store, avoiding deadlocks.
1.5 Fixed the calendar example, making it perform a proper function.
1.6 Added the notion of processed virtual path info - the part of the original
1.7 -path info not represented in the current virtual path info (prompted by a
1.8 -different suggestion from Scott Robinson).
1.9 +path info not represented in the current virtual path info.
1.10 +Added "pass through" behaviour to ResourceMap.MapResource (prompted by a patch
1.11 +from Scott Robinson).
1.12 Changed the ResourceMap.MapResource class to provide the empty string as the
1.13 resource name where the virtual path info is only one component in length.
1.14 Added a convenience method to Transaction for the decoding of path values and
2.1 --- a/WebStack/Resources/ResourceMap.py Fri Aug 19 20:20:58 2005 +0000
2.2 +++ b/WebStack/Resources/ResourceMap.py Mon Aug 22 11:49:11 2005 +0000
2.3 @@ -26,14 +26,48 @@
2.4
2.5 "A resource mapping names to other resources."
2.6
2.7 - def __init__(self, mapping, directory_redirects=1):
2.8 + def __init__(self, mapping, pass_through=0, directory_redirects=1):
2.9
2.10 """
2.11 Initialise the resource with a 'mapping' of names to resources. The
2.12 'mapping' should be a dictionary-like object employing simple names
2.13 - without "/" characters; the special value None is used where no name
2.14 - corresponds to that used in the request path and may be used to map to
2.15 - a "catch all" resource.
2.16 + without "/" characters; the special value None is used to specify a
2.17 + "catch all" resource which receives all requests whose virtual path
2.18 + info does not match any of the names in the mapping. For example:
2.19 +
2.20 + mapping is {"mammals" : ..., "reptiles" : ..., None : ...}
2.21 +
2.22 + /mammals/cat -> matches "mammals"
2.23 + /reptiles/python -> matches "reptiles"
2.24 + /creatures/goblin -> no match, handled by None
2.25 +
2.26 + When this resource matches a name in the virtual path info to one of the
2.27 + names in the mapping, it removes the section of the virtual path info
2.28 + corresponding to that name before dispatching to the corresponding
2.29 + resource. For example:
2.30 +
2.31 + /mammals/dog -> match with "mammals" in mapping -> /dog
2.32 +
2.33 + By default, where the first part of the virtual path info does not
2.34 + correspond to any of the names in the mapping, the first piece of the
2.35 + virtual path info is removed before dispatching to the "catch all"
2.36 + resource. For example:
2.37 +
2.38 + /creatures/unicorn -> no match -> /unicorn
2.39 +
2.40 + However, the optional 'pass_through' parameter, if set to a true value
2.41 + (which is not the default setting), changes the above behaviour in cases
2.42 + where no matching name is found: in such cases, no part of the virtual
2.43 + path info is removed, and the request is dispatched to the "catch all"
2.44 + resource unchanged. For example:
2.45 +
2.46 + /creatures/unicorn -> no match -> /creatures/unicorn
2.47 +
2.48 + With 'pass_through' set to a true value, care must be taken if this
2.49 + resource is set as its own "catch all" resource. For example:
2.50 +
2.51 + map_resource = MapResource(...)
2.52 + map_resource.mapping[None] = map_resource
2.53
2.54 The optional 'directory_redirects' parameter, if set to a true value (as
2.55 is the default setting), causes a redirect adding a trailing "/"
2.56 @@ -41,6 +75,7 @@
2.57 """
2.58
2.59 self.mapping = mapping
2.60 + self.pass_through = pass_through
2.61 self.directory_redirects = directory_redirects
2.62
2.63 def respond(self, trans):
2.64 @@ -74,15 +109,23 @@
2.65 resource = self.mapping.get(name)
2.66 if resource is None:
2.67 resource = self.mapping.get(None)
2.68 + catch_all_resource = 1
2.69 + else:
2.70 + catch_all_resource = 0
2.71
2.72 # If a resource was found, change the transaction's path info.
2.73 # eg. "/this/next" -> "/next"
2.74 # eg. "/this/" -> "/"
2.75 # eg. "/this" -> ""
2.76 + # Such changes are not made if the resource is in "pass through" mode
2.77 + # and where the "catch all" resource is being used. In such situations
2.78 + # this resource just passes control to the "catch all" resource along
2.79 + # with all the path information intact.
2.80
2.81 - new_path = parts[0:1] + parts[2:]
2.82 - new_path_info = "/".join(new_path)
2.83 - trans.set_virtual_path_info(new_path_info)
2.84 + if not (catch_all_resource and self.pass_through):
2.85 + new_path = parts[0:1] + parts[2:]
2.86 + new_path_info = "/".join(new_path)
2.87 + trans.set_virtual_path_info(new_path_info)
2.88
2.89 # Invoke the transaction, transferring control completely.
2.90