From 6da1d71c6e5ae8d259ca736c312dfa92d7b254e6 Mon Sep 17 00:00:00 2001 From: Andrew Svetlov Date: Sat, 20 Jul 2019 11:16:09 +0300 Subject: [PATCH] [3.5] Close session on error in aiohttp.request (#3628) (#3640) (#3917) (cherry picked from commit 20bfadcb) Co-authored-by: Robert Nikolich --- CHANGES/3628.bugfix | 1 + CONTRIBUTORS.txt | 1 + aiohttp/client.py | 9 +++++++-- tests/test_client_functional.py | 18 ++++++++++++++++++ 4 files changed, 27 insertions(+), 2 deletions(-) create mode 100644 CHANGES/3628.bugfix diff --git a/CHANGES/3628.bugfix b/CHANGES/3628.bugfix new file mode 100644 index 00000000000..22be2a07d27 --- /dev/null +++ b/CHANGES/3628.bugfix @@ -0,0 +1 @@ +Close session created inside ``aiohttp.request`` when unhandled exception occurs diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt index 504c81bde43..2caf3d195e5 100644 --- a/CONTRIBUTORS.txt +++ b/CONTRIBUTORS.txt @@ -192,6 +192,7 @@ Rafael Viotti Raúl Cumplido Required Field Robert Lu +Robert Nikolich Roman Podoliaka Samuel Colvin Sean Hunt diff --git a/aiohttp/client.py b/aiohttp/client.py index cdd61e59857..392466663fb 100644 --- a/aiohttp/client.py +++ b/aiohttp/client.py @@ -1048,8 +1048,13 @@ def __init__(self, self._session = session async def __aenter__(self) -> ClientResponse: - self._resp = await self._coro - return self._resp + try: + self._resp = await self._coro + except BaseException: + await self._session.close() + raise + else: + return self._resp async def __aexit__(self, exc_type: Optional[Type[BaseException]], diff --git a/tests/test_client_functional.py b/tests/test_client_functional.py index 52901afa0cb..9a6a0ac718d 100644 --- a/tests/test_client_functional.py +++ b/tests/test_client_functional.py @@ -2383,6 +2383,24 @@ async def handler(request): assert resp.status == 200 +async def test_aiohttp_request_ctx_manager_close_sess_on_error( + ssl_ctx, aiohttp_server) -> None: + async def handler(request): + return web.Response() + + app = web.Application() + app.router.add_get('/', handler) + server = await aiohttp_server(app, ssl=ssl_ctx) + + cm = aiohttp.request('GET', server.make_url('/')) + + with pytest.raises(aiohttp.ClientConnectionError): + async with cm: + pass + + assert cm._session.closed + + async def test_aiohttp_request_ctx_manager_not_found() -> None: with pytest.raises(aiohttp.ClientConnectionError):