Skip to content

Adding headers with multiple casings of the same field name #787

Open

Description

@wingo

WhatWG fetch specifies that if there is an existing header Foo: 42, and you go to append foo: 69, the lower-case header name is first corrected to the casing of the existing Foo: https://fetch.spec.whatwg.org/#concept-header-list-append

I understand that one goal of wasi-http is to be implementable in terms of whatwg fetch. This constrains us, in that we can't support both the contract of append and copy-all:

   /// Append a value for a name. Does not change or delete any existing
    /// values for that name.
    ///
    /// Fails with `header-error.immutable` if the `fields` are immutable.
    append: func(name: field-name, value: field-value) -> result<_, header-error>;
    /// Retrieve the full set of names and values in the Fields. Like the
    /// constructor, the list represents each name-value pair.
    ///
    /// The outer list represents each name-value pair in the Fields. Names
    /// which have multiple values are represented by multiple entries in this
    /// list with the same name.
    ///
    /// The names and values are always returned in the original casing and in
    /// the order in which they will be serialized for transport.
    copy-all: func() -> list<tuple<field-name, field-value>>;

I suggest that we adopt to make set and append operations first adapt the case of the field-name to any existing field-name.

Activity

  1. lann commented on Sep 2, 2025

    @lann
    Contributor

    Would it be sufficient to say that set and append may change the case of name?

    I'd also be interested in the origin of this:

        /// The names and values are always returned in the original casing and in
        /// the order in which they will be serialized for transport.
    

    It seems like that could be relaxed quite a bit.

  2. lann commented on Sep 2, 2025

    @lann
    Contributor

    @lukewagner seems to be the source of this requirement: WebAssembly/wasi-http#117 (comment)

    The fields resource remembers the original case of field names (exactly as passed to set or as came in over the wire), and this remembered-case is what goes out over the wire. This is what the JS Fetch API specifies because it was found necessary in practice for various interop scenarios.

  3. tschneidereit commented on Sep 2, 2025

    @tschneidereit
    Member

    It's possible that this can be relaxed, and if the current requirements create undue implementation burdens for anything that is not fetch, then that might be the right call, too.

    I do want to highlight though that as a spec, WASI is more in the same boat as WHATWG than the HTTP spec: we want code tested against one implementation to work in other implementations, too—almost all of which is written by people who have no understanding of the details of HTTP semantics.

    All that is to say that where WHATWG chose to define certain requirements, they might've done so because not doing so would've been an interop hazard for content running in browsers. That might mean that those same hazards exist for us, too. (It's of course also entirely possible that some of this is more opinionated than it needs to be!)

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    P-httpProposal: wasi-http

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions