How do I handle Expect: 100-continue when using BodyDataStream?
#3625
-
SummaryThe code contains a POST endpoint that reads the request body and sends a response body in parallel, allowing clients without access to a decent WebSocket client to process arbitrarily large jobs without having to manually break them up into smaller jobs. The issue is that when using curl with a large payload, curl sends an The timeline when using
What I need to do is somehow inject a "URL Cleaner Site notices the While I can pass axum version0.8.8 |
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 5 replies
-
|
Can you try |
Beta Was this translation helpful? Give feedback.
-
|
(Using port 9148 because my main instance is on 9149 but it's the same thing) h2 is at 0.4.13, not that it's relevant here. Edit: I probably should clarify that I'm using a slightly updated version of the linked code that fixes a few bugs, but this particular issue behaves identically between the two versions. Just saying that now in case a proposed fix works on the linked code but not on my local copy. |
Beta Was this translation helpful? Give feedback.
-
|
@Scripter17 this is a timing issue in hyper's 100-continue mechanism. it's not a bug, just a consequence of your handler's architecture. why it happens: hyper automatically sends extractors like fix: poll the body once before returning the response use futures_util::StreamExt;
pub async fn clean_http(
State(state): State<&'static crate::State>,
job: Job<'static>,
body: Body,
) -> Result<Response, (StatusCode, &'static str)> {
let mut stream = body.into_data_stream();
let first_chunk = stream.next().await; // triggers 100-continue
let full_stream = futures_util::stream::iter(first_chunk)
.chain(stream);
tokio::spawn(async move {
let mut reader = full_stream
.map_err(std::io::Error::other)
.into_async_read();
// ... rest of your line-by-line reading ...
});
// return streaming response after body has been polled
Ok(Body::from_stream(/* ... */).into_response())
}the then ref: hyper PR #2119 (100-continue-on-first-poll design) | axum #863 (confirms poll triggers 100-continue) | hyper #3827 (related issue) |
Beta Was this translation helpful? Give feedback.
@Scripter17 this is a timing issue in hyper's 100-continue mechanism. it's not a bug, just a consequence of your handler's architecture.
why it happens: hyper automatically sends
100 Continuewhen the request body is first polled viapoll_frame, but only if the response headers haven't been written yet (Writing::Initstate). in your handler, you move the body intotokio::spawnand return a streaming response immediately. hyper sees the response is ready, writes the 200 headers (Writingtransitions toBody), and by the time your spawned task polls the body, theWriting::Initcheck inpoll_read_bodyfails and 100-continue is skipped.extractors like
BytesorJsonwork because they consume t…