From cb1a25398495f44d0b45bee3b6c8398ede0d4c87 Mon Sep 17 00:00:00 2001 From: James M Snell Date: Sat, 11 Jul 2026 12:09:13 -0700 Subject: [PATCH] Add onInformation interim response support Adds an optional fetch call for receiving 1xx responses in a fetch. e.g. ```js fetch('...', { onInformation(status, headers) { // status is the 1xx code // headers is the Headers object }, }); ``` Support is entirely optional. Implementations that currently would ignore `onInformation` are fully compliant. --- fetch.bs | 163 +++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 129 insertions(+), 34 deletions(-) diff --git a/fetch.bs b/fetch.bs index fa6deae20..f070ddb26 100755 --- a/fetch.bs +++ b/fetch.bs @@ -222,6 +222,7 @@ lt="authentication entry">authentication entries (for HTTP authentication). (default null)
process request end-of-body (default null)
process early hints response (default null) +
process informational response (default null)
process response (default null)
process response end-of-body (default null)
process response consume body (default null) @@ -4628,6 +4629,7 @@ optional algorithm optional algorithm processRequestEndOfBody, an optional algorithm processEarlyHintsResponse, an optional +algorithm processInformationalResponse, an optional algorithm processResponse, an optional algorithm processResponseEndOfBody, an optional algorithm processResponseConsumeBody, @@ -4636,7 +4638,9 @@ the steps below. If given, processRequestBodyChunkLength must be an a an integer representing the number of bytes transmitted. If given, processRequestEndOfBody must be an algorithm accepting no arguments. If given, processEarlyHintsResponse must be an algorithm accepting a response. If -given, processResponse must be an algorithm accepting a response. If given, +given, processInformationalResponse must be an algorithm accepting a +response. If given, +processResponse must be an algorithm accepting a response. If given, processResponseEndOfBody must be an algorithm accepting a response. If given, processResponseConsumeBody must be an algorithm accepting a response and null, failure, or a byte sequence. @@ -4658,7 +4662,8 @@ the response. [[!HTTP-CACHING]] processEarlyHintsResponse is null.

Processing of early hints (responses whose status - is 103) is only vetted for navigations. + is 103) via processEarlyHintsResponse is only vetted for navigations. + The general processInformationalResponse callback has no such restriction.

  • Let taskDestination be null. @@ -4700,6 +4705,7 @@ the response. [[!HTTP-CACHING]] processRequestBodyChunkLength, process request end-of-body is processRequestEndOfBody, process early hints response is processEarlyHintsResponse, + process informational response is processInformationalResponse, process response is processResponse, process response consume body is processResponseConsumeBody, process response end-of-body is processResponseEndOfBody, @@ -6730,33 +6736,41 @@ optional boolean forceNewConnection (default false), run these steps:

  • Let status be the HTTP response's status code. -

  • -

    If status is in the range 100 to 199, inclusive: - - -

      -
    1. If timingInfo's - first interim network-response start time is 0, then set - timingInfo's - first interim network-response start time to - timingInfo's final network-response start time. - -

    2. If request's mode is "websocket" and - status is 101, then break. - -

    3. If status is 103 and fetchParams's - process early hints response is non-null, then - queue a fetch task to run fetchParams's - process early hints response, with response. - -

    4. Continue. -

    - -

    These kind of HTTP responses are eventually followed by a "final" HTTP - response. +

  • +

    If status is in the range 100 to 199, inclusive: + +

      +
    1. If timingInfo's + first interim network-response start time is 0, then set + timingInfo's + first interim network-response start time to + timingInfo's final network-response start time. + +

    2. If fetchParams's + process informational response is non-null, then + the implementation MAY queue a fetch task to run + fetchParams's + process informational response given + response. + +

    3. If status is 103 and fetchParams's + process early hints response is non-null, then + queue a fetch task to run fetchParams's + process early hints response given + response. + +

    4. If request's mode is "websocket" and + status is 101, then break. + +

    5. Continue. +

    + +

    These kind of HTTP responses are eventually followed by a "final" HTTP + response. The process informational response + callback is invoked for all informational responses, including 100 (Continue), + 101 (Switching Protocols), 102 (Processing), and 103 (Early Hints). + Support for invoking this callback is entirely optional; implementations that + never invoke it are fully compliant with this specification.

  • Break. @@ -8621,6 +8635,8 @@ interface Request { }; Request includes Body; +callback InformationalCallback = undefined (unsigned short status, Headers headers); + dictionary RequestInit { ByteString method; HeadersInit headers; @@ -8636,6 +8652,7 @@ dictionary RequestInit { AbortSignal? signal; RequestDuplex duplex; RequestPriority priority; + InformationalCallback onInformation; any window; // can only be set to null }; @@ -8742,6 +8759,12 @@ object), initially null.

    {{RequestInit/priority}}
    A string to set request's priority. + +
    {{RequestInit/onInformation}} +
    A callback invoked when an informational response (HTTP 1xx) is received. The callback + receives the 1xx status code and an immutable {{Headers}} object containing the informational + response's headers, appropriately filtered. Any return value is ignored. Implementations are + not required to support informational responses and may ignore this option entirely.
    request . method @@ -9682,8 +9705,78 @@ method steps are:
  • -

    Set controller to the result of calling fetch given - request and processResponse given response being +

    Let processInformationalResponse be null. + +

  • +

    If init["{{RequestInit/onInformation}}"] exists, then set + processInformationalResponse to the following steps given a response + response: + +

      +
    1. If locallyAborted is true, then return. + +

    2. Let headerList be a new header list. + +

    3. +

      If request's response tainting is + "basic", then for each header of response's + header list, if header's name + is not a forbidden response-header name, then + append header to headerList. + +

    4. +

      Otherwise, if request's response tainting is + "cors", then: + +

        +
      1. Let headerNames be the result of + extracting header list values given + `Access-Control-Expose-Headers` and response's + header list. + +

      2. If headerNames is not null and is not failure, and + request's credentials mode is not + "include", and headerNames contains + `*`, then for each header of response's + header list, if header's name + is not a forbidden response-header name, then + append header to headerList. + +

      3. +

        Otherwise: + +

          +
        1. If headerNames is null or failure, then set + headerNames to « ». + +

        2. For each header of response's + header list, if header's name + is a CORS-safelisted response-header name given headerNames, + then append header to + headerList. +

        +
      + +
    5. +

      If request's response tainting is + "opaque", headerList remains empty. + +

    6. Let headers be a new {{Headers}} object with + requestObject's relevant realm, whose + header list is headerList and whose + guard is "immutable". + +

    7. Invoke + init["{{RequestInit/onInformation}}"] with + « response's status, headers ». +

    + +
  • +

    Set controller to the result of calling fetch given + request, with + processInformationalResponse set to + processInformationalResponse and + processResponse given response being these steps:

      @@ -10345,9 +10438,11 @@ particular at what stage you would like to receive a callback:

      Apart from the callbacks to handle responses, fetch accepts additional callbacks -for advanced cases. processEarlyHintsResponse is intended specifically for -responses whose status is 103, and is currently handled only by -navigations. processRequestBodyChunkLength and +for advanced cases. processInformationalResponse is invoked for HTTP +informational responses (1xx status codes) and is exposed to JavaScript through the +{{RequestInit/onInformation}} option. processEarlyHintsResponse is +intended specifically for responses whose status is 103, and is +currently handled only by navigations. processRequestBodyChunkLength and processRequestEndOfBody notify the caller of request body uploading progress.