From fa76cbe1de42a89d3c7e59121341c6bd975b7007 Mon Sep 17 00:00:00 2001 From: pgjones Date: Mon, 25 Jul 2022 16:58:32 +0100 Subject: [PATCH 1/2] Ensure that rules without strict slashes match paths with slashes A rule defined as `/path` with strict-slashes == False should match a path `/path/` but only if there isn't a rule that directly matches `/path/`. This restores the previous 2.2.0 behaviour. --- CHANGES.rst | 3 +++ src/werkzeug/routing/matcher.py | 16 ++++++++++++++++ tests/test_routing.py | 2 ++ 3 files changed, 21 insertions(+) diff --git a/CHANGES.rst b/CHANGES.rst index 95100d26b..a39325e1e 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -5,6 +5,9 @@ Version 2.2.1 Unreleased +- Fix router so that ``/path/`` will match a rule ``/path`` if strict + slashes mode is disabled for the rule. :issue:`2467` + Version 2.2.0 ------------- diff --git a/src/werkzeug/routing/matcher.py b/src/werkzeug/routing/matcher.py index 3c649c2e6..c02812693 100644 --- a/src/werkzeug/routing/matcher.py +++ b/src/werkzeug/routing/matcher.py @@ -129,6 +129,22 @@ def _match( rv = _match(new_state, remaining, values + list(match.groups())) if rv is not None: return rv + + # If there is no match and the only part left is a + # trailing slash ("") consider rules that aren't + # strict-slashes as these should match if there is a final + # slash part. + if parts == [""]: + for rule in state.rules: + if rule.strict_slashes: + continue + if rule.methods is not None and method not in rule.methods: + have_match_for.update(rule.methods) + elif rule.websocket != websocket: + websocket_mismatch = True + else: + return rule, values + return None try: diff --git a/tests/test_routing.py b/tests/test_routing.py index dc0acfa6f..0c28a1867 100644 --- a/tests/test_routing.py +++ b/tests/test_routing.py @@ -219,6 +219,7 @@ def test_strict_slashes_leaves_dont_consume(): r.Rule("/path3/", endpoint="branch", strict_slashes=False), r.Rule("/path4", endpoint="leaf", strict_slashes=False), r.Rule("/path4/", endpoint="branch", strict_slashes=False), + r.Rule("/path5", endpoint="leaf"), ], strict_slashes=False, ) @@ -233,6 +234,7 @@ def test_strict_slashes_leaves_dont_consume(): assert adapter.match("/path3/", method="GET") == ("branch", {}) assert adapter.match("/path4", method="GET") == ("leaf", {}) assert adapter.match("/path4/", method="GET") == ("branch", {}) + assert adapter.match("/path5/", method="GET") == ("leaf", {}) def test_environ_defaults(): From 364d9c2a90f02815347c0a998cf0f31ebf6a3ee5 Mon Sep 17 00:00:00 2001 From: pgjones Date: Mon, 25 Jul 2022 17:08:09 +0100 Subject: [PATCH 2/2] Restore ValidationError as part of the werkzeug.routing API This matches the documented import path. --- CHANGES.rst | 2 ++ src/werkzeug/routing/__init__.py | 1 + 2 files changed, 3 insertions(+) diff --git a/CHANGES.rst b/CHANGES.rst index a39325e1e..ce9a469cc 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -7,6 +7,8 @@ Unreleased - Fix router so that ``/path/`` will match a rule ``/path`` if strict slashes mode is disabled for the rule. :issue:`2467` +- Restore ``ValidationError`` to be importable from + ``werkzeug.routing``. :issue:`2465` Version 2.2.0 diff --git a/src/werkzeug/routing/__init__.py b/src/werkzeug/routing/__init__.py index 7f80e8386..04d092b01 100644 --- a/src/werkzeug/routing/__init__.py +++ b/src/werkzeug/routing/__init__.py @@ -112,6 +112,7 @@ from .converters import PathConverter from .converters import UnicodeConverter from .converters import UUIDConverter +from .converters import ValidationError from .exceptions import BuildError from .exceptions import NoMatch from .exceptions import RequestAliasRedirect