diff --git a/CHANGES/5233.bugfix b/CHANGES/5233.bugfix new file mode 100644 index 00000000000..ab5544cec3c --- /dev/null +++ b/CHANGES/5233.bugfix @@ -0,0 +1 @@ +Fix cookies disappearing from HTTPExceptions. diff --git a/aiohttp/web_protocol.py b/aiohttp/web_protocol.py index 8d5cbaa15cb..dd44d41c18d 100644 --- a/aiohttp/web_protocol.py +++ b/aiohttp/web_protocol.py @@ -420,9 +420,7 @@ async def _handle_request( finally: self._current_request = None except HTTPException as exc: - resp = Response( - status=exc.status, reason=exc.reason, text=exc.text, headers=exc.headers - ) + resp = exc reset = await self.finish_response(request, resp, start_time) except asyncio.CancelledError: raise @@ -434,6 +432,15 @@ async def _handle_request( resp = self.handle_error(request, 500, exc) reset = await self.finish_response(request, resp, start_time) else: + # Deprecation warning (See #2415) + if getattr(resp, "__http_exception__", False): + warnings.warn( + "returning HTTPException object is deprecated " + "(#2415) and will be removed, " + "please raise the exception instead", + DeprecationWarning, + ) + reset = await self.finish_response(request, resp, start_time) return resp, reset @@ -492,14 +499,6 @@ async def start(self) -> None: except (asyncio.CancelledError, ConnectionError): self.log_debug("Ignored premature client disconnection") break - # Deprecation warning (See #2415) - if getattr(resp, "__http_exception__", False): - warnings.warn( - "returning HTTPException object is deprecated " - "(#2415) and will be removed, " - "please raise the exception instead", - DeprecationWarning, - ) # Drop the processed task from asyncio.Task.all_tasks() early del task diff --git a/tests/test_web_exceptions.py b/tests/test_web_exceptions.py index 33b5a4f240a..2b32db05d6b 100644 --- a/tests/test_web_exceptions.py +++ b/tests/test_web_exceptions.py @@ -204,3 +204,31 @@ def test_HTTPException_retains_cause() -> None: tb = "".join(format_exception(ei.type, ei.value, ei.tb)) assert "CustomException" in tb assert "direct cause" in tb + + +async def test_HTTPException_retains_cookie(aiohttp_client): + @web.middleware + async def middleware(request, handler): + try: + return await handler(request) + except web.HTTPException as exc: + exc.set_cookie("foo", request["foo"]) + raise exc + + async def save(request): + request["foo"] = "works" + raise web.HTTPFound("/show") + + async def show(request): + return web.Response(text=request.cookies["foo"]) + + app = web.Application(middlewares=[middleware]) + app.router.add_route("GET", "/save", save) + app.router.add_route("GET", "/show", show) + client = await aiohttp_client(app) + + resp = await client.get("/save") + assert resp.status == 200 + assert str(resp.url)[-5:] == "/show" + text = await resp.text() + assert text == "works"