From ed4246fcc1e52dc2fdc8cf068ce4a4aee972f0e1 Mon Sep 17 00:00:00 2001 From: florimondmanca Date: Wed, 11 Aug 2021 11:16:16 +0200 Subject: [PATCH] Unwrap view errors occurring under a BaseHTTPMiddleware --- starlette/middleware/base.py | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/starlette/middleware/base.py b/starlette/middleware/base.py index 77ba669251..5e9cee0b5f 100644 --- a/starlette/middleware/base.py +++ b/starlette/middleware/base.py @@ -34,7 +34,7 @@ async def coro() -> None: try: message = await recv_stream.receive() except anyio.EndOfStream: - raise RuntimeError("No response returned.") + raise RuntimeError("No response returned.") from None assert message["type"] == "http.response.start" @@ -50,11 +50,28 @@ async def body_stream() -> typing.AsyncGenerator[bytes, None]: response.raw_headers = message["headers"] return response - async with anyio.create_task_group() as task_group: - request = Request(scope, receive=receive) - response = await self.dispatch_func(request, call_next) - await response(scope, receive, send) - task_group.cancel_scope.cancel() + try: + async with anyio.create_task_group() as task_group: + request = Request(scope, receive=receive) + response = await self.dispatch_func(request, call_next) + await response(scope, receive, send) + task_group.cancel_scope.cancel() + except anyio.ExceptionGroup as exc_group: + first, *rest = exc_group.exceptions + if str(first) == "No response returned.": + # "No response returned", and we got an exception group, meaning + # the app raised an exception. + # Raise the latter in priority, so that we: + # a/ match the behavior before 0.16.0 (see regression #1255). + # b/ keep `anyio` as an implementation detail internally. + assert len(rest) == 1 + (exc,) = rest + raise exc from None + else: + # User may have used `anyio` directly and triggered an + # `ExceptionGroup` which they may want to manage themselves. + # Let it be. + raise async def dispatch( self, request: Request, call_next: RequestResponseEndpoint