Skip to content

Commit 92cbb52

Browse files
author
Joakim Nohlgård
committed
coap: Update PathRegex matching to the proposed implementation
chrysn/aiocoap#38
1 parent 745817e commit 92cbb52

File tree

1 file changed

+24
-7
lines changed

1 file changed

+24
-7
lines changed

arrowhead/servicedirectory/coap.py

+24-7
Original file line numberDiff line numberDiff line change
@@ -66,25 +66,42 @@ class BadRequestError(aiocoap.error.RenderableError):
6666
code = Code.BAD_REQUEST
6767
message = "BadRequest"
6868

69+
class PathRegex(str):
70+
"""Regular expression match in resource path components"""
71+
6972
class Site(LogMixin, resource.Site):
7073
"""CoAP Site resource with path regex matching"""
7174

7275
@asyncio.coroutine
7376
def render(self, request):
74-
"""Dispatch rendering to the best matching resource"""
7577
path = tuple(request.opt.uri_path)
7678
# Only compare against resources with the same number of path components
7779
matches = [(key, res) for key, res in self._resources.items() if len(key) == len(path)]
80+
# Filter routes matching the path, one level at a time
7881
for level in range(len(path)):
79-
# Filter routes matching the path, one level at a time
80-
matches = [(key, res) for key, res in matches if re.fullmatch(key[level], path[level])]
82+
# Try to find exact string matches
83+
string_matches = [
84+
(key, res) for key, res in matches \
85+
if not isinstance(key[level], PathRegex) and \
86+
key[level] == path[level]
87+
]
88+
if string_matches:
89+
# string matches have a higher priority than regex matches
90+
matches = string_matches
91+
continue
92+
# Try to find any regex matches
93+
matches = [
94+
(key, res) for key, res in matches \
95+
if isinstance(key[level], PathRegex) and \
96+
re.fullmatch(key[level], path[level])
97+
]
8198
if len(matches) == 0:
8299
raise aiocoap.error.NoResource()
83100
elif len(matches) > 1:
84101
raise aiocoap.error.RenderableError(
85102
"Ambiguous matches: {} = {}".format(repr(path), repr(matches)))
86-
self.log.info("{} -> {}".format(repr(path), repr(matches[0][0])))
87-
return matches[0][1].render(request)
103+
child = matches[0][1]
104+
return child.render(request)
88105

89106
class ServiceDirectoryCoAP(RequestDispatcher, Site):
90107
"""Service Directory resource handler class"""
@@ -168,11 +185,11 @@ def _create_resources(self):
168185
self.add_resource(
169186
self.uri_prefix + ('service', ), self._servicelist_resource)
170187
self.add_resource(
171-
self.uri_prefix + ('service', '.*'), self._service_resource)
188+
self.uri_prefix + ('service', PathRegex('.*')), self._service_resource)
172189
self.add_resource(
173190
self.uri_prefix + ('type', ), self._typelist_resource)
174191
self.add_resource(
175-
self.uri_prefix + ('type', '.*'), self._type_resource)
192+
self.uri_prefix + ('type', PathRegex('.*')), self._type_resource)
176193
self.add_resource(
177194
self.uri_prefix + ('publish', ),
178195
self.Resource(post=self._render_publish))

0 commit comments

Comments
 (0)