Transfer-encoding in http/1.0 got status code 400
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
- 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]
- 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
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.