@@ -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+
6972class 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
89106class 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