Skip to content

Commit

Permalink
[PR #8566/f3a1afc5 backport][3.10] Fix url dispatcher index when vari…
Browse files Browse the repository at this point in the history
…able is preceded by a fixed string after a slash (#8578)

Co-authored-by: J. Nick Koston <nick@koston.org>
fix for a regression in 3.10.x. Regressed in #7829 fixes #8567
  • Loading branch information
patchback[bot] authored Aug 1, 2024
1 parent 6dff116 commit f19d920
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 2 deletions.
1 change: 1 addition & 0 deletions CHANGES/8566.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fixed url dispatcher index not matching when a variable is preceded by a fixed string after a slash -- by :user:`bdraco`.
10 changes: 8 additions & 2 deletions aiohttp/web_urldispatcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -1131,8 +1131,14 @@ def register_resource(self, resource: AbstractResource) -> None:

def _get_resource_index_key(self, resource: AbstractResource) -> str:
"""Return a key to index the resource in the resource index."""
# strip at the first { to allow for variables
return resource.canonical.partition("{")[0].rstrip("/") or "/"
if "{" in (index_key := resource.canonical):
# strip at the first { to allow for variables, and than
# rpartition at / to allow for variable parts in the path
# For example if the canonical path is `/core/locations{tail:.*}`
# the index key will be `/core` since index is based on the
# url parts split by `/`
index_key = index_key.partition("{")[0].rpartition("/")[0]
return index_key.rstrip("/") or "/"

def index_resource(self, resource: AbstractResource) -> None:
"""Add a resource to the resource index."""
Expand Down
24 changes: 24 additions & 0 deletions tests/test_web_urldispatcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -937,3 +937,27 @@ async def get(self) -> web.Response:
r = await client.get("///a")
assert r.status == 200
await r.release()


async def test_route_with_regex(aiohttp_client: AiohttpClient) -> None:
"""Test a route with a regex preceded by a fixed string."""
app = web.Application()

async def handler(request: web.Request) -> web.Response:
assert isinstance(request.match_info._route.resource, Resource)
return web.Response(text=request.match_info._route.resource.canonical)

app.router.add_get("/core/locations{tail:.*}", handler)
client = await aiohttp_client(app)

r = await client.get("/core/locations/tail/here")
assert r.status == 200
assert await r.text() == "/core/locations{tail}"

r = await client.get("/core/locations_tail_here")
assert r.status == 200
assert await r.text() == "/core/locations{tail}"

r = await client.get("/core/locations_tail;id=abcdef")
assert r.status == 200
assert await r.text() == "/core/locations{tail}"

0 comments on commit f19d920

Please sign in to comment.