diff --git a/homeassistant/components/http/__init__.py b/homeassistant/components/http/__init__.py index 04a8c13bba2..5a1d182e80c 100644 --- a/homeassistant/components/http/__init__.py +++ b/homeassistant/components/http/__init__.py @@ -18,11 +18,7 @@ from aiohttp.typedefs import JSONDecoder, StrOrURL from aiohttp.web_exceptions import HTTPMovedPermanently, HTTPRedirection from aiohttp.web_log import AccessLogger from aiohttp.web_protocol import RequestHandler -from aiohttp.web_urldispatcher import ( - AbstractResource, - UrlDispatcher, - UrlMappingMatchInfo, -) +from aiohttp_fast_url_dispatcher import FastUrlDispatcher, attach_fast_url_dispatcher from aiohttp_zlib_ng import enable_zlib_ng from cryptography import x509 from cryptography.hazmat.primitives import hashes, serialization @@ -321,7 +317,7 @@ class HomeAssistantHTTP: # By default aiohttp does a linear search for routing rules, # we have a lot of routes, so use a dict lookup with a fallback # to the linear search. - self.app._router = FastUrlDispatcher() + attach_fast_url_dispatcher(self.app, FastUrlDispatcher()) self.hass = hass self.ssl_certificate = ssl_certificate self.ssl_peer_certificate = ssl_peer_certificate @@ -587,40 +583,3 @@ async def start_http_server_and_save_config( ] store.async_delay_save(lambda: conf, SAVE_DELAY) - - -class FastUrlDispatcher(UrlDispatcher): - """UrlDispatcher that uses a dict lookup for resolving.""" - - def __init__(self) -> None: - """Initialize the dispatcher.""" - super().__init__() - self._resource_index: dict[str, list[AbstractResource]] = {} - - def register_resource(self, resource: AbstractResource) -> None: - """Register a resource.""" - super().register_resource(resource) - canonical = resource.canonical - if "{" in canonical: # strip at the first { to allow for variables - canonical = canonical.split("{")[0].rstrip("/") - # There may be multiple resources for a canonical path - # so we use a list to avoid falling back to a full linear search - self._resource_index.setdefault(canonical, []).append(resource) - - async def resolve(self, request: web.Request) -> UrlMappingMatchInfo: - """Resolve a request.""" - url_parts = request.rel_url.raw_parts - resource_index = self._resource_index - - # Walk the url parts looking for candidates - for i in range(len(url_parts), 0, -1): - url_part = "/" + "/".join(url_parts[1:i]) - if (resource_candidates := resource_index.get(url_part)) is not None: - for candidate in resource_candidates: - if ( - match_dict := (await candidate.resolve(request))[0] - ) is not None: - return match_dict - - # Finally, fallback to the linear search - return await super().resolve(request) diff --git a/homeassistant/components/http/manifest.json b/homeassistant/components/http/manifest.json index dffd1dd1d8c..f2f8b51665a 100644 --- a/homeassistant/components/http/manifest.json +++ b/homeassistant/components/http/manifest.json @@ -6,5 +6,9 @@ "integration_type": "system", "iot_class": "local_push", "quality_scale": "internal", - "requirements": ["aiohttp_cors==0.7.0", "aiohttp-zlib-ng==0.1.1"] + "requirements": [ + "aiohttp_cors==0.7.0", + "aiohttp-fast-url-dispatcher==0.1.0", + "aiohttp-zlib-ng==0.1.1" + ] } diff --git a/homeassistant/package_constraints.txt b/homeassistant/package_constraints.txt index 37cb51d4178..03dd947e098 100644 --- a/homeassistant/package_constraints.txt +++ b/homeassistant/package_constraints.txt @@ -1,4 +1,5 @@ aiodiscover==1.5.1 +aiohttp-fast-url-dispatcher==0.1.0 aiohttp-zlib-ng==0.1.1 aiohttp==3.8.5;python_version<'3.12' aiohttp==3.9.0b0;python_version>='3.12' diff --git a/pyproject.toml b/pyproject.toml index 4b079aed093..550cafc4146 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -26,6 +26,7 @@ dependencies = [ "aiohttp==3.9.0b0;python_version>='3.12'", "aiohttp==3.8.5;python_version<'3.12'", "aiohttp_cors==0.7.0", + "aiohttp-fast-url-dispatcher==0.1.0", "aiohttp-zlib-ng==0.1.1", "astral==2.2", "attrs==23.1.0", diff --git a/requirements.txt b/requirements.txt index 324217b0f55..1ca4643a747 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,6 +4,7 @@ aiohttp==3.9.0b0;python_version>='3.12' aiohttp==3.8.5;python_version<'3.12' aiohttp_cors==0.7.0 +aiohttp-fast-url-dispatcher==0.1.0 aiohttp-zlib-ng==0.1.1 astral==2.2 attrs==23.1.0 diff --git a/requirements_all.txt b/requirements_all.txt index cc6be993d08..72fe9df3370 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -257,6 +257,9 @@ aioharmony==0.2.10 # homeassistant.components.homekit_controller aiohomekit==3.0.9 +# homeassistant.components.http +aiohttp-fast-url-dispatcher==0.1.0 + # homeassistant.components.http aiohttp-zlib-ng==0.1.1 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 0fbde65a23f..34a82175d01 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -235,6 +235,9 @@ aioharmony==0.2.10 # homeassistant.components.homekit_controller aiohomekit==3.0.9 +# homeassistant.components.http +aiohttp-fast-url-dispatcher==0.1.0 + # homeassistant.components.http aiohttp-zlib-ng==0.1.1