Skip to content

Commit cdee5ce

Browse files
authored
Merge pull request #2472 from pgjones/2.2.x
Bugfix the calculation of weighting based on static parts
2 parents 5c85706 + 56a24f7 commit cdee5ce

File tree

3 files changed

+20
-2
lines changed

3 files changed

+20
-2
lines changed

CHANGES.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ Unreleased
99
slashes mode is disabled for the rule. :issue:`2467`
1010
- Fix router so that partial part matches are not allowed
1111
i.e. ``/2df`` does not match ``/<int>``. :pr:`2470`
12+
- Fix router static part weighting, so that simpler routes are matched
13+
before more complex ones. :issue:`2471`
1214
- Restore ``ValidationError`` to be importable from
1315
``werkzeug.routing``. :issue:`2465`
1416

src/werkzeug/routing/rules.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -592,8 +592,12 @@ def _parse_rule(self, rule: str) -> t.Iterable[RulePart]:
592592

593593
data = match.groupdict()
594594
if data["static"]:
595-
static_weights.append((static_parts, -len(data["static"])))
596-
static_parts += 1
595+
# Only static parts beyond the `/` count towards the
596+
# weighting (more static parts mean the rule should be
597+
# weighted first).
598+
if data["static"] != "/":
599+
static_weights.append((static_parts, -len(data["static"])))
600+
static_parts += 1
597601
self._trace.append((False, data["static"]))
598602

599603
if data["variable"] is not None:

tests/test_routing.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1394,6 +1394,18 @@ def test_rule_websocket_methods():
13941394
r.Rule("/ws", endpoint="ws", websocket=True, methods=["get", "head", "options"])
13951395

13961396

1397+
def test_path_weighting():
1398+
m = r.Map(
1399+
[
1400+
r.Rule("/<path:path>/c", endpoint="simple"),
1401+
r.Rule("/<path:path>/<a>/<b>", endpoint="complex"),
1402+
]
1403+
)
1404+
a = m.bind("localhost", path_info="/a/b/c")
1405+
1406+
assert a.match() == ("simple", {"path": "a/b"})
1407+
1408+
13971409
def test_newline_match():
13981410
m = r.Map([r.Rule("/hello", endpoint="hello")])
13991411
a = m.bind("localhost")

0 commit comments

Comments
 (0)