Mercurial > piecrust2
comparison piecrust/routing.py @ 380:f33712c4cfab
routing: Fix bugs with matching URLs with correct route but missing metadata.
When matching a route like `/foo/%slug%` against an URL like `/foo`, the route
will (correctly) return a match, but it will be completely missing the `slug`
metadata, resulting in problems elsewhere. This change makes it so that any
missing route metadata will be filled in with an empty string.
And because this means generated URLs may differ from the incoming URL when
using trailing slashes (`/foo/` _vs._ `/foo`), we make the assert in the
chef server handle those discrepancies.
author | Ludovic Chabant <ludovic@chabant.com> |
---|---|
date | Sun, 10 May 2015 00:34:21 -0700 |
parents | 4b1019bb2533 |
children | dc0988d937b3 |
comparison
equal
deleted
inserted
replaced
379:d40b744a9d99 | 380:f33712c4cfab |
---|---|
88 return self.source.realm | 88 return self.source.realm |
89 | 89 |
90 def matchesMetadata(self, route_metadata): | 90 def matchesMetadata(self, route_metadata): |
91 return self.required_route_metadata.issubset(route_metadata.keys()) | 91 return self.required_route_metadata.issubset(route_metadata.keys()) |
92 | 92 |
93 def matchUri(self, uri): | 93 def matchUri(self, uri, strict=False): |
94 if not uri.startswith(self.uri_root): | 94 if not uri.startswith(self.uri_root): |
95 raise Exception("The given URI is not absolute: %s" % uri) | 95 raise Exception("The given URI is not absolute: %s" % uri) |
96 uri = uri[len(self.uri_root):] | 96 uri = uri[len(self.uri_root):] |
97 | 97 |
98 if not self.pretty_urls: | 98 if not self.pretty_urls: |
99 uri = ugly_url_cleaner.sub('', uri) | 99 uri = ugly_url_cleaner.sub('', uri) |
100 elif self.trailing_slash: | 100 elif self.trailing_slash: |
101 uri = uri.rstrip('/') | 101 uri = uri.rstrip('/') |
102 | 102 |
103 route_metadata = None | |
103 m = self.uri_re.match(uri) | 104 m = self.uri_re.match(uri) |
104 if m: | 105 if m: |
105 return m.groupdict() | 106 route_metadata = m.groupdict() |
106 if self.uri_re_no_path: | 107 if self.uri_re_no_path: |
107 m = self.uri_re_no_path.match(uri) | 108 m = self.uri_re_no_path.match(uri) |
108 if m: | 109 if m: |
109 return m.groupdict() | 110 route_metadata = m.groupdict() |
110 return None | 111 if route_metadata is None: |
112 return None | |
113 | |
114 if not strict: | |
115 # When matching URIs, if the URI is a match but is missing some | |
116 # metadata, fill those up with empty strings. This can happen if, | |
117 # say, a route's pattern is `/foo/%slug%`, and we're matching an | |
118 # URL like `/foo`. | |
119 matched_keys = set(route_metadata.keys()) | |
120 missing_keys = self.required_route_metadata - matched_keys | |
121 for k in missing_keys: | |
122 route_metadata[k] = '' | |
123 | |
124 return route_metadata | |
111 | 125 |
112 def getUri(self, route_metadata, *, sub_num=1, provider=None): | 126 def getUri(self, route_metadata, *, sub_num=1, provider=None): |
113 route_metadata = copy.deepcopy(route_metadata) | 127 route_metadata = copy.deepcopy(route_metadata) |
114 if provider: | 128 if provider: |
115 route_metadata.update(provider.getRouteMetadata()) | 129 route_metadata.update(provider.getRouteMetadata()) |