Skip to content

Sending trailers#1941

Open
jasnell wants to merge 2 commits into
whatwg:mainfrom
jasnell:jasnell/send-trailers
Open

Sending trailers#1941
jasnell wants to merge 2 commits into
whatwg:mainfrom
jasnell:jasnell/send-trailers

Conversation

@jasnell

@jasnell jasnell commented Jul 11, 2026

Copy link
Copy Markdown

Adds an option for sending trailing header fields. Ensures that the mechanism is entirely optional for implementers, and all existing implementations that just don't handle trailers should be out-of-the-box compliant.

Builds on #1940 (the first commit in here is from that PR)


  • At least two implementers are interested (and none opposed):
  • Tests are written and can be reviewed and commented upon at:
  • Implementation bugs are filed:
    • Chromium: …
    • Gecko: …
    • WebKit: …
    • Deno (not for CORS changes): …
  • MDN issue is filed: …
  • The top of this comment includes a clear commit message to use.

(See WHATWG Working Mode: Changes for more details.)


💥 Error: 422 Unprocessable Entity 💥

PR Preview failed to build. (Last tried on Jul 11, 2026, 5:59 PM UTC).

More

PR Preview relies on a number of web services to run. There seems to be an issue with the following one:

🚨 Spec Generator - Spec Generator is the web service used to build bikeshed/ReSpec specs

🔗 Related URL

Error output:

[
    {
        "lineNum": "1676:17",
        "messageType": "link",
        "text": "Multiple possible 'dfn' local refs for 'trailer state'.\nRandomly chose one of them; other instances might get a different random choice."
    },
    {
        "lineNum": "1681:51",
        "messageType": "link",
        "text": "Multiple possible 'dfn' local refs for 'trailer state'.\nRandomly chose one of them; other instances might get a different random choice."
    },
    {
        "lineNum": "1701:48",
        "messageType": "link",
        "text": "Multiple possible 'dfn' local refs for 'trailer state'.\nRandomly chose one of them; other instances might get a different random choice."
    },
    {
        "lineNum": "1724:50",
        "messageType": "link",
        "text": "Multiple possible 'dfn' local refs for 'trailer state'.\nRandomly chose one of them; other instances might get a different random choice."
    },
    {
        "lineNum": "2466:4",
        "messageType": "link",
        "text": "Multiple possible 'dfn' local refs for 'trailer state'.\nRandomly chose one of them; other instances might get a different random choice."
    },
    {
        "lineNum": "2466:63",
        "messageType": "link",
        "text": "Multiple possible 'dfn' local refs for 'trailer state'.\nRandomly chose one of them; other instances might get a different random choice."
    },
    {
        "lineNum": "2751:4",
        "messageType": "link",
        "text": "Multiple possible 'dfn' local refs for 'trailer state'.\nRandomly chose one of them; other instances might get a different random choice."
    },
    {
        "lineNum": "2751:63",
        "messageType": "link",
        "text": "Multiple possible 'dfn' local refs for 'trailer state'.\nRandomly chose one of them; other instances might get a different random choice."
    },
    {
        "lineNum": "9514:48",
        "messageType": "link",
        "text": "Multiple possible 'dfn' local refs for 'trailer state'.\nRandomly chose one of them; other instances might get a different random choice."
    },
    {
        "lineNum": "6996:7",
        "messageType": "lint",
        "text": "RFC2119 keyword in non-normative section (use: might, can, has to, or override with <span class=allow-2119>): Sending trailer fields is entirely optional.\n      Implementations that do not support sending trailer fields are fully\n      compliant with this specification. The "
    },
    {
        "lineNum": "6996:7",
        "messageType": "lint",
        "text": "RFC2119 keyword in non-normative section (use: might, can, has to, or override with <span class=allow-2119>):  algorithm (which is called during\n      request construction), so implementations that ignore the trailer state\n      do not cause unhandled promise rejections.\n      Whether or not to actually forward trailer fields is an implementation\n      decision, consistent with how HTTP intermediaries may forward, discard,\n      or store trailer fields\n      ("
    },
    {
        "lineNum": "9012:4",
        "messageType": "lint",
        "text": "RFC2119 keyword in non-normative section (use: might, can, has to, or override with <span class=allow-2119>):  providing trailer fields to send after the\n   request body. Trailer field names must be pre-declared in the `"
    },
    {
        "lineNum": "9012:4",
        "messageType": "lint",
        "text": "RFC2119 keyword in non-normative section (use: might, can, has to, or override with <span class=allow-2119>): ` header;\n   undeclared trailer fields are silently dropped. Implementations are not required to send\n   trailer fields and may ignore this option entirely.\n  "
    },
    {
        "lineNum": "9099:3",
        "messageType": "lint",
        "text": "RFC2119 keyword in non-normative section (use: might, can, has to, or override with <span class=allow-2119>):  promise, not the timing of body\n  transmission. This may indirectly reveal when payload processing completes if\n  the caller ties the promise to body consumption (e.g., computing a digest over\n  the body stream), but this timing is controlled by the caller, not the\n  implementation.\n\n "
    },
    {
        "lineNum": "1795:7",
        "messageType": "lint",
        "text": "Unexported dfn for 'ignore a trailers init' that's not referenced locally - did you mean to export it?"
    },
    {
        "lineNum": null,
        "messageType": "failure",
        "text": "Did not generate, due to errors exceeding the allowed error level."
    }
]

This seems to be an issue with the Spec Generator service. PR Preview doesn't manage this service and so has no control over it. If you've identified an issue with it, you can report the issue to the maintainers of Spec Generator directly. Please be courteous. Thank you!

If you don't have enough information above to solve the error by yourself or if the issue doesn't seem related to Spec Generator, you can file an issue with PR Preview.

jasnell added 2 commits July 11, 2026 10:08
Adds `Promise<Headers>` `trailers` properties to `Request` and
`Response`

When sending... `trailers` resolves to an empty, immutable
`Headers` since we're not dealing with sending trailers in
this change.

When receiving... `trailers` resolves to an immutable,
populated/filtered `Headers` resolved after the body
is completed. This means the trailers promise will not
resolve if the body is not consumed.
Adds a new constructor option to both `Request` and `Response`
that allows sending trailing header fields:

```js
async function trailersReady() {
  // ...
  return { "X-Checksum": '...' };
}

const response = new Response(readable, {
  headers: { "Trailer": "X-Checksum" },
  trailers: trailersReady(),
});
```

It is defined such that support is entirely optional.
A conformant implementation can simply ignore the
option entirely, meaning all existing implementations
are ok out of the box. An implementation that chooses
to at least pay some attention to the option but not
actually send the headers should at least mark the
promise as handled to avoid unhandled rejection warnings,
but that would be the minimum support requirement.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant