Skip to content

Header names with capital letters are not deserialized #1373

Description

@JuliDi

Headers with (renamed) names that include capital letters fail to deserialize.

For example:

#[derive(Serialize, Deserialize, JsonSchema)]
pub struct MyHeaders {
    header_a: String,
    #[serde(rename = "X-Header-B")]
    header_b: String,
}

#[endpoint {
    method = GET,
    path = "/test",
}]
pub async fn get_test(
    rqctx: RequestContext<AppContext>,
    header_params: Header<MyHeaders>,
) -> Result<HttpResponseOk<()>, HttpError> {
    info!("rqctx headers: {:?}", rqctx.request.headers());
    let headers = header_params.into_inner();
    info!("Headers: {:?}, {:?}", headers.header_a, headers.header_b);

    Ok(HttpResponseOk(()))
}

Using the following request

Image

causes the following error:

thread 'tokio-runtime-worker' panicked at /home/user/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/dropshot-0.16.2/src/extractor/header.rs:53:44:
called `Result::unwrap()` on an `Err` value: "missing field `X-Header-B`"
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Jul 18 08:31:05.526 ERRO handler panicked; propogating panic, uri: /test, method: GET, req_id: 921b5a49-668e-4a6a-9e48-284ff37f91cb, remote_addr: 127.0.0.1:60506, local_addr: 127.0.0.1:8020

Removing the #[serde(rename = "X-Header-B")] reveals in the logs:

rqctx headers: {"accept": "application/json, text/plain, */*", "user-agent": "bruno-runtime/2.7.0", "header_a": "header_a value", "x-header-b": "header_b value", "header_b": "header_b value", "request-start-time": "1752827600143", "accept-encoding": "gzip, compress, deflate, br", "host": "localhost:8020", "connection": "keep-alive"}

So the error seems to be caused by "X-Header-B" being renamed to "x-header-b" in the request context. Since HTTP headers are not case-sensitive, I think deserialization should generally not be case sensitive either.

If someone could tell me where to best introduce this change, I am happy to make a PR for this.

As a workaround, it seems like it's sufficient to specify an alias, e.g. #[serde(rename = "X-Header-B", alias = "x-header-b")]

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions