reqwest icon indicating copy to clipboard operation
reqwest copied to clipboard

`Response::chunk(...)` will return `Ok(Some([]))` before returning `Ok(None)` at the end of the response under certain circumstances

Open richardstephens opened this issue 2 months ago • 2 comments

When processing a response body one response.chunk() at a time, sometimes a single Ok(Some([])) (0-byte chunk) will be returned before the response starts returning Ok(None).

I am not 100% certain exactly what causes this but it seems to require both rustls and http2 to be enabled, and also be dependant on the remote server and the response being large enough.

here is a simple reproducer case

[package]
name = "httpbugtest"
version = "0.1.0"
edition = "2024"

[dependencies]
reqwest = { version = "0.12.24", default-features = false, features = ["rustls-tls", "rustls-tls-webpki-roots", "http2"] }
tokio = { version = "1.48.0", features = ["macros", "rt-multi-thread"] }
#[tokio::main]
async fn main() {
    let client = reqwest::Client::new();
    let mut response = client
        .get("https://bunny.net/")
        .send().await.unwrap();

    let mut total_bytes = 0;
    while let Some(chunk) = response.chunk().await.unwrap() {
        total_bytes += chunk.len();
        if chunk.len() == 0 {
            eprintln!("Zero-length chunk received at offset={total_bytes}");
        }
    }
    eprintln!("Total bytes received: {}", total_bytes);
}

richardstephens avatar Oct 20 '25 18:10 richardstephens

Hi, it's possible and sometimes expected. Please don't treat a 0-size chunk as the termination; read until you reach None.

Xuanwo avatar Oct 20 '25 18:10 Xuanwo

@Xuanwo I found the behaviour surprising. I believe it should be called out in the documentation even if it is not considered a bug. I am happy to open a PR.

richardstephens avatar Oct 20 '25 18:10 richardstephens