diff --git a/CHANGES/7869.bugfix b/CHANGES/7869.bugfix new file mode 100644 index 00000000000..23282fc3bb4 --- /dev/null +++ b/CHANGES/7869.bugfix @@ -0,0 +1 @@ +Fix ClientResponse.close releasing the connection instead of closing diff --git a/aiohttp/client_reqrep.py b/aiohttp/client_reqrep.py index f05a08637f2..21858fc345a 100644 --- a/aiohttp/client_reqrep.py +++ b/aiohttp/client_reqrep.py @@ -967,7 +967,9 @@ def close(self) -> None: return self._cleanup_writer() - self._release_connection() + if self._connection is not None: + self._connection.close() + self._connection = None def release(self) -> Any: if not self._released: diff --git a/tests/test_client_functional.py b/tests/test_client_functional.py index 38983244097..4f0d594cb1f 100644 --- a/tests/test_client_functional.py +++ b/tests/test_client_functional.py @@ -20,6 +20,7 @@ from aiohttp import Fingerprint, ServerFingerprintMismatch, hdrs, web from aiohttp.abc import AbstractResolver from aiohttp.client_exceptions import TooManyRedirects +from aiohttp.pytest_plugin import AiohttpClient, TestClient from aiohttp.test_utils import unused_port @@ -3175,6 +3176,39 @@ async def handler(request): await client.get("/") +async def test_read_timeout_closes_connection(aiohttp_client: AiohttpClient) -> None: + request_count = 0 + + async def handler(request): + nonlocal request_count + request_count += 1 + if request_count < 3: + await asyncio.sleep(0.5) + return web.Response(body=f"request:{request_count}") + + app = web.Application() + app.add_routes([web.get("/", handler)]) + + timeout = aiohttp.ClientTimeout(total=0.1) + client: TestClient = await aiohttp_client(app, timeout=timeout) + with pytest.raises(asyncio.TimeoutError): + await client.get("/") + + # Make sure its really closed + assert not client.session.connector._conns + + with pytest.raises(asyncio.TimeoutError): + await client.get("/") + + # Make sure its really closed + assert not client.session.connector._conns + result = await client.get("/") + assert await result.read() == b"request:3" + + # Make sure its not closed + assert client.session.connector._conns + + async def test_read_timeout_on_prepared_response(aiohttp_client: Any) -> None: async def handler(request): resp = aiohttp.web.StreamResponse()