http-rs / surf

Fast and friendly HTTP client framework for async Rust
https://docs.rs/surf
Apache License 2.0
1.46k stars 120 forks source link

400 Bad Request on Windows 10 #175

Closed mihai-dinculescu closed 4 years ago

mihai-dinculescu commented 4 years ago
#[async_std::main]
async fn main() {
    let res = surf::get("https://globalcdn.nuget.org/packages/win2d.uwp.1.25.0.nupkg")
        .await
        .unwrap();
    assert_eq!(res.status(), 200);
}

Returns 400 - Bad Request on Windows 10. In WSL or other OSs (I imagine) it returns 200, as expected.

Surf 1.0.3 with default features & rustc 1.43.1.

tim-weis commented 4 years ago

I was able to reproduce the issue on Windows 10. Switching to the reqwest crate produced the desired 200 response:

[dependencies]
reqwest = { version = "0.10", features = ["blocking"] }
fn main() {
    let resp =
        reqwest::blocking::get("https://globalcdn.nuget.org/packages/win2d.uwp.1.25.0.nupkg")
            .unwrap();
    println!("{:#?}", resp);
}

I wasn't able to get my debug environment into shape to look into the asynchronous implementation to see where things go wrong.

zhzy0077 commented 4 years ago

I did the investigation and will paste the long reason later. Here is the workaround(Yes, adding the content-length header manually):

#[async_std::main]
async fn main() {
    let res = surf::get("https://globalcdn.nuget.org/packages/win2d.uwp.1.25.0.nupkg")
        .set_header("Content-Length", "0")
        .await
        .unwrap();
    assert_eq!(res.status(), 200);
}
zhzy0077 commented 4 years ago

The reason cause this issue is: at last stable version 1.0.3, surf uses the following code to invoke the isahc: let body = isahc::Body::reader(body);. It will make isahc to place a 'Transfer-Encoding', 'chuecked' header, thus causing this issue:

    /// Create a streaming body that reads from the given reader.
    ///
    /// The body will have an unknown length. When used as a request body,
    /// chunked transfer encoding might be used to send the request.
    pub fn from_reader(read: impl AsyncRead + Send + Sync + 'static) -> Self {
        Body(Inner::AsyncRead(Box::pin(read), None))
    }

From: https://github.com/sagebind/isahc/blob/master/src/body.rs#L100

I believe it's fixed by this commit https://github.com/http-rs/http-client/commit/86223b976ecdb8fef78c48b2d70089090f03762d#diff-5f9a78c705c3d5bd9ffa2d115d3085ac. You can either set the content-length manually or pick an alpha version surf = "2.0.0-alpha.4". Both works fine for me.

yoshuawuyts commented 4 years ago

We're gearing up for a 2.0.0 proper release to get us off the -alpha release channel. Hopefully that'll resolve this issue.

Going to close this for now since it's already been released and published, @zhzy0077's answer here is correct. Let us know if this is still an issue and we can reopen.