You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
When using a StreamingResponse and, by extension, any custom middleware (any subclass of BaseHTTPMiddleware) with Starlette 0.13.3, with the async httpx client directly connected to the app (i.e. httpx.AsyncClient(app=...)), Starlette responses never complete. This did not happen with Starlette 0.13.2.
Minimal-ish test case:
With starlette==0.13.3, httpx==0.12.1, and pytest + pytest-asyncio:
Actual behaviour:
The await client.get() call never returns/completes.
Stacktrace:
If you hit ctrl-c while the test is stuck you get a long stacktrace. But the important bits I believe are:
File "/Users/jamie/.virtualenvs/tempenv-51153646622a/lib/python3.7/site-packages/starlette/responses.py", line 202, in listen_for_disconnect
message = await receive()
File "/Users/jamie/.virtualenvs/tempenv-51153646622a/lib/python3.7/site-packages/httpx/_dispatch/asgi.py", line 78, in receive
body = await request_body_chunks.__anext__()
Suspected cause:
Starlette calls both the receive() (to check for disconnects) and send() (to send the response) concurrently in its StreamingResponse type (since #839). It tries to wait for either of those two options to complete (using asyncio.wait({tasks}, return_when=asyncio.FIRST_COMPLETED)). Because the ASGI dispatch in httpx is generally effectively synchronous, both send() and receive() may never return control to the event loop when called which means that if either task that is waited on does not complete, then asyncio.wait() will not return and the program will remain stuck in an infinite loop inside the StreamingResponse.listen_for_disconnect method.
The text was updated successfully, but these errors were encountered:
I think this will actually impact anything that involves a StreamingResponse. Confirmed this applies to any StreamingResponse. Updated the issue title and description.
When using a
StreamingResponse
and, by extension, any custom middleware (any subclass ofBaseHTTPMiddleware
) with Starlette 0.13.3, with the async httpx client directly connected to the app (i.e.httpx.AsyncClient(app=...)
), Starlette responses never complete. This did not happen with Starlette 0.13.2.Minimal-ish test case:
With
starlette==0.13.3
,httpx==0.12.1
, and pytest + pytest-asyncio:Expected behaviour:
The test passes
Actual behaviour:
The
await client.get()
call never returns/completes.Stacktrace:
If you hit ctrl-c while the test is stuck you get a long stacktrace. But the important bits I believe are:
Suspected cause:
Starlette calls both the
receive()
(to check for disconnects) andsend()
(to send the response) concurrently in itsStreamingResponse
type (since #839). It tries to wait for either of those two options to complete (usingasyncio.wait({tasks}, return_when=asyncio.FIRST_COMPLETED)
). Because the ASGI dispatch in httpx is generally effectively synchronous, bothsend()
andreceive()
may never return control to the event loop when called which means that if either task that is waited on does not complete, thenasyncio.wait()
will not return and the program will remain stuck in an infinite loop inside theStreamingResponse.listen_for_disconnect
method.The text was updated successfully, but these errors were encountered: