starlette: TestClient.request does not honor stream=True

Checklist

  • The bug is reproducible against the latest release and/or master.
  • There are no similar issues or pull requests to fix it yet.

Describe the bug

The requests.request interface exposes an stream=True option which results on the call not waiting for the entire body to arrive. stream=True is not handled properly by starlette.testclient._ASGIAdapter.send, as it is unconditionally waiting for the entire request to finish:

https://github.com/encode/starlette/blob/e4307065ea6dbe708fba9643d14fe7adfff06d46/starlette/testclient.py#L240

To reproduce

  1. Perform an event wait asyncio.Event wait() after your ASGI application responds with your headers (http.response.start) and first chunk (http.response.body), this can be easily done inside the generator passed to starlette.StreamingResponse.
  2. Set the event viaasyncio.Event set() only after doing the request with stream=True.
  3. Deadlock.

Expected behavior

With stream=True, TestClient.request should return right after first http.response.body (asgiref defines server must sent http.response.start headers only after the first http.response.body event is generated).

Streaming-related response methods (like iter_content) should be implemented via awaiting further http.response.body until more_body is missing or False.

Actual behavior

Deadlock.

Additional context

I suspect #533 could be related to this.

[!IMPORTANT]

  • We’re using Polar.sh so you can upvote and help fund this issue.
  • We receive the funding once the issue is completed & confirmed by you.
  • Thank you in advance for helping prioritize & fund our backlog.
<picture> <source media="(prefers-color-scheme: dark)" srcset="https://polar.sh/api/github/encode/starlette/issues/1102/pledge.svg?darkmode=1"> Fund with Polar </picture>

About this issue

  • Original URL
  • State: open
  • Created 4 years ago
  • Reactions: 2
  • Comments: 21 (14 by maintainers)

Most upvoted comments

You’re suggesting I try httpx-sse, as in that example, correct? @Kludex

yes