diff --git a/fetch.bs b/fetch.bs index fa6deae20..6dca829f3 100755 --- a/fetch.bs +++ b/fetch.bs @@ -1651,6 +1651,74 @@ these steps: +
A trailer state is a struct used to represent +HTTP trailer fields received after a response body +([[HTTP]], Section 6.5). +It has: + +
A header list (a header list), + initially « ». + +
A state
+ ("pending", "complete", or "errored"),
+ initially "pending".
+
+
An error (null or a value), initially null. + +
An observers (a list of + algorithms), initially « ». +
A trailer state is shared by reference between a +response and its clones. + +
To complete a trailer state given a trailer state +trailerState: + +
+To error a trailer state given a trailer state +trailerState and a value reason: + +
+This section documents how requests work in detail. To get started, see @@ -2579,6 +2647,18 @@ message as HTTP/2 does not support them.
The source and length concepts of a network's response's body are always null. +
A response has an associated +trailer state +(a trailer state). Unless stated otherwise it is a new trailer state. + +
A response's +trailer header list +is its trailer state's header list. + +
The trailer state is shared by reference between a +response and its clones (see clone), ensuring trailer fields +received after cloning are visible to all copies. +
A response has an associated
cache state (the empty string,
"local", or "validated"). Unless stated otherwise, it is the empty
@@ -2692,17 +2772,23 @@ of defining the concrete types of filtered responses.)
A basic filtered response is a
filtered response whose
-type is "basic" and
+type is "basic",
header list excludes any
headers in
internal response's
header list whose
name is a
+forbidden response-header name, and
+trailer header list excludes any
+headers in
+internal response's
+trailer header list whose
+name is a
forbidden response-header name.
A CORS filtered response is a
filtered response whose
-type is "cors" and
+type is "cors",
header list excludes any
headers in
internal response's
@@ -2710,6 +2796,14 @@ of defining the concrete types of filtered responses.)
name is not a
CORS-safelisted response-header name, given
internal response's
+CORS-exposed header-name list, and
+trailer header list excludes any
+headers in
+internal response's
+trailer header list whose
+name is not a
+CORS-safelisted response-header name, given
+internal response's
CORS-exposed header-name list.
An opaque filtered response is a @@ -2719,6 +2813,7 @@ of defining the concrete types of filtered responses.) status is 0, status message is the empty byte sequence, header list is « », +trailer header list is « », body is null, and body info is a new response body info. @@ -2729,6 +2824,7 @@ is a filtered response whose status is 0, status message is the empty byte sequence, header list is « », +trailer header list is « », body is null, and body info is a new response body info. @@ -2781,7 +2877,10 @@ console.log((await fetch("/surprise-me", { redirect: "manual" })).type); // "opa internal response.
Let newResponse be a copy of response, except for its - body. + body and trailer state. + +
Set newResponse's trailer state to + response's trailer state.
If response's body is non-null, then set newResponse's body to the result of cloning @@ -5310,6 +5409,9 @@ steps:
Complete a trailer state given response's + trailer state. +
If fetchParams's process response end-of-body is non-null, then run fetchParams's process response end-of-body given response. @@ -5360,13 +5462,34 @@ steps: flushAlgorithm set to processResponseEndOfBody. -
Set internalResponse's body's stream to the - result of internalResponse's body's stream - piped through transformStream. +
Let readable be transformStream's + readable. + +
Let pipePromise be the result of + piping internalResponse's + body's stream to + transformStream's writable. + +
Upon rejection of pipePromise with + reason: + +
Error a trailer state given response's + trailer state and reason. +
This {{TransformStream}} is needed for the purpose of receiving a notification when - the stream reaches its end, and is otherwise an identity transform stream. +
The {{TransformStream}} receives a notification when the body + stream reaches its end (via the flush algorithm) or when it errors (via the + pipe promise rejection). On successful completion, + processResponseEndOfBody completes + the trailer state. On error, the trailer state is + errored, which rejects any pending + {{Response/trailers}} promises.
If fetchParams's process response consume body is @@ -6760,6 +6883,21 @@ optional boolean forceNewConnection (default false), run these steps:
Break. + +
If the HTTP response includes trailer fields + ([[HTTP]], Section 6.5), + then, after the response body has been fully transmitted, set + response's trailer header list to a + header list containing each received trailer field as a + header. + +
Trailer fields are received after the response body. The HTTP + layer is responsible for omitting trailer fields prohibited by HTTP semantics + (e.g., fields used in transfer codings, content framing, or routing). The + trailer header list is populated before + completing the trailer state + in the fetch response handover steps.
The exact layering between Fetch and HTTP still needs to be sorted through and @@ -8616,6 +8754,7 @@ interface Request { readonly attribute boolean isHistoryNavigation; readonly attribute AbortSignal signal; readonly attribute RequestDuplex duplex; + readonly attribute Promise<Headers> trailers; [NewObject] Request clone(); }; @@ -8663,6 +8802,9 @@ used or observed from JavaScript.
A {{Request}} object has an associated signal (null or an {{AbortSignal}} object), initially null. +
A {{Request}} object has an associated +trailers promise (null or a {{Promise}}), initially null. +
A {{Request}} object's body is its
request's
body.
@@ -8815,6 +8957,10 @@ object), initially null.
See issue #1254 for
defining "full".
+
request . trailers
+ Returns a promise that resolves to an empty immutable {{Headers}} object. Client-side + requests do not support sending trailer fields. +
request . clone()
Returns a clone of request. @@ -9287,6 +9433,32 @@ set; otherwise false.
The duplex getter steps are to return
"half".
+
The trailers getter steps are:
+
+
If this's trailers promise is null, then: + +
Let promise be a new promise. + +
Resolve promise with a new {{Headers}} object
+ whose header list is « » and whose guard is
+ "immutable".
+
+
Set this's trailers promise to promise. +
Return this's trailers promise. +
Client-side requests do not support sending trailer fields. The +{{Request/trailers}} attribute always returns a promise that resolves to empty +immutable {{Headers}}. This does not foreclose future extension to support sending +trailer fields. +
A {{Response}} object also has an associated headers (null or a {{Headers}} object), initially null. +
A {{Response}} object has an associated +trailers promise (null or a {{Promise}}), initially null. +
A {{Response}} object's body is its response's body. @@ -9394,8 +9570,20 @@ enum ResponseType { "basic", "cors", "default", "error", "opaque", "opaqueredire
response . headers
Returns response's headers as {{Headers}}. +
response . trailers
+ Returns a promise that resolves to {{Headers}} containing the response's trailer fields. + +
For responses obtained from {{WindowOrWorkerGlobalScope/fetch()}}, the promise resolves after the + response body has been fully received. For synthetically constructed responses (via the + {{Response/Response()}} constructor, {{Response/error()}}, {{Response/redirect()}}, or + {{Response/json()}}), the promise resolves immediately to empty immutable {{Headers}}. + +
If the response body stream errors, the promise is rejected. +
response . clone()
- Returns a clone of response. +
Returns a clone of response. The clone shares the same + trailer state, so both will receive the same trailer fields.
Perform initialize a response given this, init, and bodyWithType. + +
Complete a trailer state given this's response's + trailer state.
The static error() method steps are to return the
-result of creating a {{Response}} object, given a new network error,
-"immutable", and the current realm.
+
The static error() method steps are:
+
+
Let responseObject be the result of creating a {{Response}}
+ object, given a new network error, "immutable", and the current realm.
+
+
Complete a trailer state given responseObject's + response's trailer state. + +
Return responseObject. +
The static @@ -9518,6 +9719,9 @@ are:
Append (`Location`, value) to
responseObject's response's header list.
+
Complete a trailer state given responseObject's + response's trailer state. +
Return responseObject.
Perform initialize a response given responseObject, init, and
(body, "application/json").
+
Complete a trailer state given responseObject's + response's trailer state. +
Return responseObject. @@ -9574,6 +9781,72 @@ otherwise false.
The headers getter steps are to return
this's headers.
+
The trailers getter steps are:
+
+
If this's trailers promise is null, then: + +
Let trailerState be response's + trailer state. + +
Let promise be a new promise. + +
If trailerState's state is
+ "complete", then:
+
+
Let headers be a new {{Headers}} object whose
+ header list is response's
+ trailer header list and whose guard is
+ "immutable".
+
+
Resolve promise with headers. +
Otherwise, if trailerState's state is
+ "errored", then reject promise with
+ trailerState's error.
+
+
Otherwise (trailerState's state is
+ "pending"):
+
+
Append the following steps to trailerState's + observers: + +
If trailerState's state is
+ "complete", then:
+
+
Let headers be a new {{Headers}} object whose
+ header list is response's
+ trailer header list and whose guard is
+ "immutable".
+
+
Resolve promise with headers. +
Set this's trailers promise to promise. +
Return this's trailers promise. +
If response's body is non-null and is readable, then error response's body with error. + +
Error a trailer state given response's + trailer state and error.