Skip to content

HTTP/1.1 trailers are case-sensitive #4010

@pborzenkov

Description

@pborzenkov

Version
Hyper 1.8.1

Platform
Linux trance 6.10.10-arch1-1 #1 SMP PREEMPT_DYNAMIC Thu, 12 Sep 2024 17:21:02 +0000 x86_64 GNU/Linux

Description
It seems Hyper doesn't normalize trailer names declared via the Trailer header and won't send them if the trailers weren't declared in lowercase.

The following example doesn't produce any trailers, but if I declare the expected trailer name as trailer-1 instead of Trailer-1 the trailers are sent as expected.

use std::{convert::Infallible, net::SocketAddr};

use http_body_util::{BodyExt, Full, combinators::BoxBody};
use hyper::{
    HeaderMap, Request, Response,
    body::Bytes,
    header::{HeaderName, HeaderValue},
    service::service_fn,
};
use hyper_util::rt::{TokioIo, TokioTimer};
use tokio::net::TcpListener;

async fn hello(
    _: Request<impl hyper::body::Body>,
) -> Result<Response<BoxBody<Bytes, Infallible>>, Infallible> {
    let mut trailers = HeaderMap::new();
    trailers.insert(
        HeaderName::from_static("trailer-1"),
        HeaderValue::from_static("a-trailer-value"),
    );

    Ok(Response::builder()
        .header("transfer-encoding", "chunked")
        .header("trailer", "Trailer-1")
        .body(
            Full::new(Bytes::from("Hello World!"))
                .with_trailers(std::future::ready(Some(Ok(trailers))))
                .boxed(),
        )
        .unwrap())
}

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

    let listener = TcpListener::bind(addr).await?;
    println!("Listening on http://{}", addr);
    loop {
        let (tcp, _) = listener.accept().await?;

        let io = TokioIo::new(tcp);

        tokio::task::spawn(async move {
            if let Err(err) = hyper::server::conn::http1::Builder::new()
                .timer(TokioTimer::new())
                .serve_connection(io, service_fn(hello))
                .await
            {
                println!("Error serving connection: {:?}", err);
            }
        });
    }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-http1Area: HTTP/1 specific.C-bugCategory: bug. Something is wrong. This is bad!E-easyEffort: easy. A task that would be a great starting point for a new contributor.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions