Skip to content

Commit e618dcb

Browse files
[PR #11673/e8c5252c backport][3.13] Fix domain matching being lower priority than path matching (#11675)
**This is a backport of PR #11673 as merged into master (e8c5252).** Co-authored-by: Sam Bull <[email protected]>
1 parent b8eff25 commit e618dcb

File tree

4 files changed

+26
-16
lines changed

4 files changed

+26
-16
lines changed

CHANGES/11673.bugfix.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fixed routing to a sub-application added via ``.add_domain()`` not working
2+
if the same path exists on the parent app. -- by :user:`Dreamsorcerer`.

aiohttp/web_urldispatcher.py

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1034,6 +1034,21 @@ async def resolve(self, request: Request) -> UrlMappingMatchInfo:
10341034
resource_index = self._resource_index
10351035
allowed_methods: Set[str] = set()
10361036

1037+
# MatchedSubAppResource is primarily used to match on domain names
1038+
# (though custom rules could match on other things). This means that
1039+
# the traversal algorithm below can't be applied, and that we likely
1040+
# need to check these first so a sub app that defines the same path
1041+
# as a parent app will get priority if there's a domain match.
1042+
#
1043+
# For most cases we do not expect there to be many of these since
1044+
# currently they are only added by `.add_domain()`.
1045+
for resource in self._matched_sub_app_resources:
1046+
match_dict, allowed = await resource.resolve(request)
1047+
if match_dict is not None:
1048+
return match_dict
1049+
else:
1050+
allowed_methods |= allowed
1051+
10371052
# Walk the url parts looking for candidates. We walk the url backwards
10381053
# to ensure the most explicit match is found first. If there are multiple
10391054
# candidates for a given url part because there are multiple resources
@@ -1051,21 +1066,6 @@ async def resolve(self, request: Request) -> UrlMappingMatchInfo:
10511066
break
10521067
url_part = url_part.rpartition("/")[0] or "/"
10531068

1054-
#
1055-
# We didn't find any candidates, so we'll try the matched sub-app
1056-
# resources which we have to walk in a linear fashion because they
1057-
# have regex/wildcard match rules and we cannot index them.
1058-
#
1059-
# For most cases we do not expect there to be many of these since
1060-
# currently they are only added by `add_domain`
1061-
#
1062-
for resource in self._matched_sub_app_resources:
1063-
match_dict, allowed = await resource.resolve(request)
1064-
if match_dict is not None:
1065-
return match_dict
1066-
else:
1067-
allowed_methods |= allowed
1068-
10691069
if allowed_methods:
10701070
return MatchInfoError(HTTPMethodNotAllowed(request.method, allowed_methods))
10711071

docs/web_reference.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1625,6 +1625,14 @@ Application and Router
16251625
matches the pattern *domain* then
16261626
further resolving is passed to *subapp*.
16271627

1628+
.. warning::
1629+
1630+
Registering many domains using this method may cause performance
1631+
issues with handler routing. If you have a substantial number of
1632+
applications for different domains, you may want to consider
1633+
using a reverse proxy (such as Nginx) to handle routing to
1634+
different apps, rather that registering them as sub-applications.
1635+
16281636
:param str domain: domain or mask of domain for the resource.
16291637

16301638
:param Application subapp: nested application.

tests/test_web_urldispatcher.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -986,8 +986,8 @@ async def get(self) -> web.Response:
986986
await r.release()
987987

988988

989-
@pytest.mark.xfail(reason="https://github.com/aio-libs/aiohttp/issues/11665")
990989
async def test_subapp_domain_routing_same_path(aiohttp_client: AiohttpClient) -> None:
990+
"""Regression test for #11665."""
991991
app = web.Application()
992992
sub_app = web.Application()
993993

0 commit comments

Comments
 (0)