From 12873dc0a04dfec8cd4fafa8dd9d6544cb509154 Mon Sep 17 00:00:00 2001 From: Dan King Date: Wed, 10 Mar 2021 15:55:34 -0500 Subject: [PATCH 1/9] StaticResource only matches folder-like URL prefix I think this fixes https://github.com/aio-libs/aiohttp/issues/5250 --- aiohttp/web_urldispatcher.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aiohttp/web_urldispatcher.py b/aiohttp/web_urldispatcher.py index a229cd7e4ed..ad87309a5d6 100644 --- a/aiohttp/web_urldispatcher.py +++ b/aiohttp/web_urldispatcher.py @@ -617,7 +617,7 @@ async def resolve(self, request: Request) -> _Resolve: path = request.rel_url.raw_path method = request.method allowed_methods = set(self._routes) - if not path.startswith(self._prefix): + if not path.startswith(self._prefix + "/"): return None, set() if method not in allowed_methods: From 87308971720f029a9607e9da49e77adcb3c0bf42 Mon Sep 17 00:00:00 2001 From: Daniel King Date: Wed, 10 Mar 2021 15:59:55 -0500 Subject: [PATCH 2/9] add to contributors --- CONTRIBUTORS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt index 20f110dea92..69996ce9fcb 100644 --- a/CONTRIBUTORS.txt +++ b/CONTRIBUTORS.txt @@ -71,6 +71,7 @@ Claudiu Popa Colin Dunklau Cong Xu Damien Nadé +Dan King Dan Xu Daniel García Daniel Grossmann-Kavanagh From 0d0f5667fa536c46ce9fa5fca1292c0a32050383 Mon Sep 17 00:00:00 2001 From: Daniel King Date: Wed, 10 Mar 2021 16:02:48 -0500 Subject: [PATCH 3/9] add CHANGES --- CHANGES/5250.bugfix | 1 + 1 file changed, 1 insertion(+) create mode 100644 CHANGES/5250.bugfix diff --git a/CHANGES/5250.bugfix b/CHANGES/5250.bugfix new file mode 100644 index 00000000000..33c6e064378 --- /dev/null +++ b/CHANGES/5250.bugfix @@ -0,0 +1 @@ +StaticResource prefixes no longer match URLs with a non-folder prefix. For example `routes.static('/foo', '/foo')` no longer matches the URL `/foobar`. Previously, this would attempt to load the file `/foo/ar`. \ No newline at end of file From a457f32ddd8559d6fdbe14884edb7f90bd223184 Mon Sep 17 00:00:00 2001 From: Daniel King Date: Wed, 10 Mar 2021 16:16:42 -0500 Subject: [PATCH 4/9] add test --- tests/test_web_urldispatcher.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tests/test_web_urldispatcher.py b/tests/test_web_urldispatcher.py index 49465723c37..309e75470ea 100644 --- a/tests/test_web_urldispatcher.py +++ b/tests/test_web_urldispatcher.py @@ -458,3 +458,17 @@ async def test_static_absolute_url(aiohttp_client: Any, tmp_path: Any) -> None: client = await aiohttp_client(app) resp = await client.get("/static/" + str(file_path.resolve())) assert resp.status == 403 + + +async def test_for_issue_5250(aiohttp_client: Any, tmp_path: Any) -> None: + app = web.Application() + app.router.add_static("/foo", tmp_path) + + async def get_foobar(request): + return web.Response(body="success!") + app.router.add_get("/foobar", get_foobar) + + client = await aiohttp_client(app) + async with await client.get("/foobar") as resp: + assert resp.status == 200 + assert (await resp.text()) == "success!" From 1fd08e1e5f3bed3fcdc093fe666f1978cf5d1f62 Mon Sep 17 00:00:00 2001 From: Daniel King Date: Mon, 22 Mar 2021 18:02:54 -0400 Subject: [PATCH 5/9] apply black changes --- CHANGES/5250.bugfix | 2 +- tests/test_web_urldispatcher.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGES/5250.bugfix b/CHANGES/5250.bugfix index 33c6e064378..36ea1851d04 100644 --- a/CHANGES/5250.bugfix +++ b/CHANGES/5250.bugfix @@ -1 +1 @@ -StaticResource prefixes no longer match URLs with a non-folder prefix. For example `routes.static('/foo', '/foo')` no longer matches the URL `/foobar`. Previously, this would attempt to load the file `/foo/ar`. \ No newline at end of file +StaticResource prefixes no longer match URLs with a non-folder prefix. For example `routes.static('/foo', '/foo')` no longer matches the URL `/foobar`. Previously, this would attempt to load the file `/foo/ar`. diff --git a/tests/test_web_urldispatcher.py b/tests/test_web_urldispatcher.py index 309e75470ea..2eeb65b9832 100644 --- a/tests/test_web_urldispatcher.py +++ b/tests/test_web_urldispatcher.py @@ -466,6 +466,7 @@ async def test_for_issue_5250(aiohttp_client: Any, tmp_path: Any) -> None: async def get_foobar(request): return web.Response(body="success!") + app.router.add_get("/foobar", get_foobar) client = await aiohttp_client(app) From c562f50ad5a9d0061c7495f08802fc4d62f0cc7e Mon Sep 17 00:00:00 2001 From: Daniel King Date: Mon, 22 Mar 2021 19:51:41 -0400 Subject: [PATCH 6/9] show index when there is no trailing slash --- aiohttp/web_urldispatcher.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aiohttp/web_urldispatcher.py b/aiohttp/web_urldispatcher.py index ad87309a5d6..184469b1512 100644 --- a/aiohttp/web_urldispatcher.py +++ b/aiohttp/web_urldispatcher.py @@ -617,7 +617,7 @@ async def resolve(self, request: Request) -> _Resolve: path = request.rel_url.raw_path method = request.method allowed_methods = set(self._routes) - if not path.startswith(self._prefix + "/"): + if not path.startswith(self._prefix + "/") and path != self._prefix): return None, set() if method not in allowed_methods: From f1ec23a551379081183a51093f93bde03746d615 Mon Sep 17 00:00:00 2001 From: Daniel King Date: Mon, 22 Mar 2021 19:56:04 -0400 Subject: [PATCH 7/9] fix typo --- aiohttp/web_urldispatcher.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aiohttp/web_urldispatcher.py b/aiohttp/web_urldispatcher.py index 184469b1512..d5797b7e68c 100644 --- a/aiohttp/web_urldispatcher.py +++ b/aiohttp/web_urldispatcher.py @@ -617,7 +617,7 @@ async def resolve(self, request: Request) -> _Resolve: path = request.rel_url.raw_path method = request.method allowed_methods = set(self._routes) - if not path.startswith(self._prefix + "/") and path != self._prefix): + if not path.startswith(self._prefix + "/") and path != self._prefix: return None, set() if method not in allowed_methods: From b87ee480ba85fcb3d8baba603a67d35c6efe0b9e Mon Sep 17 00:00:00 2001 From: Andrew Svetlov Date: Sat, 30 Oct 2021 18:13:36 +0300 Subject: [PATCH 8/9] Update CHANGES/5250.bugfix --- CHANGES/5250.bugfix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES/5250.bugfix b/CHANGES/5250.bugfix index 36ea1851d04..3e0bf0a30bb 100644 --- a/CHANGES/5250.bugfix +++ b/CHANGES/5250.bugfix @@ -1 +1 @@ -StaticResource prefixes no longer match URLs with a non-folder prefix. For example `routes.static('/foo', '/foo')` no longer matches the URL `/foobar`. Previously, this would attempt to load the file `/foo/ar`. +StaticResource prefixes no longer match URLs with a non-folder prefix. For example ``routes.static('/foo', '/foo')`` no longer matches the URL ``/foobar``. Previously, this would attempt to load the file ``/foo/ar``. From 519539b7143ceb6a960a55215e4ff7df7f5c43a1 Mon Sep 17 00:00:00 2001 From: Andrew Svetlov Date: Sat, 30 Oct 2021 18:35:44 +0300 Subject: [PATCH 9/9] Optimize --- aiohttp/web_urldispatcher.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/aiohttp/web_urldispatcher.py b/aiohttp/web_urldispatcher.py index 31ec5156d0a..a691661d7dd 100644 --- a/aiohttp/web_urldispatcher.py +++ b/aiohttp/web_urldispatcher.py @@ -495,6 +495,7 @@ def __init__(self, prefix: str, *, name: Optional[str] = None) -> None: assert prefix in ("", "/") or not prefix.endswith("/"), prefix super().__init__(name=name) self._prefix = _requote_path(prefix) + self._prefix2 = self._prefix + "/" @property def canonical(self) -> str: @@ -505,6 +506,7 @@ def add_prefix(self, prefix: str) -> None: assert not prefix.endswith("/") assert len(prefix) > 1 self._prefix = prefix + self._prefix + self._prefix2 = self._prefix + "/" def raw_match(self, prefix: str) -> bool: return False @@ -616,7 +618,7 @@ async def resolve(self, request: Request) -> _Resolve: path = request.rel_url.raw_path method = request.method allowed_methods = set(self._routes) - if not path.startswith(self._prefix + "/") and path != self._prefix: + if not path.startswith(self._prefix2) and path != self._prefix: return None, set() if method not in allowed_methods: @@ -732,7 +734,7 @@ def get_info(self) -> _InfoDict: async def resolve(self, request: Request) -> _Resolve: if ( - not request.url.raw_path.startswith(self._prefix + "/") + not request.url.raw_path.startswith(self._prefix2) and request.url.raw_path != self._prefix ): return None, set()