20
20
21
21
logger = logging .getLogger (__name__ )
22
22
23
+ _DYNAMIC_ROUTE_PATTERN = r"(<\w+>)"
24
+ _NAMED_GROUP_BOUNDARY_PATTERN = r"(?P\1\\w+\\b)"
25
+
23
26
24
27
class ProxyEventType (Enum ):
25
28
"""An enumerations of the supported proxy event types."""
@@ -460,8 +463,35 @@ def __call__(self, event, context) -> Any:
460
463
461
464
@staticmethod
462
465
def _compile_regex (rule : str ):
463
- """Precompile regex pattern"""
464
- rule_regex : str = re .sub (r"(<\w+>)" , r"(?P\1.+)" , rule )
466
+ """Precompile regex pattern
467
+
468
+ Logic
469
+ -----
470
+
471
+ 1. Find any dynamic routes defined as <pattern>
472
+ e.g. @app.get("/accounts/<account_id>")
473
+ 2. Create a new regex by substituting every dynamic route found as a named group (?P<group>),
474
+ and match whole words only (word boundary) instead of a greedy match
475
+
476
+ non-greedy example with word boundary
477
+
478
+ rule: '/accounts/<account_id>'
479
+ regex: r'/accounts/(?P<account_id>\\ w+\\ b)'
480
+
481
+ value: /accounts/123/some_other_path
482
+ account_id: 123
483
+
484
+ greedy example without word boundary
485
+
486
+ regex: r'/accounts/(?P<account_id>.+)'
487
+
488
+ value: /accounts/123/some_other_path
489
+ account_id: 123/some_other_path
490
+ 3. Compiles a regex and include start (^) and end ($) in between for an exact match
491
+
492
+ NOTE: See #520 for context
493
+ """
494
+ rule_regex : str = re .sub (_DYNAMIC_ROUTE_PATTERN , _NAMED_GROUP_BOUNDARY_PATTERN , rule )
465
495
return re .compile ("^{}$" .format (rule_regex ))
466
496
467
497
def _to_proxy_event (self , event : Dict ) -> BaseProxyEvent :
@@ -485,7 +515,7 @@ def _resolve(self) -> ResponseBuilder:
485
515
match : Optional [re .Match ] = route .rule .match (path )
486
516
if match :
487
517
logger .debug ("Found a registered route. Calling function" )
488
- return self ._call_route (route , match .groupdict ())
518
+ return self ._call_route (route , match .groupdict ()) # pass fn args
489
519
490
520
logger .debug (f"No match found for path { path } and method { method } " )
491
521
return self ._not_found (method )
0 commit comments