hyper icon indicating copy to clipboard operation
hyper copied to clipboard

Transfer-encoding in http/1.0 got status code 400

Open blessingcharles opened this issue 3 years ago • 1 comments

Version

hyper = { version = "0.14", features = ["full"] } tokio = { version = "1", features = ["full"] }

Related to HTTP/1.0

Platform

DockerFile

    FROM rust
    WORKDIR /app
    COPY src /app/src
    COPY Cargo.toml .
    RUN cargo build --release
    CMD ["/app/target/release/hyper"]

Description

  1. In HTTP/1.0 , transfer-encoding: chunked is not defined according to rfc so the server can ignore it and if content-length header is present the server can parse the body with the help of it and most popular servers and proxies are doing like it .

[short summary of the bug]

  1. In hyper , if request is given with transfer-encoding header in http/1.0 the response received is 400

to-reproduce

echo -ne "GET / HTTP/1.0\r\nHost: localhost\r\nTransfer-Encoding: chunked\r\n\r\n2\r\naa\r\n0\r\n\r\n" | nc localhost 8002

[code sample that causes the bug]

use std::str;
use hyper::service::{make_service_fn, service_fn};
use hyper::{Body, Request, Response, Server};

async fn echo(req: Request<Body>) -> Result<Response<Body>, hyper::Error> {
    let whole_body = hyper::body::to_bytes(req.into_body()).await?;
    let mut answer: String = "Body length: ".to_owned();
    answer.push_str(&whole_body.len().to_string());
    answer.push_str(" Body: ");
    
    let s = match str::from_utf8(&whole_body) {
        Ok(v) => v,
        Err(_) => "error while converting request body to utf8",
    };

    answer.push_str(s);

    Ok(Response::new(Body::from(answer)))
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
    let addr = ([0, 0, 0, 0], 80).into();

    let service = make_service_fn(|_| async { Ok::<_, hyper::Error>(service_fn(echo)) });

    let server = Server::bind(&addr).serve(service);

    println!("Listening on http://{}", addr);

    server.await?;

    Ok(())
}

I expected to see this happen: Eventhough transfer-encoding chunked is present in http/1.0 , the request should not be rejected , most of popular servers do like it eg : nodejs , nginx , apache , actix .

Instead, this happened: Hyper reject the request with 400 status code

blessingcharles avatar May 30 '22 12:05 blessingcharles

Hm... I couldn't find in the spec where it says that HTTP/1.0 must reject a request, but it does say that it's should be assumed that 1.0 servers won't understand it. It's certainly not specified whether the body should be processed as a normal chunked, or if it should be assumed there is no body, and so because that is up to interpretation, I could easily see that become a channel to smuggle requests.

seanmonstar avatar Jun 03 '22 19:06 seanmonstar