From 1c1ba22e6186006852792aa5fda929fb49cb3b37 Mon Sep 17 00:00:00 2001 From: Vizonex Date: Sun, 26 Oct 2025 14:21:10 -0500 Subject: [PATCH 1/8] add parser and writer factories to prepare for future http protocol support --- aiohttp/client_proto.py | 14 +++++++++++--- aiohttp/client_reqrep.py | 14 ++++++++++++-- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/aiohttp/client_proto.py b/aiohttp/client_proto.py index 144cb42d52b..21958b843a2 100644 --- a/aiohttp/client_proto.py +++ b/aiohttp/client_proto.py @@ -1,6 +1,6 @@ import asyncio from contextlib import suppress -from typing import Any +from typing import Any, Callable from .base_protocol import BaseProtocol from .client_exceptions import ( @@ -22,10 +22,15 @@ from .streams import EMPTY_PAYLOAD, DataQueue, StreamReader + class ResponseHandler(BaseProtocol, DataQueue[tuple[RawResponseMessage, StreamReader]]): """Helper class to adapt between Protocol and StreamReader.""" - def __init__(self, loop: asyncio.AbstractEventLoop) -> None: + def __init__( + self, + loop: asyncio.AbstractEventLoop, + parser_factory: type[HttpResponseParser] = HttpResponseParser + ) -> None: BaseProtocol.__init__(self, loop=loop) DataQueue.__init__(self, loop) @@ -39,6 +44,9 @@ def __init__(self, loop: asyncio.AbstractEventLoop) -> None: self._tail = b"" self._upgraded = False + # parser_factory is important because it will + # allow for other protocols to be added in the future. + self._parser_factory = parser_factory self._parser: HttpResponseParser | None = None self._read_timeout: float | None = None @@ -237,7 +245,7 @@ def set_response_params( self._timeout_ceil_threshold = timeout_ceil_threshold - self._parser = HttpResponseParser( + self._parser = self._parser_factory( self, self._loop, read_bufsize, diff --git a/aiohttp/client_reqrep.py b/aiohttp/client_reqrep.py index 0d6f435b6e5..b062cd89fc2 100644 --- a/aiohttp/client_reqrep.py +++ b/aiohttp/client_reqrep.py @@ -705,7 +705,7 @@ class ClientRequestBase: method = "GET" _writer_task: asyncio.Task[None] | None = None # async task for streaming data - + _writer_factory: type[StreamWriter] = StreamWriter # allowing http/2 and http/3 _skip_auto_headers: "CIMultiDict[None] | None" = None # N.B. @@ -723,6 +723,8 @@ def __init__( loop: asyncio.AbstractEventLoop, ssl: SSLContext | bool | Fingerprint, trust_env: bool = False, + writer_factory:type[StreamWriter] | None = None, + version: HttpVersion | None = None ): if match := _CONTAINS_CONTROL_CHAR_RE.search(method): raise ValueError( @@ -743,6 +745,13 @@ def __init__( self._update_host(url) self._update_headers(headers) self._update_auth(auth, trust_env) + + # setup incase of newer protocols. + if version: + self.version = version + + if writer_factory: + self._writer_factory = writer_factory def _reset_writer(self, _: object = None) -> None: self._writer_task = None @@ -848,11 +857,12 @@ def _create_response(self, task: asyncio.Task[None] | None) -> ClientResponse: ) def _create_writer(self, protocol: BaseProtocol) -> StreamWriter: - return StreamWriter(protocol, self.loop) + return self._writer_factory(protocol, self.loop) def _should_write(self, protocol: BaseProtocol) -> bool: return protocol.writing_paused + # TODO: Make _send swappable for http/2 or http/3 ? async def _send(self, conn: "Connection") -> ClientResponse: # Specify request target: # - CONNECT request must send authority form URI From 2dd236f1dcb9b9376a325261cc37208d137dbc2e Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 26 Oct 2025 19:33:31 +0000 Subject: [PATCH 2/8] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- aiohttp/client_proto.py | 11 +++++------ aiohttp/client_reqrep.py | 8 ++++---- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/aiohttp/client_proto.py b/aiohttp/client_proto.py index 21958b843a2..b2f842c306d 100644 --- a/aiohttp/client_proto.py +++ b/aiohttp/client_proto.py @@ -22,15 +22,14 @@ from .streams import EMPTY_PAYLOAD, DataQueue, StreamReader - class ResponseHandler(BaseProtocol, DataQueue[tuple[RawResponseMessage, StreamReader]]): """Helper class to adapt between Protocol and StreamReader.""" def __init__( - self, - loop: asyncio.AbstractEventLoop, - parser_factory: type[HttpResponseParser] = HttpResponseParser - ) -> None: + self, + loop: asyncio.AbstractEventLoop, + parser_factory: type[HttpResponseParser] = HttpResponseParser, + ) -> None: BaseProtocol.__init__(self, loop=loop) DataQueue.__init__(self, loop) @@ -44,7 +43,7 @@ def __init__( self._tail = b"" self._upgraded = False - # parser_factory is important because it will + # parser_factory is important because it will # allow for other protocols to be added in the future. self._parser_factory = parser_factory self._parser: HttpResponseParser | None = None diff --git a/aiohttp/client_reqrep.py b/aiohttp/client_reqrep.py index b062cd89fc2..505bfe30934 100644 --- a/aiohttp/client_reqrep.py +++ b/aiohttp/client_reqrep.py @@ -705,7 +705,7 @@ class ClientRequestBase: method = "GET" _writer_task: asyncio.Task[None] | None = None # async task for streaming data - _writer_factory: type[StreamWriter] = StreamWriter # allowing http/2 and http/3 + _writer_factory: type[StreamWriter] = StreamWriter # allowing http/2 and http/3 _skip_auto_headers: "CIMultiDict[None] | None" = None # N.B. @@ -723,8 +723,8 @@ def __init__( loop: asyncio.AbstractEventLoop, ssl: SSLContext | bool | Fingerprint, trust_env: bool = False, - writer_factory:type[StreamWriter] | None = None, - version: HttpVersion | None = None + writer_factory: type[StreamWriter] | None = None, + version: HttpVersion | None = None, ): if match := _CONTAINS_CONTROL_CHAR_RE.search(method): raise ValueError( @@ -745,7 +745,7 @@ def __init__( self._update_host(url) self._update_headers(headers) self._update_auth(auth, trust_env) - + # setup incase of newer protocols. if version: self.version = version From 51d699c33c42fa6ded1afaace070112cc08f3291 Mon Sep 17 00:00:00 2001 From: Vizonex Date: Sun, 26 Oct 2025 14:38:56 -0500 Subject: [PATCH 3/8] add change to timeline --- CHANGES/11717.feature.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 CHANGES/11717.feature.rst diff --git a/CHANGES/11717.feature.rst b/CHANGES/11717.feature.rst new file mode 100644 index 00000000000..0f65a7f92ce --- /dev/null +++ b/CHANGES/11717.feature.rst @@ -0,0 +1 @@ +Add parser factory to :class:`ResponseHandler` and a writer factory to :class:`ClientRequestBase` to prepare for future protocol support -- by :user:`Vizonex` \ No newline at end of file From 1e9c147eb60cb10a172cbb3d6551262bfaa2b674 Mon Sep 17 00:00:00 2001 From: Vizonex Date: Sun, 26 Oct 2025 14:39:23 -0500 Subject: [PATCH 4/8] add change to timeline --- aiohttp/client_proto.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aiohttp/client_proto.py b/aiohttp/client_proto.py index 21958b843a2..bdeda299a83 100644 --- a/aiohttp/client_proto.py +++ b/aiohttp/client_proto.py @@ -1,6 +1,6 @@ import asyncio from contextlib import suppress -from typing import Any, Callable +from typing import Any from .base_protocol import BaseProtocol from .client_exceptions import ( From 4984edeba7f5c8c734e12b0575e7410e746ac1f0 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 26 Oct 2025 19:40:15 +0000 Subject: [PATCH 5/8] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- CHANGES/11717.feature.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES/11717.feature.rst b/CHANGES/11717.feature.rst index 0f65a7f92ce..6427e00fba2 100644 --- a/CHANGES/11717.feature.rst +++ b/CHANGES/11717.feature.rst @@ -1 +1 @@ -Add parser factory to :class:`ResponseHandler` and a writer factory to :class:`ClientRequestBase` to prepare for future protocol support -- by :user:`Vizonex` \ No newline at end of file +Add parser factory to :class:`ResponseHandler` and a writer factory to :class:`ClientRequestBase` to prepare for future protocol support -- by :user:`Vizonex` From 9165e47fea21e649a6c6c126c660afd584660402 Mon Sep 17 00:00:00 2001 From: Vizonex Date: Thu, 30 Oct 2025 12:17:20 -0500 Subject: [PATCH 6/8] fix 11717 rst file --- CHANGES/11717.feature.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES/11717.feature.rst b/CHANGES/11717.feature.rst index 6427e00fba2..100466b3335 100644 --- a/CHANGES/11717.feature.rst +++ b/CHANGES/11717.feature.rst @@ -1 +1 @@ -Add parser factory to :class:`ResponseHandler` and a writer factory to :class:`ClientRequestBase` to prepare for future protocol support -- by :user:`Vizonex` +Add parser factory to :class:`aiohttp.client_proto.ResponseHandler` and a writer factory to :class:`aiohttp.client_reqrep.ClientRequestBase` to prepare for future protocol support -- by :user:`Vizonex` From 3642ee2e49e24c2f43fc4b728aa82050b524ad70 Mon Sep 17 00:00:00 2001 From: Vizonex Date: Thu, 30 Oct 2025 12:19:57 -0500 Subject: [PATCH 7/8] fix spelling mistake --- aiohttp/client_reqrep.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aiohttp/client_reqrep.py b/aiohttp/client_reqrep.py index a51bd45f5f3..bcae4daf962 100644 --- a/aiohttp/client_reqrep.py +++ b/aiohttp/client_reqrep.py @@ -742,7 +742,7 @@ def __init__( self._update_headers(headers) self._update_auth(auth, trust_env) - # setup incase of newer protocols. + # setup in case of newer protocols. if version: self.version = version From 747a81eaf3649fc58fb5e38f9dd4807404714642 Mon Sep 17 00:00:00 2001 From: Vizonex Date: Thu, 30 Oct 2025 12:22:57 -0500 Subject: [PATCH 8/8] forget class labels for now --- CHANGES/11717.feature.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES/11717.feature.rst b/CHANGES/11717.feature.rst index 100466b3335..e38b91fc804 100644 --- a/CHANGES/11717.feature.rst +++ b/CHANGES/11717.feature.rst @@ -1 +1 @@ -Add parser factory to :class:`aiohttp.client_proto.ResponseHandler` and a writer factory to :class:`aiohttp.client_reqrep.ClientRequestBase` to prepare for future protocol support -- by :user:`Vizonex` +Add parser factory to response handler and a writer factory to client request base to prepare for future protocol support -- by :user:`Vizonex`