Is sending and receiving at the same time breaking the rules? #1004
Replies: 1 comment
|
What you are describing is possible at the protocol level, but it is not generally safe to get it by simply putting _send_request_body() in an asyncio task. HTTP/1.1 permits a server to send a final response before the request body has completed. Expect: 100-continue is the standardized mechanism specifically intended to let a client wait before sending a potentially large body. But full-duplex application streaming over HTTP/1.1 has awkward semantics: once the final response arrives the client may need to stop producing the request body, and connection reuse depends on both sides ending in a valid framing/state-machine state. The current httpcore ordering is deliberate and simple: send headers -> send the complete request body -> receive response headers. Moving only the body sender into a background task creates several ownership problems that handle_request currently does not have to solve:
HTTP/2 is structurally much better suited to bidirectional streaming, but httpcore's current HTTP/2 implementation also performs the body send before awaiting response headers, so its public request API does not currently expose full duplex either. If the actual goal is "don't upload a large body when the server will reject it", Expect: 100-continue support is the narrower feature (see the separate discussion about that). If the goal is true simultaneous request/response streaming, that needs an API/lifecycle design where the send task is owned and cleaned up as part of the response stream, rather than a detached create_task inside handle_request. |
Uh oh!
There was an error while loading. Please reload this page.
httpcore/httpcore/_async/http11.py
Lines 83 to 112 in 38f277c
Of course, it's not the norm, so it can't be a change in the library, but it's pure curiosity. I was writing a program the other day that streams some data to a server, and the server processes the data and responds as a client. As I was writing it, I realized that unlike in my head, most clients can't process the response until all the bodies are sent(because it's blocked at line 88 of the above code). Below is a small snippet of code using fastapi and httpx that implemented my idea.
In this code, the server sends a response as soon as it receives the first body, but the client doesn't get the response (the response object is available after 90 seconds!). What if we replaced that code with the following?
(Of course, this is experimental code, and concurrency can be disastrous for debugging and error-handling)
In this case, you can fill a certain buffer of responses and get a response even before you finish sending your request! What I'm wondering is if this mechanism violates the protocol of HTTP(the timing of returning a response), or if it could actually cause other threats in the code.
All reactions