Search code examples
httprusthyper

How to send chunked transfer-encoded hyper response?


I am trying to send a hyper response with a specific number of bytes and chunks. I've been lost on how to generate a generic chunked response or set the transfer-encoding header. There seemed to be a httpWriter/chunkedWriter for hyper which is now depreciated.

This is my attempt, but the transfer-encoding header is not being set and I don't believe that this is the right way to have a chunked response.

let chunked_body = "5\r\nhello\r\n5\r\n worl\r\n1\r\nd\r\n0\r\n\r\n";
let mut resp: hyper::Response<Body> = Response::new(Body::from(chunked_body));
resp.headers_mut().insert(TRANSFER_ENCODING, HeaderValue::from_static("Chunked"));
Ok(resp)

Solution

  • Chunked transfer encoding is part of HTTP/1.1, and not part of HTTP/2. When a handler responds with a chunked stream, Hyper will do the "right thing" depending on which HTTP version the client supports.

    For example, the following will send a chunked response in HTTP/1.1 but use data frames if clients support HTTP/2:

    async fn handle(_req: Request<Body>) -> Result<Response<Body>, Infallible> {
        let chunked_body = vec!["Hello", ", ", "worl", "d", "!"];
        let stream = stream::iter(chunked_body.into_iter().map(Result::<_, Infallible>::Ok));
        let body = Body::wrap_stream(stream);
        Ok(Response::new(body))
    }
    

    The headers on this response (when forcing HTTP/1.1 on the client) are:

    HTTP/1.1 200 OK
    transfer-encoding: chunked
    

    If you wish to only support HTTP/1.1, you can specify that on the Server builder, with Builder::http1_only(true).