@@ -66,25 +66,42 @@ class BadRequestError(aiocoap.error.RenderableError):
66
66
code = Code .BAD_REQUEST
67
67
message = "BadRequest"
68
68
69
+ class PathRegex (str ):
70
+ """Regular expression match in resource path components"""
71
+
69
72
class Site (LogMixin , resource .Site ):
70
73
"""CoAP Site resource with path regex matching"""
71
74
72
75
@asyncio .coroutine
73
76
def render (self , request ):
74
- """Dispatch rendering to the best matching resource"""
75
77
path = tuple (request .opt .uri_path )
76
78
# Only compare against resources with the same number of path components
77
79
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
78
81
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
+ ]
81
98
if len (matches ) == 0 :
82
99
raise aiocoap .error .NoResource ()
83
100
elif len (matches ) > 1 :
84
101
raise aiocoap .error .RenderableError (
85
102
"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 )
88
105
89
106
class ServiceDirectoryCoAP (RequestDispatcher , Site ):
90
107
"""Service Directory resource handler class"""
@@ -168,11 +185,11 @@ def _create_resources(self):
168
185
self .add_resource (
169
186
self .uri_prefix + ('service' , ), self ._servicelist_resource )
170
187
self .add_resource (
171
- self .uri_prefix + ('service' , '.*' ), self ._service_resource )
188
+ self .uri_prefix + ('service' , PathRegex ( '.*' ) ), self ._service_resource )
172
189
self .add_resource (
173
190
self .uri_prefix + ('type' , ), self ._typelist_resource )
174
191
self .add_resource (
175
- self .uri_prefix + ('type' , '.*' ), self ._type_resource )
192
+ self .uri_prefix + ('type' , PathRegex ( '.*' ) ), self ._type_resource )
176
193
self .add_resource (
177
194
self .uri_prefix + ('publish' , ),
178
195
self .Resource (post = self ._render_publish ))
0 commit comments