diff --git a/CHANGES/10714.misc.rst b/CHANGES/10714.misc.rst new file mode 100644 index 00000000000..a36a80872f5 --- /dev/null +++ b/CHANGES/10714.misc.rst @@ -0,0 +1 @@ +Improved web server performance when connection can be reused -- by :user:`bdraco`. diff --git a/aiohttp/test_utils.py b/aiohttp/test_utils.py index 84813124ecb..569baf7c32d 100644 --- a/aiohttp/test_utils.py +++ b/aiohttp/test_utils.py @@ -675,6 +675,10 @@ def make_mocked_request( if protocol is None: protocol = mock.Mock() protocol.transport = transport + type(protocol).peername = mock.PropertyMock( + return_value=transport.get_extra_info("peername") + ) + type(protocol).ssl_context = mock.PropertyMock(return_value=sslcontext) if writer is None: writer = mock.Mock() diff --git a/aiohttp/web_protocol.py b/aiohttp/web_protocol.py index d162a729f54..38d49ceeb30 100644 --- a/aiohttp/web_protocol.py +++ b/aiohttp/web_protocol.py @@ -24,6 +24,7 @@ ) import yarl +from propcache import under_cached_property from .abc import AbstractAccessLogger, AbstractAsyncAccessLogger, AbstractStreamWriter from .base_protocol import BaseProtocol @@ -47,6 +48,8 @@ __all__ = ("RequestHandler", "RequestPayloadError", "PayloadAccessError") if TYPE_CHECKING: + import ssl + from .web_server import Server @@ -189,6 +192,7 @@ class RequestHandler(BaseProtocol, Generic[_Request]): "_current_request", "_timeout_ceil_threshold", "_request_in_progress", + "_cache", ) def __init__( @@ -275,6 +279,7 @@ def __init__( self._close = False self._force_close = False self._request_in_progress = False + self._cache: dict[str, Any] = {} def __repr__(self) -> str: return "<{} {}>".format( @@ -282,6 +287,26 @@ def __repr__(self) -> str: "connected" if self.transport is not None else "disconnected", ) + @under_cached_property + def ssl_context(self) -> Optional["ssl.SSLContext"]: + """Return SSLContext if available.""" + return ( + None + if self.transport is None + else self.transport.get_extra_info("sslcontext") + ) + + @under_cached_property + def peername( + self, + ) -> Optional[Union[str, Tuple[str, int, int, int], Tuple[str, int]]]: + """Return peername if available.""" + return ( + None + if self.transport is None + else self.transport.get_extra_info("peername") + ) + @property def keepalive_timeout(self) -> float: return self._keepalive_timeout diff --git a/aiohttp/web_request.py b/aiohttp/web_request.py index 48eb9814114..48cf0d2f229 100644 --- a/aiohttp/web_request.py +++ b/aiohttp/web_request.py @@ -179,10 +179,8 @@ def __init__( self._client_max_size = client_max_size self._loop = loop - transport = protocol.transport - assert transport is not None - self._transport_sslcontext = transport.get_extra_info("sslcontext") - self._transport_peername = transport.get_extra_info("peername") + self._transport_sslcontext = protocol.ssl_context + self._transport_peername = protocol.peername if remote is not None: self._cache["remote"] = remote diff --git a/requirements/base.txt b/requirements/base.txt index ffb6b8d43da..3ee6eae233f 100644 --- a/requirements/base.txt +++ b/requirements/base.txt @@ -16,7 +16,7 @@ brotli==1.1.0 ; platform_python_implementation == "CPython" # via -r requirements/runtime-deps.in cffi==1.17.1 # via pycares -frozenlist==1.5.0 +frozenlist==1.6.0 # via # -r requirements/runtime-deps.in # aiosignal diff --git a/requirements/constraints.txt b/requirements/constraints.txt index eebec0b6741..003ddb2018c 100644 --- a/requirements/constraints.txt +++ b/requirements/constraints.txt @@ -78,7 +78,7 @@ freezegun==1.5.1 # via # -r requirements/lint.in # -r requirements/test.in -frozenlist==1.5.0 +frozenlist==1.6.0 # via # -r requirements/runtime-deps.in # aiosignal diff --git a/requirements/dev.txt b/requirements/dev.txt index 314eb9f0263..891638a1ebd 100644 --- a/requirements/dev.txt +++ b/requirements/dev.txt @@ -76,7 +76,7 @@ freezegun==1.5.1 # via # -r requirements/lint.in # -r requirements/test.in -frozenlist==1.5.0 +frozenlist==1.6.0 # via # -r requirements/runtime-deps.in # aiosignal diff --git a/requirements/runtime-deps.txt b/requirements/runtime-deps.txt index b8f8d7c7717..11100abb6a6 100644 --- a/requirements/runtime-deps.txt +++ b/requirements/runtime-deps.txt @@ -16,7 +16,7 @@ brotli==1.1.0 ; platform_python_implementation == "CPython" # via -r requirements/runtime-deps.in cffi==1.17.1 # via pycares -frozenlist==1.5.0 +frozenlist==1.6.0 # via # -r requirements/runtime-deps.in # aiosignal diff --git a/requirements/test.txt b/requirements/test.txt index 54aa275a9fa..3b4b8aa76eb 100644 --- a/requirements/test.txt +++ b/requirements/test.txt @@ -39,7 +39,7 @@ forbiddenfruit==0.1.4 # via blockbuster freezegun==1.5.1 # via -r requirements/test.in -frozenlist==1.5.0 +frozenlist==1.6.0 # via # -r requirements/runtime-deps.in # aiosignal