The goal is to unify fetching across the web platform and provide consistent handling of everything that involves, including:
Referer
` [REFERRER]To do so it also supersedes the HTTP `Origin
` header semantics originally defined in The Web Origin Concept. [ORIGIN]
At a high level, fetching a resource is a fairly simple operation. A request goes in, a response comes out. The details of that operation are however quite involved and used to not be written down carefully and differ from one API to the next.
Numerous APIs provide the ability to fetch a resource, e.g. HTML’s img
and script
element, CSS' cursor
and list-style-image
, the navigator.sendBeacon()
and self.importScripts()
JavaScript APIs. The Fetch Standard provides a unified architecture for these features so they are all consistent when it comes to various aspects of fetching, such as redirects and the CORS protocol.
The Fetch Standard also defines the fetch()
JavaScript API, which exposes most of the networking functionality at a fairly low level of abstraction.
This specification depends on the Infra Standard. [INFRA]
This specification uses terminology from ABNF, Encoding, HTML, HTTP, MIME Sniffing, Streams, URL, Web IDL, and WebSockets. [ABNF] [ENCODING] [HTML] [HTTP] [MIMESNIFF] [STREAMS] [URL] [WEBIDL] [WEBSOCKETS]
ABNF means ABNF as augmented by HTTP (in particular the addition of #
) and RFC 7405. [RFC7405]
Credentials are HTTP cookies, TLS client certificates, and authentication entries (for HTTP authentication). [COOKIES] [TLS] [HTTP]
A fetch params is a struct used as a bookkeeping detail by the fetch algorithm. It has the following items:
pending
", or a response.
A fetch controller is a struct used to enable callers of fetch to perform certain operations on it after it has started. It has the following items:
ongoing
")
ongoing
", "terminated
", or "aborted
"
To deserialize a serialized abort reason, given null or a Record abortReason and a realm realm:
Let fallbackError be an "AbortError
" DOMException
.
Let deserializedError be fallbackError.
If abortReason is non-null, then set deserializedError to StructuredDeserialize(abortReason, realm). If that threw an exception or returned undefined, then set deserializedError to fallbackError.
Return deserializedError.
To terminate a fetch controller controller, set controller’s state to "terminated
".
A fetch params fetchParams is aborted if its controller’s state is "aborted
".
A fetch params fetchParams is canceled if its controller’s state is "aborted
" or "terminated
".
A fetch timing info is a struct used to maintain timing information needed by Resource Timing and Navigation Timing. It has the following items: [RESOURCE-TIMING] [NAVIGATION-TIMING]
DOMHighResTimeStamp
.
A response body info is a struct used to maintain information needed by Resource Timing and Navigation Timing. It has the following items: [RESOURCE-TIMING] [NAVIGATION-TIMING]
To create an opaque timing info, given a fetch timing info timingInfo, return a new fetch timing info whose start time and post-redirect start time are timingInfo’s start time.
To serialize an integer, represent it as a string of the shortest possible decimal number.
This will be replaced by a more descriptive algorithm in Infra. See infra/201.
2.1. URLA local scheme is "about
", "blob
", or "data
".
A URL is local if its scheme is a local scheme.
This definition is also used by Referrer Policy. [REFERRER]
An HTTP(S) scheme is "http
" or "https
".
A fetch scheme is "about
", "blob
", "data
", "file
", or an HTTP(S) scheme.
HTTP(S) scheme and fetch scheme are also used by HTML. [HTML]
2.2. HTTPWhile fetching encompasses more than just HTTP, it borrows a number of concepts from HTTP and applies these to resources obtained via other means (e.g., data
URLs).
An HTTP tab or space is U+0009 TAB or U+0020 SPACE.
HTTP whitespace is U+000A LF, U+000D CR, or an HTTP tab or space.
HTTP whitespace is only useful for specific constructs that are reused outside the context of HTTP headers (e.g., MIME types). For HTTP header values, using HTTP tab or space is preferred, and outside that context ASCII whitespace is preferred. Unlike ASCII whitespace this excludes U+000C FF.
An HTTP newline byte is 0x0A (LF) or 0x0D (CR).
An HTTP tab or space byte is 0x09 (HT) or 0x20 (SP).
An HTTP whitespace byte is an HTTP newline byte or HTTP tab or space byte.
To collect an HTTP quoted string from a string input, given a position variable position and an optional boolean extract-value (default false):
Let positionStart be position.
Let value be the empty string.
Assert: the code point at position within input is U+0022 (").
Advance position by 1.
While true:
Append the result of collecting a sequence of code points that are not U+0022 (") or U+005C (\) from input, given position, to value.
If position is past the end of input, then break.
Let quoteOrBackslash be the code point at position within input.
Advance position by 1.
If quoteOrBackslash is U+005C (\), then:
If position is past the end of input, then append U+005C (\) to value and break.
Append the code point at position within input to value.
Advance position by 1.
Otherwise:
If extract-value is true, then return value.
Return the code points from positionStart to position, inclusive, within input.
"\
" ""\
" "\
" 2 ""Hello" World
" ""Hello"
" "Hello
" 7 ""Hello \\ World\""
" ""Hello \\ World\""
" "Hello \ World"
" 18
The position variable always starts at 0 in these examples.
2.2.1. MethodsA method is a byte sequence that matches the method token production.
A CORS-safelisted method is a method that is `GET
`, `HEAD
`, or `POST
`.
A forbidden method is a method that is a byte-case-insensitive match for `CONNECT
`, `TRACE
`, or `TRACK
`. [HTTPVERBSEC1], [HTTPVERBSEC2], [HTTPVERBSEC3]
To normalize a method, if it is a byte-case-insensitive match for `DELETE
`, `GET
`, `HEAD
`, `OPTIONS
`, `POST
`, or `PUT
`, byte-uppercase it.
Normalization is done for backwards compatibility and consistency across APIs as methods are actually "case-sensitive".
Using `patch
` is highly likely to result in a `405 Method Not Allowed
`. `PATCH
` is much more likely to succeed.
There are no restrictions on methods. `CHICKEN
` is perfectly acceptable (and not a misspelling of `CHECKIN
`). Other than those that are normalized there are no casing restrictions either. `Egg
` or `eGg
` would be fine, though uppercase is encouraged for consistency.
HTTP generally refers to a header as a "field" or "header field". The web platform uses the more colloquial term "header". [HTTP]
A is a list of zero or more headers. It is initially « ».
A header list is essentially a specialized multimap: an ordered list of key-value pairs with potentially duplicate keys. Since headers other than `Set-Cookie
` are always combined when exposed to client-side JavaScript, implementations could choose a more efficient representation, as long as they also support an associated data structure for `Set-Cookie
` headers.
A header list list a header name name if list contains a header whose name is a byte-case-insensitive match for name.
To get, decode, and split a header value value, run these steps. They return a list of strings.
Let input be the result of isomorphic decoding value.
Let position be a position variable for input, initially pointing at the start of input.
Let temporaryValue be the empty string.
While true:
Append the result of collecting a sequence of code points that are not U+0022 (") or U+002C (,) from input, given position, to temporaryValue.
The result might be the empty string.
If position is not past the end of input and the code point at position within input is U+0022 ("):
Append the result of collecting an HTTP quoted string from input, given position, to temporaryValue.
Remove all HTTP tab or space from the start and end of temporaryValue.
Append temporaryValue to values.
Set temporaryValue to the empty string.
If position is past the end of input, then return values.
Assert: the code point at position within input is U+002C (,).
Advance position by 1.
Except for blessed call sites, the algorithm directly above is not to be invoked directly. Use get, decode, and split instead.
To a header name name from a header list list, remove all headers whose name is a byte-case-insensitive match for name from list.
A is a tuple that consists of a (a header name) and (a header value).
A is a byte sequence that matches the field-name token production.
A is a byte sequence that matches the following conditions:
Has no leading or trailing HTTP tab or space bytes.
Contains no 0x00 (NUL) or HTTP newline bytes.
The definition of header value is not defined in terms of the field-value token production as it is not compatible with deployed content.
To a byte sequence potentialValue, remove any leading and trailing HTTP whitespace bytes from potentialValue.
If value’s length is greater than 128, then return false.
Byte-lowercase name and switch on the result:
accept
`
If value contains a CORS-unsafe request-header byte, then return false.
accept-language
`
content-language
`
If value contains a byte that is not in the range 0x30 (0) to 0x39 (9), inclusive, is not in the range 0x41 (A) to 0x5A (Z), inclusive, is not in the range 0x61 (a) to 0x7A (z), inclusive, and is not 0x20 (SP), 0x2A (*), 0x2C (,), 0x2D (-), 0x2E (.), 0x3B (;), or 0x3D (=), then return false.
content-type
`
If value contains a CORS-unsafe request-header byte, then return false.
Let mimeType be the result of parsing the result of isomorphic decoding value.
If mimeType is failure, then return false.
If mimeType’s essence is not "application/x-www-form-urlencoded
", "multipart/form-data
", or "text/plain
", then return false.
This intentionally does not use extract a MIME type as that algorithm is rather forgiving and servers are not expected to implement it.
range
`
Let rangeValue be the result of parsing a single range header value given value and false.
If rangeValue is failure, then return false.
If rangeValue[0] is null, then return false.
As web browsers have historically not emitted ranges such as `bytes=-500
` this algorithm does not safelist them.
Return false.
Return true.
There are limited exceptions to the `Content-Type
` header safelist, as documented in CORS protocol exceptions.
A is a byte byte for which one of the following is true:
byte is less than 0x20 and is not 0x09 HT
byte is 0x22 ("), 0x28 (left parenthesis), 0x29 (right parenthesis), 0x3A (:), 0x3C (<), 0x3E (>), 0x3F (?), 0x40 (@), 0x5B ([), 0x5C (\), 0x5D (]), 0x7B ({), 0x7D (}), or 0x7F DEL.
A is a header name that is a byte-case-insensitive match for `Authorization
`.
A is a header name that is a byte-case-insensitive match for one of
Range
`.These are headers that can be set by privileged APIs, and will be preserved if their associated request object is copied, but will be removed if the request is modified by unprivileged APIs.
`Range
` headers are commonly used by downloads and media fetches.
A helper is provided to add a range header to a particular request.
A , given a list of header names list, is a header name that is a byte-case-insensitive match for one of
Cache-Control
`Content-Language
`Content-Length
`Content-Type
`Expires
`Last-Modified
`Pragma
`A is a header name that is a byte-case-insensitive match for one of
Accept
`Accept-Language
`Content-Language
`Content-Type
`A is a header name that is a byte-case-insensitive match for one of:
Set-Cookie
`Set-Cookie2
`A request-body-header name is a header name that is a byte-case-insensitive match for one of:
Content-Encoding
`Content-Language
`Content-Location
`Content-Type
`To given a header header, run these steps:
If parsing header’s value, per the ABNF for header’s name, fails, then return failure.
Return one or more values resulting from parsing header’s value, per the ABNF for header’s name.
To build a content range given an integer rangeStart, an integer rangeEnd, and an integer fullLength, run these steps:
Let contentRange be `bytes
`.
Append rangeStart, serialized and isomorphic encoded, to contentRange.
Append 0x2D (-) to contentRange.
Append rangeEnd, serialized and isomorphic encoded to contentRange.
Append 0x2F (/) to contentRange.
Append fullLength, serialized and isomorphic encoded to contentRange.
Return contentRange.
To from a byte sequence value and a boolean allowWhitespace, run these steps:
Let data be the isomorphic decoding of value.
If data does not start with "bytes
", then return failure.
Let position be a position variable for data, initially pointing at the 5th code point of data.
If allowWhitespace is true, collect a sequence of code points that are HTTP tab or space, from data given position.
If the code point at position within data is not U+003D (=), then return failure.
Advance position by 1.
If allowWhitespace is true, collect a sequence of code points that are HTTP tab or space, from data given position.
Let rangeStart be the result of collecting a sequence of code points that are ASCII digits, from data given position.
Let rangeStartValue be rangeStart, interpreted as decimal number, if rangeStart is not the empty string; otherwise null.
If allowWhitespace is true, collect a sequence of code points that are HTTP tab or space, from data given position.
If the code point at position within data is not U+002D (-), then return failure.
Advance position by 1.
If allowWhitespace is true, collect a sequence of code points that are HTTP tab or space, from data given position.
Let rangeEnd be the result of collecting a sequence of code points that are ASCII digits, from data given position.
Let rangeEndValue be rangeEnd, interpreted as decimal number, if rangeEnd is not the empty string; otherwise null.
If position is not past the end of data, then return failure.
If rangeEndValue and rangeStartValue are null, then return failure.
If rangeStartValue and rangeEndValue are numbers, and rangeStartValue is greater than rangeEndValue, then return failure.
Return (rangeStartValue, rangeEndValue).
The range end or start can be omitted, e.g., `bytes=0-
` or `bytes=-500
` are valid ranges.
Parse a single range header value succeeds for a subset of allowed range header values, but it is the most common form used by user agents when requesting media or resuming downloads. This format of range header value can be set using add a range header.
A default `User-Agent
` value is an implementation-defined header value for the `User-Agent
` header.
For unfortunate web compatibility reasons, web browsers are strongly encouraged to have this value start with `Mozilla/5.0 (
` and be generally modeled after other web browsers.
The is `text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
`.
A status is an integer in the range 0 to 999, inclusive.
Various edge cases in mapping HTTP/1’s status-code
to this concept are worked on in issue #1156.
A null body status is a status that is 101, 103, 204, 205, or 304.
An ok status is a status in the range 200 to 299, inclusive.
A redirect status is a status that is 301, 302, 303, 307, or 308.
2.2.4. BodiesA body consists of:
A stream (a ReadableStream
object).
A source (null, a byte sequence, a Blob
object, or a FormData
object), initially null.
A length (null or an integer), initially null.
To clone a body body, run these steps:
Set body’s stream to out1.
Return a body whose stream is out2 and other members are copied from body.
To get a byte sequence bytes as a body, return the body of the result of safely extracting bytes.
To incrementally read a body body, given an algorithm processBodyChunk, an algorithm processEndOfBody, an algorithm processBodyError, and an optional null, parallel queue, or global object taskDestination (default null), run these steps. processBodyChunk must be an algorithm accepting a byte sequence. processEndOfBody must be an algorithm accepting no arguments. processBodyError must be an algorithm accepting an exception.
If taskDestination is null, then set taskDestination to the result of starting a new parallel queue.
Let reader be the result of getting a reader for body’s stream.
This operation will not throw an exception.
Perform the incrementally-read loop given reader, taskDestination, processBodyChunk, processEndOfBody, and processBodyError.
To perform the incrementally-read loop, given a ReadableStreamDefaultReader
object reader, parallel queue or global object taskDestination, algorithm processBodyChunk, algorithm processEndOfBody, and algorithm processBodyError:
Let readRequest be the following read request:
Let continueAlgorithm be null.
If chunk is not a Uint8Array
object, then set continueAlgorithm to this step: run processBodyError given a TypeError
.
Otherwise:
Let bytes be a copy of chunk.
Implementations are strongly encouraged to use an implementation strategy that avoids this copy where possible.
Set continueAlgorithm to these steps:
Run processBodyChunk given bytes.
Perform the incrementally-read loop given reader, taskDestination, processBodyChunk, processEndOfBody, and processBodyError.
Queue a fetch task given continueAlgorithm and taskDestination.
Queue a fetch task given processEndOfBody and taskDestination.
Queue a fetch task to run processBodyError given e, with taskDestination.
Read a chunk from reader given readRequest.
To fully read a body body, given an algorithm processBody, an algorithm processBodyError, and an optional null, parallel queue, or global object taskDestination (default null), run these steps. processBody must be an algorithm accepting a byte sequence. processBodyError must be an algorithm optionally accepting an exception.
If taskDestination is null, then set taskDestination to the result of starting a new parallel queue.
Let successSteps given a byte sequence bytes be to queue a fetch task to run processBody given bytes, with taskDestination.
Let errorSteps optionally given an exception exception be to queue a fetch task to run processBodyError given exception, with taskDestination.
Let reader be the result of getting a reader for body’s stream. If that threw an exception, then run errorSteps with that exception and return.
Read all bytes from reader, given successSteps and errorSteps.
A body with type is a tuple that consists of a body (a body) and a type (a header value or null).
To handle content codings given codings and bytes, run these steps:
If codings are not supported, then return bytes.
Return the result of decoding bytes with codings as explained in HTTP, if decoding does not result in an error, and failure otherwise. [HTTP]
This section documents how requests work in detail. To get started, see Setting up a request.
The input to fetch is a request.
A request has an associated method (a method). Unless stated otherwise it is `GET
`.
This can be updated during redirects to `GET
` as described in HTTP fetch.
A request has an associated URL (a URL).
Implementations are encouraged to make this a pointer to the first URL in request’s URL list. It is provided as a distinct field solely for the convenience of other standards hooking into Fetch.
A request has an associated local-URLs-only flag. Unless stated otherwise it is unset.
A request has an associated (a header list). Unless stated otherwise it is « ».
A request has an associated unsafe-request flag. Unless stated otherwise it is unset.
The unsafe-request flag is set by APIs such as fetch()
and XMLHttpRequest
to ensure a CORS-preflight fetch is done based on the supplied method and header list. It does not free an API from outlawing forbidden methods and forbidden request-headers.
A request has an associated body (null, a byte sequence, or a body). Unless stated otherwise it is null.
A byte sequence will be safely extracted into a body early on in fetch. As part of HTTP fetch it is possible for this field to be set to null due to certain redirects.
A request has an associated client (null or an environment settings object).
A request has an associated reserved client (null, an environment, or an environment settings object). Unless stated otherwise it is null.
This is only used by navigation requests and worker requests, but not service worker requests. It references an environment for a navigation request and an environment settings object for a worker request.
A request has an associated replaces client id (a string). Unless stated otherwise it is the empty string.
This is only used by navigation requests. It is the id of the target browsing context’s active document’s environment settings object.
A request has an associated traversable for user prompts, that is "no-traversable
", "client
", or a traversable navigable. Unless stated otherwise it is "client
".
This is used to determine whether and where to show necessary UI for the request, such as authentication prompts or client certificate dialogs.
no-traversable
"
client
"
no-traversable
" or to a traversable navigable derived from the request’s client during fetching. This provides a convenient way for standards to not have to explicitly set a request’s traversable for user prompts.
When displaying a user interface associated with a request in that request’s traversable for user prompts, the user agent should update the address bar to display something derived from the request’s current URL (and not, e.g., leave it at its previous value, derived from the URL of the request’s initiator). Additionally, the user agent should avoid displaying content from the request’s initiator in the traversable for user prompts, especially in the case of cross-origin requests. Displaying a blank page behind such prompts is a good way to fulfill these requirements. Failing to follow these guidelines can confuse users as to which origin is responsible for the prompt.
A request has an associated boolean keepalive. Unless stated otherwise it is false.
This can be used to allow the request to outlive the environment settings object, e.g., navigator.sendBeacon()
and the HTML img
element use this. Requests with this set to true are subject to additional processing requirements.
A request has an associated initiator type, which is null, "audio
", "beacon
", "body
", "css
", "early-hints
", "embed
", "fetch
", "font
", "frame
", "iframe
", "image
", "img
", "input
", "link
", "object
", "ping
", "script
", "track
", "video
", "xmlhttprequest
", or "other
". Unless stated otherwise it is null. [RESOURCE-TIMING]
A request has an associated service-workers mode, that is "all
" or "none
". Unless stated otherwise it is "all
".
This determines which service workers will receive a fetch
event for this fetch.
all
"
fetch
event for this fetch.
none
"
A request has an associated initiator, which is the empty string, "download
", "imageset
", "manifest
", "prefetch
", "prerender
", or "xslt
". Unless stated otherwise it is the empty string.
A request’s initiator is not particularly granular for the time being as other specifications do not require it to be. It is primarily a specification device to assist defining CSP and Mixed Content. It is not exposed to JavaScript. [CSP] [MIX]
A destination type is one of: the empty string, "audio
", "audioworklet
", "document
", "embed
", "font
", "frame
", "iframe
", "image
", "json
", "manifest
", "object
", "paintworklet
", "report
", "script
", "serviceworker
", "sharedworker
", "style
", "track
", "video
", "webidentity
", "worker
", or "xslt
".
A request has an associated destination, which is destination type. Unless stated otherwise it is the empty string.
These are reflected on RequestDestination
except for "serviceworker
" and "webidentity
" as fetches with those destinations skip service workers.
A request’s destination is script-like if it is "audioworklet
", "paintworklet
", "script
", "serviceworker
", "sharedworker
", or "worker
".
Algorithms that use script-like should also consider "xslt
" as that too can cause script execution. It is not included in the list as it is not always relevant and might require different behavior.
The following table illustrates the relationship between a request’s initiator, destination, CSP directives, and features. It is not exhaustive with respect to features. Features need to have the relevant values defined in their respective standards.
Initiator Destination CSP directive Features "" "report
" — CSP, NEL reports. "document
" HTML’s navigate algorithm (top-level only). "frame
" child-src
HTML’s <frame>
"iframe
" child-src
HTML’s <iframe>
"" connect-src
navigator.sendBeacon()
, EventSource
, HTML’s <a ping="">
and <area ping="">
, fetch()
, fetchLater()
, XMLHttpRequest
, WebSocket
, Cache API "object
" object-src
HTML’s <object>
"embed
" object-src
HTML’s <embed>
"audio
" media-src
HTML’s <audio>
"font
" font-src
CSS' @font-face
"image
" img-src
HTML’s <img src>
, /favicon.ico
resource, SVG’s <image>
, CSS' background-image
, CSS' cursor
, CSS' list-style-image
, … "audioworklet
" script-src
audioWorklet.addModule()
"paintworklet
" script-src
CSS.paintWorklet.addModule()
"script
" script-src
HTML’s <script>
, importScripts()
"serviceworker
" child-src
, script-src
, worker-src
navigator.serviceWorker.register()
"sharedworker
" child-src
, script-src
, worker-src
SharedWorker
"webidentity
" connect-src
Federated Credential Management requests
"worker
" child-src
, script-src
, worker-src
Worker
"json
" connect-src
import "..." with { type: "json" }
"style
" style-src
HTML’s <link rel=stylesheet>
, CSS' @import
, import "..." with { type: "css" }
"track
" media-src
HTML’s <track>
"video
" media-src
HTML’s <video>
element "download
" "" — HTML’s download=""
, "Save Link As…" UI "imageset
" "image
" img-src
HTML’s <img srcset>
and <picture>
"manifest
" "manifest
" manifest-src
HTML’s <link rel=manifest>
"prefetch
" "" default-src
(no specific directive) HTML’s <link rel=prefetch>
"prerender
" HTML’s <link rel=prerender>
"xslt
" "xslt
" script-src
<?xml-stylesheet>
CSP’s form-action
needs to be a hook directly in HTML’s navigate or form submission algorithm.
CSP will also need to check request’s client’s global object’s associated Document
’s ancestor navigables for various CSP directives.
A request has an associated priority, which is "high
", "low
", or "auto
". Unless stated otherwise it is "auto
".
A request has an associated internal priority (null or an implementation-defined object). Unless otherwise stated it is null.
A request has an associated origin, which is "client
" or an origin. Unless stated otherwise it is "client
".
"client
" is changed to an origin during fetching. It provides a convenient way for standards to not have to set request’s origin.
A request has an associated top-level navigation initiator origin, which is an origin or null. Unless stated otherwise it is null.
A request has an associated policy container, which is "client
" or a policy container. Unless stated otherwise it is "client
".
"client
" is changed to a policy container during fetching. It provides a convenient way for standards to not have to set request’s policy container.
A request has an associated referrer, which is "no-referrer
", "client
", or a URL. Unless stated otherwise it is "client
".
"client
" is changed to "no-referrer
" or a URL during fetching. It provides a convenient way for standards to not have to set request’s referrer.
A request has an associated referrer policy, which is a referrer policy. Unless stated otherwise it is the empty string. [REFERRER]
This can be used to override the referrer policy to be used for this request.
A request has an associated mode, which is "same-origin
", "cors
", "no-cors
", "navigate
", or "websocket
". Unless stated otherwise, it is "no-cors
".
A request has an associated use-CORS-preflight flag. Unless stated otherwise, it is unset.
The use-CORS-preflight flag being set is one of several conditions that results in a CORS-preflight request. The use-CORS-preflight flag is set if either one or more event listeners are registered on an XMLHttpRequestUpload
object or if a ReadableStream
object is used in a request.
A request has an associated credentials mode, which is "omit
", "same-origin
", or "include
". Unless stated otherwise, it is "same-origin
".
omit
"
same-origin
"
include
"
Request’s credentials mode controls the flow of credentials during a fetch. When request’s mode is "navigate
", its credentials mode is assumed to be "include
" and fetch does not currently account for other values. If HTML changes here, this standard will need corresponding changes.
A request has an associated use-URL-credentials flag. Unless stated otherwise, it is unset.
When this flag is set, when a request’s URL has a username and password, and there is an available authentication entry for the request, then the URL’s credentials are preferred over that of the authentication entry. Modern specifications avoid setting this flag, since putting credentials in URLs is discouraged, but some older features set it for compatibility reasons.
A request has an associated cache mode, which is "default
", "no-store
", "reload
", "no-cache
", "force-cache
", or "only-if-cached
". Unless stated otherwise, it is "default
".
default
"
no-store
"
reload
"
no-cache
"
force-cache
"
only-if-cached
"
same-origin
". Any cached redirects will be followed assuming request’s redirect mode is "follow
" and the redirects do not violate request’s mode.)
If header list contains `If-Modified-Since
`, `If-None-Match
`, `If-Unmodified-Since
`, `If-Match
`, or `If-Range
`, fetch will set cache mode to "no-store
" if it is "default
".
A request has an associated redirect mode, which is "follow
", "error
", or "manual
". Unless stated otherwise, it is "follow
".
A request has associated integrity metadata (a string). Unless stated otherwise, it is the empty string.
A request has associated cryptographic nonce metadata (a string). Unless stated otherwise, it is the empty string.
A request has associated parser metadata which is the empty string, "parser-inserted
", or "not-parser-inserted
". Unless otherwise stated, it is the empty string.
A request’s cryptographic nonce metadata and parser metadata are generally populated from attributes and flags on the HTML element responsible for creating a request. They are used by various algorithms in Content Security Policy to determine whether requests or responses are to be blocked in a given context. [CSP]
A request has an associated reload-navigation flag. Unless stated otherwise, it is unset.
This flag is for exclusive use by HTML’s navigate algorithm. [HTML]
A request has an associated history-navigation flag. Unless stated otherwise, it is unset.
This flag is for exclusive use by HTML’s navigate algorithm. [HTML]
A request has an associated boolean user-activation. Unless stated otherwise, it is false.
This is for exclusive use by HTML’s navigate algorithm. [HTML]
A request has an associated boolean render-blocking. Unless stated otherwise, it is false.
This flag is for exclusive use by HTML’s render-blocking mechanism. [HTML]
A request has an associated URL list (a list of one or more URLs). Unless stated otherwise, it is a list containing a copy of request’s URL.
A request has an associated current URL. It is a pointer to the last URL in request’s URL list.
A request has an associated redirect count. Unless stated otherwise, it is zero.
A request has an associated response tainting, which is "basic
", "cors
", or "opaque
". Unless stated otherwise, it is "basic
".
A request has an associated prevent no-cache cache-control header modification flag. Unless stated otherwise, it is unset.
A request has an associated done flag. Unless stated otherwise, it is unset.
A request has an associated timing allow failed flag. Unless stated otherwise, it is unset.
A request’s URL list, current URL, redirect count, response tainting, done flag, and timing allow failed flag are used as bookkeeping details by the fetch algorithm.
A subresource request is a request whose destination is "audio
", "audioworklet
", "font
", "image
", "json
", "manifest
", "paintworklet
", "script
", "style
", "track
", "video
", "xslt
", or the empty string.
A non-subresource request is a request whose destination is "document
", "embed
", "frame
", "iframe
", "object
", "report
", "serviceworker
", "sharedworker
", or "worker
".
A navigation request is a request whose destination is "document
", "embed
", "frame
", "iframe
", or "object
".
See handle fetch for usage of these terms. [SW]
Byte-serializing a request origin, given a request request, is to return the result of serializing a request origin with request, isomorphic encoded.
To clone a request request, run these steps:
Let newRequest be a copy of request, except for its body.
If request’s body is non-null, set newRequest’s body to the result of cloning request’s body.
Return newRequest.
To to a request request, with an integer first, and an optional integer last, run these steps:
Assert: last is not given, or first is less than or equal to last.
Let rangeValue be `bytes=
`.
Serialize and isomorphic encode first, and append the result to rangeValue.
Append 0x2D (-) to rangeValue.
If last is given, then serialize and isomorphic encode it, and append the result to rangeValue.
Append (`Range
`, rangeValue) to request’s header list.
A range header denotes an inclusive byte range. There a range header where first is 0 and last is 500, is a range of 501 bytes.
Features that combine multiple responses into one logical resource are historically a source of security bugs. Please seek security review for features that deal with partial responses.
2.2.6. ResponsesThe result of fetch is a response. A response evolves over time. That is, not all its fields are available straight away.
A response has an associated type which is "basic
", "cors
", "default
", "error
", "opaque
", or "opaqueredirect
". Unless stated otherwise, it is "default
".
A response can have an associated aborted flag, which is initially unset.
This indicates that the request was intentionally aborted by the developer or end-user.
A response has an associated URL. It is a pointer to the last URL in response’s URL list and null if response’s URL list is empty.
A response has an associated URL list (a list of zero or more URLs). Unless stated otherwise, it is « ».
Except for the first and last URL, if any, a response’s URL list is not directly exposed to script as that would violate atomic HTTP redirect handling.
A response has an associated status, which is a status. Unless stated otherwise it is 200.
A response has an associated status message. Unless stated otherwise it is the empty byte sequence.
Responses over an HTTP/2 connection will always have the empty byte sequence as status message as HTTP/2 does not support them.
A response has an associated (a header list). Unless stated otherwise it is « ».
A response has an associated body (null or a body). Unless stated otherwise it is null.
The source and length concepts of a network’s response’s body are always null.
A response has an associated cache state (the empty string, "local
", or "validated
"). Unless stated otherwise, it is the empty string.
This is intended for usage by Service Workers and Resource Timing. [SW] [RESOURCE-TIMING]
A response has an associated (a list of zero or more header names). The list is empty unless otherwise specified.
A response will typically get its CORS-exposed header-name list set by extracting header values from the `Access-Control-Expose-Headers
` header. This list is used by a CORS filtered response to determine which headers to expose.
A response has an associated range-requested flag, which is initially unset.
This is used to prevent a partial response from an earlier ranged request being provided to an API that didn’t make a range request. See the flag’s usage for a detailed description of the attack.
A response has an associated request-includes-credentials (a boolean), which is initially true.
A response has an associated timing allow passed flag, which is initially unset.
This is used so that the caller to a fetch can determine if sensitive timing data is allowed on the resource fetched by looking at the flag of the response returned. Because the flag on the response of a redirect has to be set if it was set for previous responses in the redirect chain, this is also tracked internally using the request’s timing allow failed flag.
A response has an associated body info (a response body info). Unless stated otherwise, it is a new response body info.
A response has an associated service worker timing info (null or a service worker timing info), which is initially null.
A response has an associated redirect taint ("same-origin
", "same-site
", or "cross-site
"), which is initially "same-origin
".
A network error is a response whose type is "error
", status is 0, status message is the empty byte sequence, header list is « », body is null, and body info is a new response body info.
An aborted network error is a network error whose aborted flag is set.
A filtered response is a response that offers a limited view on an associated response. This associated response can be accessed through filtered response’s internal response (a response that is neither a network error nor a filtered response).
Unless stated otherwise a filtered response’s associated concepts (such as its body) refer to the associated concepts of its internal response. (The exceptions to this are listed below as part of defining the concrete types of filtered responses.)
A basic filtered response is a filtered response whose type is "basic
" and header list excludes any headers in internal response’s header list whose name is a forbidden response-header name.
A CORS filtered response is a filtered response whose type is "cors
" and header list excludes any headers in internal response’s 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 filtered response whose type is "opaque
", URL list is « », status is 0, status message is the empty byte sequence, header list is « », body is null, and body info is a new response body info.
An opaque-redirect filtered response is a filtered response whose type is "opaqueredirect
", status is 0, status message is the empty byte sequence, header list is « », body is null, and body info is a new response body info.
The type of a response is exposed to script through the type
getter:
console.log(new Response().type); // "default"
console.log((await fetch("/")).type); // "basic"
console.log((await fetch("https://api.example/status")).type); // "cors"
console.log((await fetch("https://crossorigin.example/image", { mode: "no-cors" })).type); // "opaque"
console.log((await fetch("/surprise-me", { redirect: "manual" })).type); // "opaqueredirect"
(This assumes that the various resources exist, https://api.example/status
has the appropriate CORS headers, and /surprise-me
uses a redirect status.)
A fresh response is a response whose current age is within its freshness lifetime.
A stale-while-revalidate response is a response that is not a fresh response and whose current age is within the stale-while-revalidate lifetime. [HTTP-CACHING] [STALE-WHILE-REVALIDATE]
A stale response is a response that is not a fresh response or a stale-while-revalidate response.
The location URL of a response response, given null or an ASCII string requestFragment, is the value returned by the following steps. They return null, failure, or a URL.
If response’s status is not a redirect status, then return null.
Let location be the result of extracting header list values given `Location
` and response’s header list.
If location is a header value, then set location to the result of parsing location with response’s URL.
If response was constructed through the Response
constructor, response’s URL will be null, meaning that location will only parse successfully if it is an absolute-URL-with-fragment string.
If location is a URL whose fragment is null, then set location’s fragment to requestFragment.
This ensures that synthetic (indeed, all) responses follow the processing model for redirects defined by HTTP. [HTTP]
Return location.
The location URL algorithm is exclusively used for redirect handling in this standard and in HTML’s navigate algorithm which handles redirects manually. [HTML]
2.2.7. MiscellaneousA potential destination is "fetch
" or a destination which is not the empty string.
To translate a potential destination potentialDestination, run these steps:
If potentialDestination is "fetch
", then return the empty string.
Assert: potentialDestination is a destination.
Return potentialDestination.
An authentication entry and a proxy-authentication entry are tuples of username, password, and realm, used for HTTP authentication and HTTP proxy authentication, and associated with one or more requests.
User agents should allow both to be cleared together with HTTP cookies and similar tracking functionality.
Further details are defined by HTTP. [HTTP] [HTTP-CACHING]
2.4. Fetch groupsEach environment settings object has an associated fetch group, which holds a fetch group.
A fetch group holds information about fetches.
A fetch group has associated:
A fetch record is a struct with the following items:
A deferred fetch record is a struct used to maintain state needed to invoke a fetch at a later time, e.g., when a document is unloaded or becomes not fully active. It has the following items:
pending
")
pending
", "sent
", or "aborted
".
When a fetch group fetchGroup is terminated:
For each fetch record record of fetchGroup’s fetch records, if record’s controller is non-null and record’s request’s done flag is unset and keepalive is false, terminate record’s controller.
Process deferred fetches for fetchGroup.
To resolve an origin, given a network partition key key and an origin origin:
If origin’s host is an IP address, then return « origin’s host ».
If origin’s host’s public suffix is "localhost
" or "localhost.
", then return « ::1
, 127.0.0.1
».
Perform an implementation-defined operation to turn origin into a set of one or more IP addresses.
It is also implementation-defined whether other operations might be performed to get connection information beyond just IP addresses. For example, if origin’s scheme is an HTTP(S) scheme, the implementation might perform a DNS query for HTTPS RRs. [SVCB]
If this operation succeeds, return the set of IP addresses and any additional implementation-defined information.
Return failure.
The results of resolve an origin may be cached. If they are cached, key should be used as part of the cache key.
Typically this operation would involve DNS and as such caching can happen on DNS servers without key being taken into account. Depending on the implementation it might also not be possible to take key into account locally. [RFC1035]
The order of the IP addresses that the resolve an origin algorithm can return can differ between invocations.
The particulars (apart from the cache key) are not tied down as they are not pertinent to the system the Fetch Standard establishes. Other documents ought not to build on this primitive without having a considered discussion with the Fetch Standard community first.
2.6. ConnectionsA user agent has an associated connection pool. A connection pool is an ordered set of zero or more connections. Each connection is identified by an associated key (a network partition key), origin (an origin), and credentials (a boolean).
Each connection has an associated timing info (a connection timing info).
A connection timing info is a struct used to maintain timing information pertaining to the process of obtaining a connection. It has the following items:
DOMHighResTimeStamp
.
To clamp and coarsen connection timing info, given a connection timing info timingInfo, a DOMHighResTimeStamp
defaultStartTime, and a boolean crossOriginIsolatedCapability, run these steps:
If timingInfo’s connection start time is less than defaultStartTime, then return a new connection timing info whose domain lookup start time is defaultStartTime, domain lookup end time is defaultStartTime, connection start time is defaultStartTime, connection end time is defaultStartTime, secure connection start time is defaultStartTime, and ALPN negotiated protocol is timingInfo’s ALPN negotiated protocol.
Return a new connection timing info whose domain lookup start time is the result of coarsen time given timingInfo’s domain lookup start time and crossOriginIsolatedCapability, domain lookup end time is the result of coarsen time given timingInfo’s domain lookup end time and crossOriginIsolatedCapability, connection start time is the result of coarsen time given timingInfo’s connection start time and crossOriginIsolatedCapability, connection end time is the result of coarsen time given timingInfo’s connection end time and crossOriginIsolatedCapability, secure connection start time is the result of coarsen time given timingInfo’s connection end time and crossOriginIsolatedCapability, and ALPN negotiated protocol is timingInfo’s ALPN negotiated protocol.
A new connection setting is "no
", "yes
", or "yes-and-dedicated
".
To obtain a connection, given a network partition key key, URL url, boolean credentials, an optional new connection setting new (default "no
"), and an optional boolean requireUnreliable (default false), run these steps:
If new is "no
", then:
Let connections be a set of connections in the user agent’s connection pool whose key is key, origin is url’s origin, and credentials is credentials.
If connections is not empty and requireUnreliable is false, then return one of connections.
If there is a connection capable of supporting unreliable transport in connections, e.g., HTTP/3, then return that connection.
Let proxies be the result of finding proxies for url in an implementation-defined manner. If there are no proxies, let proxies be « "DIRECT
" ».
This is where non-standard technology such as Web Proxy Auto-Discovery Protocol (WPAD) and proxy auto-config (PAC) come into play. The "DIRECT
" value means to not use a proxy for this particular url.
Let timingInfo be a new connection timing info.
For each proxy of proxies:
Set timingInfo’s domain lookup start time to the .
If proxy is "DIRECT
", then set hosts to the result of running resolve an origin given key and url’s origin.
If hosts is failure, then continue.
Set timingInfo’s domain lookup end time to the .
Let connection be the result of running this step: run create a connection given key, url’s origin, credentials, proxy, an implementation-defined host from hosts, timingInfo, and requireUnreliable an implementation-defined number of times, in parallel from each other, and wait for at least 1 to return a value. In an implementation-defined manner, select a value to return from the returned values and return it. Any other returned values that are connections may be closed.
Essentially this allows an implementation to pick one or more IP addresses from the return value of resolve an origin (assuming proxy is "DIRECT
") and race them against each other, favor IPv6 addresses, retry in case of a timeout, etc.
If connection is failure, then continue.
If new is not "yes-and-dedicated
", then append connection to the user agent’s connection pool.
Return connection.
Return failure.
This is intentionally a little vague as there are a lot of nuances to connection management that are best left to the discretion of implementers. Describing this helps explain the <link rel=preconnect>
feature and clearly stipulates that connections are keyed on credentials. The latter clarifies that, e.g., TLS session identifiers are not reused across connections whose credentials are false with connections whose credentials are true.
To create a connection, given a network partition key key, origin origin, boolean credentials, string proxy, host host, connection timing info timingInfo, and boolean requireUnreliable, run these steps:
Set timingInfo’s connection start time to the .
Let connection be a new connection whose key is key, origin is origin, credentials is credentials, and timing info is timingInfo. Record connection timing info given connection and use connection to establish an HTTP connection to host, taking proxy and origin into account, with the following caveats: [HTTP] [HTTP1] [TLS]
If requireUnreliable is true, then establish a connection capable of unreliable transport, e.g., an HTTP/3 connection. [HTTP3]
When establishing a connection capable of unreliable transport, enable options that are necessary for WebTransport. For HTTP/3, this means including SETTINGS_ENABLE_WEBTRANSPORT
with a value of 1
and H3_DATAGRAM
with a value of 1
in the initial SETTINGS
frame. [WEBTRANSPORT-HTTP3] [HTTP3-DATAGRAM]
If credentials is false, then do not send a TLS client certificate.
If establishing a connection does not succeed (e.g., a UDP, TCP, or TLS error), then return failure.
Set timingInfo’s ALPN negotiated protocol to connection’s ALPN Protocol ID, with the following caveats: [RFC7301]
When a proxy is configured, if a tunnel connection is established then this must be the ALPN Protocol ID of the tunneled protocol, otherwise it must be the ALPN Protocol ID of the first hop to the proxy.
In case the user agent is using an experimental, non-registered protocol, the user agent must use the used ALPN Protocol ID, if any. If ALPN was not used for protocol negotiations, the user agent may use another descriptive string.
timingInfo’s ALPN negotiated protocol is intended to identify the network protocol in use regardless of how it was actually negotiated; that is, even if ALPN is not used to negotiate the network protocol, this is the ALPN Protocol IDs that indicates the protocol in use.
IANA maintains a list of ALPN Protocol IDs.
Return connection.
To record connection timing info given a connection connection, let timingInfo be connection’s timing info and observe these requirements:
timingInfo’s connection end time should be the immediately after establishing the connection to the server or proxy, as follows:
The returned time must include the time interval to establish the transport connection, as well as other time intervals such as SOCKS authentication. It must include the time interval to complete enough of the TLS handshake to request the resource.
If the user agent used TLS False Start for this connection, this interval must not include the time needed to receive the server’s Finished message. [RFC7918]
If the user agent sends the request with early data without waiting for the full handshake to complete, this interval must not include the time needed to receive the server’s ServerHello message. [RFC8470]
If the user agent waits for full handshake completion to send the request, this interval includes the full TLS handshake even if other requests were sent using early data on connection.
Suppose the user agent establishes an HTTP/2 connection over TLS 1.3 to send a GET
request and a POST
request. It sends the ClientHello at time t1 and then sends the GET
request with early data. The POST
request is not safe ([HTTP], section 9.2.1), so the user agent waits to complete the handshake at time t2 before sending it. Although both requests used the same connection, the GET
request reports a connection end time of t1, while the POST
request reports t2.
If a secure transport is used, timingInfo’s secure connection start time should be the result of calling immediately before starting the handshake process to secure connection. [TLS]
If connection is an HTTP/3 connection, timingInfo’s connection start time and timingInfo’s secure connection start time must be equal. (In HTTP/3 the secure transport handshake process is performed as part of the initial connection setup.) [HTTP3]
The clamp and coarsen connection timing info algorithm ensures that details of reused connections are not exposed and time values are coarsened.
2.7. Network partition keysA network partition key is a tuple consisting of a site and null or an implementation-defined value.
2.8. HTTP cache partitions 2.9. Port blockingNew protocols can avoid the need for blocking ports by negotiating the protocol through TLS using ALPN. The protocol cannot be spoofed through HTTP requests in that case. [RFC7301]
A port is a bad port if it is listed in the first column of the following table.
Port Typical service 0 — 1 tcpmux 7 echo 9 discard 11 systat 13 daytime 15 netstat 17 qotd 19 chargen 20 ftp-data 21 ftp 22 ssh 23 telnet 25 smtp 37 time 42 name 43 nicname 53 domain 69 tftp 77 — 79 finger 87 — 95 supdup 101 hostname 102 iso-tsap 103 gppitnp 104 acr-nema 109 pop2 110 pop3 111 sunrpc 113 auth 115 sftp 117 uucp-path 119 nntp 123 ntp 135 epmap 137 netbios-ns 139 netbios-ssn 143 imap 161 snmp 179 bgp 389 ldap 427 svrloc 465 submissions 512 exec 513 login 514 shell 515 printer 526 tempo 530 courier 531 chat 532 netnews 540 uucp 548 afp 554 rtsp 556 remotefs 563 nntps 587 submission 601 syslog-conn 636 ldaps 989 ftps-data 990 ftps 993 imaps 995 pop3s 1719 h323gatestat 1720 h323hostcall 1723 pptp 2049 nfs 3659 apple-sasl 4045 npp 4190 sieve 5060 sip 5061 sips 6000 x11 6566 sane-port 6665 ircu 6666 ircu 6667 ircu 6668 ircu 6669 ircu 6679 osaut 6697 ircs-u 10080 amanda 2.10. Should response to request be blocked due to its MIME type?Run these steps:
Let mimeType be the result of extracting a MIME type from response’s header list.
If mimeType is failure, then return allowed.
Let destination be request’s destination.
If destination is script-like and one of the following is true, then return blocked:
audio/
", "image/
", or "video/
".text/csv
".Return allowed.
The `Cookie
` request header and `Set-Cookie
` response headers are largely defined in their own specifications. We define additional infrastructure to be able to use them conveniently here. [COOKIES].
To , given a request request:
If the user agent is configured to disable cookies for request, then it should return.
Let sameSite be the result of determining the same-site mode for request.
Let isSecure be true if request’s current URL’s scheme is "https
"; otherwise false.
Let httpOnlyAllowed be true.
True follows from this being invoked from fetch, as opposed to the document.cookie
getter steps for instance.
Let cookies be the result of running retrieve cookies given isSecure, request’s current URL’s host, request’s current URL’s path, httpOnlyAllowed, and sameSite.
The cookie store returns an ordered list of cookies
If cookies is empty, then return.
Let value be the result of running serialize cookies given cookies.
Append (`Cookie
`, value) to request’s header list.
To parse and store response `Set-Cookie
` headers, given a request request and a response response:
If the user agent is configured to disable cookies for request, then it should return.
Let allowNonHostOnlyCookieForPublicSuffix be false.
Let isSecure be true if request’s current URL’s scheme is "https
"; otherwise false.
Let httpOnlyAllowed be true.
True follows from this being invoked from fetch, as opposed to the document.cookie
getter steps for instance.
Let sameSiteStrictOrLaxAllowed be true if the result of determine the same-site mode for request is "strict-or-less
"; otherwise false.
For each header of response’s header list:
If header’s name is not a byte-case-insensitive match for `Set-Cookie
`, then continue.
Parse and store a cookie given header’s value, isSecure, request’s current URL’s host, request’s current URL’s path, httpOnlyAllowed, allowNonHostOnlyCookieForPublicSuffix, and sameSiteStrictOrLaxAllowed.
Garbage collect cookies given request’s current URL’s host.
As noted elsewhere the `Set-Cookie
` header cannot be combined and therefore each occurrence is processed independently. This is not allowed for any other header.
The `Origin
` request header indicates where a fetch originates from.
The `Origin
` header is a version of the `Referer
` [sic] header that does not reveal a path. It is used for all HTTP fetches whose request’s response tainting is "cors
", as well as those where request’s method is neither `GET
` nor `HEAD
`. Due to compatibility constraints it is not included in all fetches.
Its possible values are all the return values of byte-serializing a request origin, given a request.
This supplants the definition in The Web Origin Concept. [ORIGIN]
To , given a request request, run these steps:
Let serializedOrigin be the result of byte-serializing a request origin with request.
If request’s response tainting is "cors
" or request’s mode is "websocket
", then append (`Origin
`, serializedOrigin) to request’s header list.
Otherwise, if request’s method is neither `GET
` nor `HEAD
`, then:
If request’s mode is not "cors
", then switch on request’s referrer policy:
no-referrer
"
Set serializedOrigin to `null
`.
no-referrer-when-downgrade
"
strict-origin
"
strict-origin-when-cross-origin
"
If request’s origin is a tuple origin, its scheme is "https
", and request’s current URL’s scheme is not "https
", then set serializedOrigin to `null
`.
same-origin
"
If request’s origin is not same origin with request’s current URL’s origin, then set serializedOrigin to `null
`.
Append (`Origin
`, serializedOrigin) to request’s header list.
A request’s referrer policy is taken into account for all fetches where the fetcher did not explicitly opt into sharing their origin with the server, e.g., via using the CORS protocol.
3.3. CORS protocolTo allow sharing responses cross-origin and allow for more versatile fetches than possible with HTML’s form
element, the CORS protocol exists. It is layered on top of HTTP and allows responses to declare they can be shared with other origins.
It needs to be an opt-in mechanism to prevent leaking data from responses behind a firewall (intranets). Additionally, for requests including credentials it needs to be opt-in to prevent leaking potentially-sensitive data.
This section explains the CORS protocol as it pertains to server developers. Requirements for user agents are part of the fetch algorithm, except for the new HTTP header syntax.
3.3.1. GeneralThe CORS protocol consists of a set of headers that indicates whether a response can be shared cross-origin.
For requests that are more involved than what is possible with HTML’s form
element, a CORS-preflight request is performed, to ensure request’s current URL supports the CORS protocol.
A CORS request is an HTTP request that includes an `Origin
` header. It cannot be reliably identified as participating in the CORS protocol as the `Origin
` header is also included for all requests whose method is neither `GET
` nor `HEAD
`.
A CORS-preflight request is a CORS request that checks to see if the CORS protocol is understood. It uses `OPTIONS
` as method and includes the following header:
Access-Control-Request-Method
`
Indicates which method a future CORS request to the same resource might use.
A CORS-preflight request can also include the following header:
Indicates which headers a future CORS request to the same resource might use.
An HTTP response to a CORS request can include the following headers:
Access-Control-Allow-Origin
`
Indicates whether the response can be shared, via returning the literal value of the `Origin
` request header (which can be `null
`) or `*
` in a response.
Access-Control-Allow-Credentials
`
Indicates whether the response can be shared when request’s credentials mode is "include
".
For a CORS-preflight request, request’s credentials mode is always "same-origin
", i.e., it excludes credentials, but for any subsequent CORS requests it might not be. Support therefore needs to be indicated as part of the HTTP response to the CORS-preflight request as well.
An HTTP response to a CORS-preflight request can include the following headers:
Access-Control-Allow-Methods
`
Indicates which methods are supported by the response’s URL for the purposes of the CORS protocol.
The `Allow
` header is not relevant for the purposes of the CORS protocol.
Indicates which headers are supported by the response’s URL for the purposes of the CORS protocol.
Access-Control-Max-Age
`
Indicates the number of seconds (5 by default) the information provided by the `Access-Control-Allow-Methods
` and `Access-Control-Allow-Headers
` headers can be cached.
An HTTP response to a CORS request that is not a CORS-preflight request can also include the following header:
A successful HTTP response, i.e., one where the server developer intends to share it, to a CORS request can use any status, as long as it includes the headers stated above with values matching up with the request.
A successful HTTP response to a CORS-preflight request is similar, except it is restricted to an ok status, e.g., 200 or 204.
Any other kind of HTTP response is not successful and will either end up not being shared or fail the CORS-preflight request. Be aware that any work the server performs might nonetheless leak through side channels, such as timing. If server developers wish to denote this explicitly, the 403 status can be used, coupled with omitting the relevant headers.
If desired, “failure” could also be shared, but that would make it a successful HTTP response. That is why for a successful HTTP response to a CORS request that is not a CORS-preflight request the status can be anything, including 403.
Ultimately server developers have a lot of freedom in how they handle HTTP responses and these tactics can differ between the response to the CORS-preflight request and the CORS request that follows it:
They can provide a static response. This can be helpful when working with caching intermediaries. A static response can both be successful and not successful depending on the CORS request. This is okay.
They can provide a dynamic response, tuned to CORS request. This can be helpful when the response body is to be tailored to a specific origin or a response needs to have credentials and be successful for a set of origins.
ABNF for the values of the headers used by the CORS protocol:
Access-Control-Request-Method = method
Access-Control-Request-Headers = 1#field-name
wildcard = "*"
Access-Control-Allow-Origin = origin-or-null / wildcard
Access-Control-Allow-Credentials = %s"true" ; case-sensitive
Access-Control-Expose-Headers = #field-name
Access-Control-Max-Age = delta-seconds
Access-Control-Allow-Methods = #method
Access-Control-Allow-Headers = #field-name
For `Access-Control-Expose-Headers
`, `Access-Control-Allow-Methods
`, and `Access-Control-Allow-Headers
` response headers, the value `*
` counts as a wildcard for requests without credentials. For such requests there is no way to solely match a header name or method that is `*
`.
When request’s credentials mode is "include
" it has an impact on the functioning of the CORS protocol other than including credentials in the fetch.
In the old days, XMLHttpRequest
could be used to set request’s credentials mode to "include
":
var client = new XMLHttpRequest()
client.open("GET", "./")
client.withCredentials = true
/* … */
Nowadays, fetch("./", { credentials:"include" }).then(/* … */)
suffices.
A request’s credentials mode is not necessarily observable on the server; only when credentials exist for a request can it be observed by virtue of the credentials being included. Note that even so, a CORS-preflight request never includes credentials.
The server developer therefore needs to decide whether or not responses "tainted" with credentials can be shared. And also needs to decide if requests necessitating a CORS-preflight request can include credentials. Generally speaking, both sharing responses and allowing requests with credentials is rather unsafe, and extreme care has to be taken to avoid the confused deputy problem.
To share responses with credentials, the `Access-Control-Allow-Origin
` and `Access-Control-Allow-Credentials
` headers are important. The following table serves to illustrate the various legal and illegal combinations for a request to https://rabbit.invalid/
:
Similarly, `Access-Control-Expose-Headers
`, `Access-Control-Allow-Methods
`, and `Access-Control-Allow-Headers
` response headers can only use `*
` as value when request’s credentials mode is not "include
".
A script at https://foo.invalid/
wants to fetch some data from https://bar.invalid/
. (Neither credentials nor response header access is important.)
var url = "https://bar.invalid/api?key=730d67a37d7f3d802e96396d00280768773813fbe726d116944d814422fc1a45&data=about:unicorn";
fetch(url).then(success, failure)
This will use the CORS protocol, though this is entirely transparent to the developer from foo.invalid
. As part of the CORS protocol, the user agent will include the `Origin
` header in the request:
Origin: https://foo.invalid
Upon receiving a response from bar.invalid
, the user agent will verify the `Access-Control-Allow-Origin
` response header. If its value is either `https://foo.invalid
` or `*
`, the user agent will invoke the success
callback. If it has any other value, or is missing, the user agent will invoke the failure
callback.
The developer of foo.invalid
returns, now fetching some data from bar.invalid
while including credentials. This time around the CORS protocol is no longer transparent to the developer as credentials require an explicit opt-in:
fetch(url, { credentials:"include" }).then(success, failure)
This also makes any `Set-Cookie
` response headers bar.invalid
includes fully functional (they are ignored otherwise).
The user agent will make sure to include any relevant credentials in the request. It will also put stricter requirements on the response. Not only will bar.invalid
need to list `https://foo.invalid
` as value for the `Access-Control-Allow-Origin
` header (`*
` is not allowed when credentials are involved), the `Access-Control-Allow-Credentials
` header has to be present too:
Access-Control-Allow-Origin: https://foo.invalid
Access-Control-Allow-Credentials: true
If the response does not include those two headers with those values, the failure
callback will be invoked. However, any `Set-Cookie
` response headers will be respected.
Specifications have allowed limited exceptions to the CORS safelist for non-safelisted `Content-Type
` header values. These exceptions are made for requests that can be triggered by web content but whose headers and bodies can be only minimally controlled by the web content. Therefore, servers should expect cross-origin web content to be allowed to trigger non-preflighted requests with the following non-safelisted `Content-Type
` header values:
application/csp-report
` [CSP]application/expect-ct-report+json
` [RFC9163]application/xss-auditor-report
`application/ocsp-request
` [RFC6960]Specifications should avoid introducing new exceptions and should only do so with careful consideration for the security consequences. New exceptions can be proposed by filing an issue.
The `Content-Length
` header is largely defined in HTTP. Its processing model is defined here as the model defined in HTTP is not compatible with web content. [HTTP]
To from a header list headers, run these steps:
Let values be the result of getting, decoding, and splitting `Content-Length
` from headers.
If values is null, then return null.
Let candidateValue be null.
For each value of values:
If candidateValue is null, then set candidateValue to value.
Otherwise, if value is not candidateValue, return failure.
If candidateValue is the empty string or has a code point that is not an ASCII digit, then return null.
Return candidateValue, interpreted as decimal number.
The `Content-Type
` header is largely defined in HTTP. Its processing model is defined here as the model defined in HTTP is not compatible with web content. [HTTP]
To from a header list headers, run these steps. They return failure or a MIME type.
Let charset be null.
Let essence be null.
Let mimeType be null.
Let values be the result of getting, decoding, and splitting `Content-Type
` from headers.
If values is null, then return failure.
For each value of values:
Let temporaryMimeType be the result of parsing value.
If temporaryMimeType is failure or its essence is "*/*
", then continue.
Set mimeType to temporaryMimeType.
If mimeType’s essence is not essence, then:
Set charset to null.
If mimeType’s parameters["charset
"] exists, then set charset to mimeType’s parameters["charset
"].
Set essence to mimeType’s essence.
Otherwise, if mimeType’s parameters["charset
"] does not exist, and charset is non-null, set mimeType’s parameters["charset
"] to charset.
If mimeType is null, then return failure.
Return mimeType.
When extract a MIME type returns failure or a MIME type whose essence is incorrect for a given format, treat this as a fatal error. Existing web platform features have not always followed this pattern, which has been a major source of security vulnerabilities in those features over the years. In contrast, a MIME type’s parameters can typically be safely ignored.
To given failure or a MIME type mimeType and an encoding fallbackEncoding, run these steps:
If mimeType is failure, then return fallbackEncoding.
If mimeType["charset
"] does not exist, then return fallbackEncoding.
Let tentativeEncoding be the result of getting an encoding from mimeType["charset
"].
If tentativeEncoding is failure, then return fallbackEncoding.
Return tentativeEncoding.
This algorithm allows mimeType to be failure so it can be more easily combined with extract a MIME type.
It is denoted as legacy as modern formats are to exclusively use UTF-8.
The `X-Content-Type-Options
` response header can be used to require checking of a response’s `Content-Type
` header against the destination of a request.
Web developers and conformance checkers must use the following value ABNF for `X-Content-Type-Options
`:
X-Content-Type-Options = "nosniff" ; case-insensitive
The `Cross-Origin-Resource-Policy
` response header can be used to require checking a request’s current URL’s origin against a request’s origin when request’s mode is "no-cors
".
Cross-Origin-Resource-Policy = %s"same-origin" / %s"same-site" / %s"cross-origin" ; case-sensitive
To perform a cross-origin resource policy check, given an origin origin, an environment settings object settingsObject, a string destination, a response response, and an optional boolean forNavigation, run these steps:
Set forNavigation to false if it is not given.
Let embedderPolicy be settingsObject’s policy container’s embedder policy.
If the cross-origin resource policy internal check with origin, "unsafe-none
", response, and forNavigation returns blocked, then return blocked.
This step is needed because we don’t want to report violations not related to Cross-Origin Embedder Policy below.
If the cross-origin resource policy internal check with origin, embedderPolicy’s report only value, response, and forNavigation returns blocked, then queue a cross-origin embedder policy CORP violation report with response, settingsObject, destination, and true.
If the cross-origin resource policy internal check with origin, embedderPolicy’s value, response, and forNavigation returns allowed, then return allowed.
Queue a cross-origin embedder policy CORP violation report with response, settingsObject, destination, and false.
Return blocked.
Only HTML’s navigate algorithm uses this check with forNavigation set to true, and it’s always for nested navigations. Otherwise, response is either the internal response of an opaque filtered response or a response which will be the internal response of an opaque filtered response. [HTML]
To perform a cross-origin resource policy internal check, given an origin origin, an embedder policy value embedderPolicyValue, a response response, and a boolean forNavigation, run these steps:
If forNavigation is true and embedderPolicyValue is "unsafe-none
", then return allowed.
Let policy be the result of getting `Cross-Origin-Resource-Policy
` from response’s header list.
This means that `Cross-Origin-Resource-Policy: same-site, same-origin
` ends up as allowed below as it will never match anything, as long as embedderPolicyValue is "unsafe-none
". Two or more `Cross-Origin-Resource-Policy
` headers will have the same effect.
If policy is neither `same-origin
`, `same-site
`, nor `cross-origin
`, then set policy to null.
If policy is null, then switch on embedderPolicyValue:
unsafe-none
"
Do nothing.
credentialless
"
Set policy to `same-origin
` if:
require-corp
"
Set policy to `same-origin
`.
Switch on policy:
cross-origin
`
Return allowed.
same-origin
`
If origin is same origin with response’s URL’s origin, then return allowed.
Otherwise, return blocked.
same-site
`
If all of the following are true
origin is schemelessly same site with response’s URL’s origin
origin’s scheme is "https
" or response’s URL’s scheme is not "https
"
then return allowed.
Otherwise, return blocked.
`Cross-Origin-Resource-Policy: same-site
` does not consider a response delivered via a secure transport to match a non-secure requesting origin, even if their hosts are otherwise same site. Securely-transported responses will only match a securely-transported initiator.
The `Sec-Purpose
` HTTP request header specifies that the request serves one or more purposes other than requesting the resource for immediate use by the user.
The `Sec-Purpose
` header field is a structured header whose value must be a token.
The sole token defined is prefetch
. It indicates the request’s purpose is to fetch a resource that is anticipated to be needed shortly.
The server can use this to adjust the caching expiry for prefetches, to disallow the prefetch, or to treat it differently when counting page visits.
4. FetchingThe algorithm below defines fetching. In broad strokes, it takes a request and one or more algorithms to run at various points during the operation. A response is passed to the last two algorithms listed below. The first two algorithms can be used to capture uploads.
To fetch, given a request request, an optional algorithm processRequestBodyChunkLength, an optional algorithm processRequestEndOfBody, an optional algorithm processEarlyHintsResponse, an optional algorithm processResponse, an optional algorithm processResponseEndOfBody, an optional algorithm processResponseConsumeBody, and an optional boolean useParallelQueue (default false), run the steps below. If given, processRequestBodyChunkLength must be an algorithm accepting 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, 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.
The user agent may be asked to suspend the ongoing fetch. The user agent may either accept or ignore the suspension request. The suspended fetch can be resumed. The user agent should ignore the suspension request if the ongoing fetch is updating the response in the HTTP cache for the request.
The user agent does not update the entry in the HTTP cache for a request if request’s cache mode is "no-store" or a `Cache-Control: no-store
` header appears in the response. [HTTP-CACHING]
Assert: request’s mode is "navigate
" or processEarlyHintsResponse is null.
Processing of early hints (responses whose status is 103) is only vetted for navigations.
Let taskDestination be null.
Let crossOriginIsolatedCapability be false.
Populate request from client given request.
If request’s client is non-null, then:
Set taskDestination to request’s client’s global object.
Set crossOriginIsolatedCapability to request’s client’s cross-origin isolated capability.
If useParallelQueue is true, then set taskDestination to the result of starting a new parallel queue.
Let timingInfo be a new fetch timing info whose start time and post-redirect start time are the given crossOriginIsolatedCapability, and render-blocking is set to request’s render-blocking.
Let fetchParams be a new fetch params whose request is request, timing info is timingInfo, process request body chunk length is processRequestBodyChunkLength, process request end-of-body is processRequestEndOfBody, process early hints response is processEarlyHintsResponse, process response is processResponse, process response consume body is processResponseConsumeBody, process response end-of-body is processResponseEndOfBody, task destination is taskDestination, and cross-origin isolated capability is crossOriginIsolatedCapability.
If request’s body is a byte sequence, then set request’s body to request’s body as a body.
If all of the following conditions are true:
request’s URL’s scheme is an HTTP(S) scheme
request’s mode is "same-origin
", "cors
", or "no-cors
"
request’s client is not null, and request’s client’s global object is a Window
object
request’s method is `GET
`
request’s unsafe-request flag is not set or request’s header list is empty
then:
Assert: request’s origin is same origin with request’s client’s origin.
Let onPreloadedResponseAvailable be an algorithm that runs the following step given a response response: set fetchParams’s preloaded response candidate to response.
Let foundPreloadedResource be the result of invoking consume a preloaded resource for request’s client, given request’s URL, request’s destination, request’s mode, request’s credentials mode, request’s integrity metadata, and onPreloadedResponseAvailable.
If foundPreloadedResource is true and fetchParams’s preloaded response candidate is null, then set fetchParams’s preloaded response candidate to "pending
".
If request’s header list does not contain `Accept
`, then:
Let value be `*/*
`.
If request’s initiator is "prefetch
", then set value to the document `Accept
` header value.
Otherwise, the user agent should set value to the first matching statement, if any, switching on request’s destination:
document
"
frame
"
iframe
"
Accept
` header value
image
"
image/png,image/svg+xml,image/*;q=0.8,*/*;q=0.5
`
json
"
application/json,*/*;q=0.5
`
style
"
text/css,*/*;q=0.1
`
Append (`Accept
`, value) to request’s header list.
If request’s header list does not contain `Accept-Language
`, then user agents should append (`Accept-Language
, an appropriate header value) to request’s header list.
If request’s internal priority is null, then use request’s priority, initiator, destination, and render-blocking in an implementation-defined manner to set request’s internal priority to an implementation-defined object.
The implementation-defined object could encompass stream weight and dependency for HTTP/2, priorities used in Extensible Prioritization Scheme for HTTP for transports where it applies (including HTTP/3), and equivalent information used to prioritize dispatch and processing of HTTP/1 fetches. [RFC9218]
If request is a subresource request:
Let record be a new fetch record whose request is request and controller is fetchParams’s controller.
Append record to request’s client’s fetch group’s fetch records.
Run main fetch given fetchParams.
Return fetchParams’s controller.
To main fetch, given a fetch params fetchParams and an optional boolean recursive (default false), run these steps:
Let request be fetchParams’s request.
Let response be null.
If request’s local-URLs-only flag is set and request’s current URL is not local, then set response to a network error.
Upgrade request to a potentially trustworthy URL, if appropriate.
Upgrade a mixed content request to a potentially trustworthy URL, if appropriate.
If should request be blocked due to a bad port, should fetching request be blocked as mixed content, should request be blocked by Content Security Policy, or should request be blocked by Integrity Policy Policy returns blocked, then set response to a network error.
If request’s referrer policy is the empty string, then set request’s referrer policy to request’s policy container’s referrer policy.
If request’s referrer is not "no-referrer
", then set request’s referrer to the result of invoking determine request’s referrer. [REFERRER]
As stated in Referrer Policy, user agents can provide the end user with options to override request’s referrer to "no-referrer
" or have it expose less sensitive information.
Set request’s current URL’s scheme to "https
" if all of the following conditions are true:
http
"localhost
" or "localhost.
"includeSubDomains
directive or a congruent match (with or without an asserted includeSubDomains
directive) [HSTS]; or DNS resolution for the request finds a matching HTTPS RR per section 9.5 of [SVCB]. [HSTS] [SVCB]As all DNS operations are generally implementation-defined, how it is determined that DNS resolution contains an HTTPS RR is also implementation-defined. As DNS operations are not traditionally performed until attempting to obtain a connection, user agents might need to perform DNS operations earlier, consult local DNS caches, or wait until later in the fetch algorithm and potentially unwind logic on discovering the need to change request’s current URL’s scheme.
If recursive is false, then run the remaining steps in parallel.
If response is null, then set response to the result of running the steps corresponding to the first matching statement:
Wait until fetchParams’s preloaded response candidate is not "pending
".
Assert: fetchParams’s preloaded response candidate is a response.
Return fetchParams’s preloaded response candidate.
basic
"
data
"
navigate
" or "websocket
"
Set request’s response tainting to "basic
".
Return the result of running override fetch given "scheme-fetch
" and fetchParams.
HTML assigns any documents and workers created from URLs whose scheme is "data
" a unique opaque origin. Service workers can only be created from URLs whose scheme is an HTTP(S) scheme. [HTML] [SW]
same-origin
"
Return a network error.
no-cors
"
If request’s redirect mode is not "follow
", then return a network error.
Set request’s response tainting to "opaque
".
Return the result of running override fetch given "scheme-fetch
" and fetchParams.
Return a network error.
Set request’s response tainting to "cors
".
Let corsWithPreflightResponse be the result of running override fetch given "http-fetch
", fetchParams, and true.
If corsWithPreflightResponse is a network error, then clear cache entries using request.
Return corsWithPreflightResponse.
Set request’s response tainting to "cors
".
Return the result of running override fetch given "http-fetch
" and fetchParams.
If recursive is true, then return response.
If response is not a network error and response is not a filtered response, then:
If request’s response tainting is "cors
", then:
Let headerNames be the result of extracting header list values given `Access-Control-Expose-Headers
` and response’s header list.
If request’s credentials mode is not "include
" and headerNames contains `*
`, then set response’s CORS-exposed header-name list to all unique header names in response’s header list.
Otherwise, if headerNames is non-null or failure, then set response’s CORS-exposed header-name list to headerNames.
One of the headerNames can still be `*
` at this point, but will only match a header whose name is `*
`.
Set response to the following filtered response with response as its internal response, depending on request’s response tainting:
basic
"
cors
"
opaque
"
Let internalResponse be response, if response is a network error; otherwise response’s internal response.
If internalResponse’s URL list is empty, then set it to a clone of request’s URL list.
A response’s URL list can be empty, e.g., when fetching an about:
URL.
Set internalResponse’s redirect taint to request’s redirect-taint.
If request’s timing allow failed flag is unset, then set internalResponse’s timing allow passed flag.
If response is not a network error and any of the following returns blocked
should internalResponse to request be blocked as mixed content
should internalResponse to request be blocked by Content Security Policy
should internalResponse to request be blocked due to its MIME type
should internalResponse to request be blocked due to nosniff
then set response and internalResponse to a network error.
If response’s type is "opaque
", internalResponse’s status is 206, internalResponse’s range-requested flag is set, and request’s header list does not contain `Range
`, then set response and internalResponse to a network error.
Traditionally, APIs accept a ranged response even if a range was not requested. This prevents a partial response from an earlier ranged request being provided to an API that did not make a range request.
Further detailsThe above steps prevent the following attack:
A media element is used to request a range of a cross-origin HTML resource. Although this is invalid media, a reference to a clone of the response can be retained in a service worker. This can later be used as the response to a script element’s fetch. If the partial response is valid JavaScript (even though the whole resource is not), executing it would leak private data.
If response is not a network error and either request’s method is `HEAD
` or `CONNECT
`, or internalResponse’s status is a null body status, set internalResponse’s body to null and disregard any enqueuing toward it (if any).
This standardizes the error handling for servers that violate HTTP.
If request’s integrity metadata is not the empty string, then:
Let processBodyError be this step: run fetch response handover given fetchParams and a network error.
If response’s body is null, then run processBodyError and abort these steps.
Let processBody given bytes be these steps:
If bytes do not match request’s integrity metadata, then run processBodyError and abort these steps. [SRI]
Run fetch response handover given fetchParams and response.
Fully read response’s body given processBody and processBodyError.
Otherwise, run fetch response handover given fetchParams and response.
The fetch response handover, given a fetch params fetchParams and a response response, run these steps:
Let timingInfo be fetchParams’s timing info.
If response is not a network error and fetchParams’s request’s client is a secure context, then set timingInfo’s server-timing headers to the result of getting, decoding, and splitting `Server-Timing
` from response’s internal response’s header list.
Using _response_’s internal response is safe as exposing `Server-Timing
` header data is guarded through the `Timing-Allow-Origin
` header.
The user agent may decide to expose `Server-Timing
` headers to non-secure contexts requests as well.
If fetchParams’s request’s destination is "document
", then set fetchParams’s controller’s full timing info to fetchParams’s timing info.
Let processResponseEndOfBody be the following steps:
Let unsafeEndTime be the .
Set fetchParams’s controller’s report timing steps to the following steps given a global object global:
If fetchParams’s request’s URL’s scheme is not an HTTP(S) scheme, then return.
Set timingInfo’s end time to the relative high resolution time given unsafeEndTime and global.
Let cacheState be response’s cache state.
Let bodyInfo be response’s body info.
If response’s timing allow passed flag is not set, then set timingInfo to the result of creating an opaque timing info for timingInfo and set cacheState to the empty string.
This covers the case of response being a network error.
Let responseStatus be 0.
If fetchParams’s request’s mode is not "navigate
" or response’s redirect taint is "same-origin
":
Set responseStatus to response’s status.
Let mimeType be the result of extracting a MIME type from response’s header list.
If mimeType is not failure, then set bodyInfo’s content type to the result of minimizing a supported MIME type given mimeType.
If fetchParams’s request’s initiator type is non-null, then mark resource timing given timingInfo, fetchParams’s request’s URL, fetchParams’s request’s initiator type, global, cacheState, bodyInfo, and responseStatus.
Let processResponseEndOfBodyTask be the following steps:
If fetchParams’s process response end-of-body is non-null, then run fetchParams’s process response end-of-body given response.
If fetchParams’s request’s initiator type is non-null and fetchParams’s request’s client’s global object is fetchParams’s task destination, then run fetchParams’s controller’s report timing steps given fetchParams’s request’s client’s global object.
Queue a fetch task to run processResponseEndOfBodyTask with fetchParams’s task destination.
If fetchParams’s process response is non-null, then queue a fetch task to run fetchParams’s process response given response, with fetchParams’s task destination.
Let internalResponse be response, if response is a network error; otherwise response’s internal response.
If internalResponse’s body is null, then run processResponseEndOfBody.
Otherwise:
Let transformStream be a new TransformStream
.
Let identityTransformAlgorithm be an algorithm which, given chunk, enqueues chunk in transformStream.
Set up transformStream with transformAlgorithm set to identityTransformAlgorithm and flushAlgorithm set to processResponseEndOfBody.
Set internalResponse’s body’s stream to the result of internalResponse’s body’s stream piped through transformStream.
This TransformStream
is needed for the purpose of receiving a notification when the stream reaches its end, and is otherwise an identity transform stream.
If fetchParams’s process response consume body is non-null, then:
Let processBody given nullOrBytes be this step: run fetchParams’s process response consume body given response and nullOrBytes.
Let processBodyError be this step: run fetchParams’s process response consume body given response and failure.
If internalResponse’s body is null, then queue a fetch task to run processBody given null, with fetchParams’s task destination.
Otherwise, fully read internalResponse’s body given processBody, processBodyError, and fetchParams’s task destination.
To override fetch, given "scheme-fetch
" or "http-fetch
" type, a fetch params fetchParams, and an optional boolean makeCORSPreflight (default false):
Let request be fetchParams’ request.
Let response be the result of executing potentially override response for a request on request.
If response is non-null, then return response.
Switch on type and run the associated step:
scheme fetch
"
Set response be the result of running scheme fetch given fetchParams.
HTTP fetch
"
Set response be the result of running HTTP fetch given fetchParams and makeCORSPreflight.
Return response.
The potentially override response for a request algorithm takes a request request, and returns either a response or null. Its behavior is implementation-defined, allowing user agents to intervene on the request by returning a response directly, or allowing the request to proceed by returning null.
By default, the algorithm has the following trivial implementation:
Return null.
User agents will generally override this default implementation with a somewhat more complex set of behaviors. For example, a user agent might decide that its users' safety is best preserved by generally blocking requests to `https://unsafe.example/`, while synthesizing a shim for the widely-used resource `https://unsafe.example/widget.js` to avoid breakage. That implementation might look like the following:
If request’s current url’s host’s registrable domain is "unsafe.example
":
If request’s current url’s path is « "widget.js
" »:
Return a network error.
Return null.
To scheme fetch, given a fetch params fetchParams:
If fetchParams is canceled, then return the appropriate network error for fetchParams.
Let request be fetchParams’s request.
Switch on request’s current URL’s scheme and run the associated steps:
about
"
If request’s current URL’s path is the string "blank
", then return a new response whose status message is `OK
`, header list is « (`Content-Type
`, `text/html;charset=utf-8
`) », and body is the empty byte sequence as a body.
URLs such as "about:config
" are handled during navigation and result in a network error in the context of fetching.
blob
"
Let blobURLEntry be request’s current URL’s blob URL entry.
If request’s method is not `GET
` or blobURLEntry is null, then return a network error. [FILEAPI]
The `GET
` method restriction serves no useful purpose other than being interoperable.
Let requestEnvironment be the result of determining the environment given request.
Let isTopLevelNavigation be true if request’s destination is "document
"; otherwise, false.
If isTopLevelNavigation is false and requestEnvironment is null, then return a network error.
Let navigationOrEnvironment be the string "navigation
" if isTopLevelNavigation is true; otherwise, requestEnvironment.
Let blob be the result of obtaining a blob object given blobURLEntry and navigationOrEnvironment.
If blob is not a Blob
object, then return a network error.
Let response be a new response.
Let fullLength be blob’s size
.
Let serializedFullLength be fullLength, serialized and isomorphic encoded.
Let type be blob’s type
.
If request’s header list does not contain `Range
`:
Let bodyWithType be the result of safely extracting blob.
Set response’s status message to `OK
`.
Set response’s header list to « (`Content-Length
`, serializedFullLength), (`Content-Type
`, type) ».
Otherwise:
Set response’s range-requested flag.
Let rangeHeader be the result of getting `Range
` from request’s header list.
Let rangeValue be the result of parsing a single range header value given rangeHeader and true.
If rangeValue is failure, then return a network error.
Let (rangeStart, rangeEnd) be rangeValue.
If rangeStart is null:
Set rangeStart to fullLength − rangeEnd.
Set rangeEnd to rangeStart + rangeEnd − 1.
Otherwise:
If rangeStart is greater than or equal to fullLength, then return a network error.
If rangeEnd is null or rangeEnd is greater than or equal to fullLength, then set rangeEnd to fullLength − 1.
Let slicedBlob be the result of invoking slice blob given blob, rangeStart, rangeEnd + 1, and type.
A range header denotes an inclusive byte range, while the slice blob algorithm input range does not. To use the slice blob algorithm, we have to increment rangeEnd.
Let slicedBodyWithType be the result of safely extracting slicedBlob.
Let serializedSlicedLength be slicedBlob’s size
, serialized and isomorphic encoded.
Let contentRange be the result of invoking build a content range given rangeStart, rangeEnd, and fullLength.
Set response’s status to 206.
Set response’s status message to `Partial Content
`.
Set response’s header list to « (`Content-Length
`, serializedSlicedLength), (`Content-Type
`, type), (`Content-Range
`, contentRange) ».
Return response.
data
"
Let dataURLStruct be the result of running the data:
URL processor on request’s current URL.
If dataURLStruct is failure, then return a network error.
Let mimeType be dataURLStruct’s MIME type, serialized.
Return a new response whose status message is `OK
`, header list is « (`Content-Type
`, mimeType) », and body is dataURLStruct’s body as a body.
file
"
For now, unfortunate as it is, file:
URLs are left as an exercise for the reader.
When in doubt, return a network error.
Return the result of running HTTP fetch given fetchParams.
Return a network error.
To HTTP fetch, given a fetch params fetchParams and an optional boolean makeCORSPreflight (default false), run these steps:
Let request be fetchParams’s request.
Let response and internalResponse be null.
If request’s service-workers mode is "all
", then:
Let requestForServiceWorker be a clone of request.
If requestForServiceWorker’s body is non-null, then:
Let transformStream be a new TransformStream
.
Let transformAlgorithm given chunk be these steps:
If fetchParams is canceled, then abort these steps.
If chunk is not a Uint8Array
object, then terminate fetchParams’s controller.
Otherwise, enqueue chunk in transformStream. The user agent may split the chunk into implementation-defined practical sizes and enqueue each of them. The user agent also may concatenate the chunks into an implementation-defined practical size and enqueue it.
Set up transformStream with transformAlgorithm set to transformAlgorithm.
Set requestForServiceWorker’s body’s stream to the result of requestForServiceWorker’s body’s stream piped through transformStream.
Let serviceWorkerStartTime be the given fetchParams’s cross-origin isolated capability.
Set response to the result of invoking handle fetch for requestForServiceWorker, with fetchParams’s controller and fetchParams’s cross-origin isolated capability. [HTML] [SW]
If response is non-null, then:
Set fetchParams’s timing info’s final service worker start time to serviceWorkerStartTime.
Set internalResponse to response, if response is not a filtered response; otherwise to response’s internal response.
If one of the following is true
response’s type is "error
"
request’s mode is "same-origin
" and response’s type is "cors
"
request’s mode is not "no-cors
" and response’s type is "opaque
"
manual
" and response’s type is "opaqueredirect
"follow
" and response’s URL list has more than one item.then return a network error.
If response is null, then:
If makeCORSPreflight is true and one of these conditions is true:
There is no method cache entry match for request’s method using request, and either request’s method is not a CORS-safelisted method or request’s use-CORS-preflight flag is set.
Then:
Let preflightResponse be the result of running CORS-preflight fetch given request.
If preflightResponse is a network error, then return preflightResponse.
This step checks the CORS-preflight cache and if there is no suitable entry it performs a CORS-preflight fetch which, if successful, populates the cache. The purpose of the CORS-preflight fetch is to ensure the fetched resource is familiar with the CORS protocol. The cache is there to minimize the number of CORS-preflight fetches.
If request’s redirect mode is "follow
", then set request’s service-workers mode to "none
".
Redirects coming from the network (as opposed to from a service worker) are not to be exposed to a service worker.
Set response and internalResponse to the result of running HTTP-network-or-cache fetch given fetchParams.
If request’s response tainting is "cors
" and a CORS check for request and response returns failure, then return a network error.
As the CORS check is not to be applied to responses whose status is 304 or 407, or responses from a service worker for that matter, it is applied here.
If the TAO check for request and response returns failure, then set request’s timing allow failed flag.
If either request’s response tainting or response’s type is "opaque
", and the cross-origin resource policy check with request’s origin, request’s client, request’s destination, and internalResponse returns blocked, then return a network error.
The cross-origin resource policy check runs for responses coming from the network and responses coming from the service worker. This is different from the CORS check, as request’s client and the service worker can have different embedder policies.
If internalResponse’s status is a redirect status:
If internalResponse’s status is not 303, request’s body is non-null, and the connection uses HTTP/2, then user agents may, and are even encouraged to, transmit an RST_STREAM
frame.
303 is excluded as certain communities ascribe special status to it.
Switch on request’s redirect mode:
error
"
Set response to a network error.
manual
"
If request’s mode is "navigate
", then set fetchParams’s controller’s next manual redirect steps to run HTTP-redirect fetch given fetchParams and response.
Otherwise, set response to an opaque-redirect filtered response whose internal response is internalResponse.
follow
"
Set response to the result of running HTTP-redirect fetch given fetchParams and response.
Return response. Typically internalResponse’s body’s stream is still being enqueued to after returning.
To HTTP-redirect fetch, given a fetch params fetchParams and a response response, run these steps:
Let request be fetchParams’s request.
Let internalResponse be response, if response is not a filtered response; otherwise response’s internal response.
Let locationURL be internalResponse’s location URL given request’s current URL’s fragment.
If locationURL is null, then return response.
If locationURL is failure, then return a network error.
If locationURL’s scheme is not an HTTP(S) scheme, then return a network error.
If request’s redirect count is 20, then return a network error.
Increase request’s redirect count by 1.
If request’s mode is "cors
", locationURL includes credentials, and request’s origin is not same origin with locationURL’s origin, then return a network error.
If request’s response tainting is "cors
" and locationURL includes credentials, then return a network error.
This catches a cross-origin resource redirecting to a same-origin URL.
If internalResponse’s status is not 303, request’s body is non-null, and request’s body’s source is null, then return a network error.
If one of the following is true
internalResponse’s status is 301 or 302 and request’s method is `POST
`
internalResponse’s status is 303 and request’s method is not `GET
` or `HEAD
`
then:
For each headerName of request-body-header name, delete headerName from request’s header list.
If request’s current URL’s origin is not same origin with locationURL’s origin, then for each headerName of CORS non-wildcard request-header name, delete headerName from request’s header list.
I.e., the moment another origin is seen after the initial request, the `Authorization
` header is removed.
If request’s body is non-null, then set request’s body to the body of the result of safely extracting request’s body’s source.
Let timingInfo be fetchParams’s timing info.
Set timingInfo’s redirect end time and post-redirect start time to the given fetchParams’s cross-origin isolated capability.
If timingInfo’s redirect start time is 0, then set timingInfo’s redirect start time to timingInfo’s start time.
Invoke set request’s referrer policy on redirect on request and internalResponse. [REFERRER]
Let recursive be true.
If request’s redirect mode is "manual
", then:
Return the result of running main fetch given fetchParams and recursive.
This has to invoke main fetch to get request’s response tainting correct.
To HTTP-network-or-cache fetch, given a fetch params fetchParams, an optional boolean isAuthenticationFetch (default false), and an optional boolean isNewConnectionFetch (default false), run these steps:
Some implementations might support caching of partial content, as per HTTP Caching. However, this is not widely supported by browser caches. [HTTP-CACHING]
Let request be fetchParams’s request.
Let httpFetchParams be null.
Let httpRequest be null.
Let response be null.
Let storedResponse be null.
Let httpCache be null.
Let the revalidatingFlag be unset.
Run these steps, but abort when fetchParams is canceled:
If request’s traversable for user prompts is "no-traversable
" and request’s redirect mode is "error
", then set httpFetchParams to fetchParams and httpRequest to request.
Otherwise:
Set httpRequest to a clone of request.
Implementations are encouraged to avoid teeing request’s body’s stream when request’s body’s source is null as only a single body is needed in that case. E.g., when request’s body’s source is null, redirects and authentication will end up failing the fetch.
Set httpFetchParams to a copy of fetchParams.
Set httpFetchParams’s request to httpRequest.
If user prompts or redirects are possible, then the user agent might need to re-send the request with a new set of headers after the user answers the prompt or the redirect location is determined. At that time, the original request body might have been partially sent already, so we need to clone the request (including the body) beforehand so that we have a spare copy available.
Let includeCredentials be true if one of
include
"same-origin
" and request’s response tainting is "basic
"is true; otherwise false.
If Cross-Origin-Embedder-Policy allows credentials with request returns false, then set includeCredentials to false.
Let contentLength be httpRequest’s body’s length, if httpRequest’s body is non-null; otherwise null.
Let contentLengthHeaderValue be null.
If httpRequest’s body is null and httpRequest’s method is `POST
` or `PUT
`, then set contentLengthHeaderValue to `0
`.
If contentLength is non-null, then set contentLengthHeaderValue to contentLength, serialized and isomorphic encoded.
If contentLengthHeaderValue is non-null, then append (`Content-Length
`, contentLengthHeaderValue) to httpRequest’s header list.
If contentLength is non-null and httpRequest’s keepalive is true, then:
Let inflightKeepaliveBytes be 0.
Let group be httpRequest’s client’s fetch group.
Let inflightRecords be the set of fetch records in group whose request’s keepalive is true and done flag is unset.
For each fetchRecord of inflightRecords:
If the sum of contentLength and inflightKeepaliveBytes is greater than 64 kibibytes, then return a network error.
The above limit ensures that requests that are allowed to outlive the environment settings object and contain a body, have a bounded size and are not allowed to stay alive indefinitely.
If httpRequest’s referrer is a URL, then:
Let referrerValue be httpRequest’s referrer, serialized and isomorphic encoded.
Append (`Referer
`, referrerValue) to httpRequest’s header list.
Append a request `Origin
` header for httpRequest.
Append the Fetch metadata headers for httpRequest. [FETCH-METADATA]
If httpRequest’s initiator is "prefetch
", then set a structured field value given (`Sec-Purpose
`, the token prefetch
) in httpRequest’s header list.
If httpRequest’s header list does not contain `User-Agent
`, then user agents should:
Let userAgent be httpRequest’s client’s environment default `User-Agent
` value.
Append (`User-Agent
`, userAgent) to httpRequest’s header list.
If httpRequest’s cache mode is "default
" and httpRequest’s header list contains `If-Modified-Since
`, `If-None-Match
`, `If-Unmodified-Since
`, `If-Match
`, or `If-Range
`, then set httpRequest’s cache mode to "no-store
".
If httpRequest’s cache mode is "no-cache
", httpRequest’s prevent no-cache cache-control header modification flag is unset, and httpRequest’s header list does not contain `Cache-Control
`, then append (`Cache-Control
`, `max-age=0
`) to httpRequest’s header list.
If httpRequest’s cache mode is "no-store
" or "reload
", then:
If httpRequest’s header list does not contain `Pragma
`, then append (`Pragma
`, `no-cache
`) to httpRequest’s header list.
If httpRequest’s header list does not contain `Cache-Control
`, then append (`Cache-Control
`, `no-cache
`) to httpRequest’s header list.
If httpRequest’s header list contains `Range
`, then append (`Accept-Encoding
`, `identity
`) to httpRequest’s header list.
Modify httpRequest’s header list per HTTP. Do not append a given header if httpRequest’s header list contains that header’s name.
It would be great if we could make this more normative somehow. At this point headers such as `Accept-Encoding
`, `Connection
`, `DNT
`, and `Host
`, are to be appended if necessary.
`Accept
`, `Accept-Charset
`, and `Accept-Language
` must not be included at this point.
`Accept
` and `Accept-Language
` are already included (unless fetch()
is used, which does not include the latter by default), and `Accept-Charset
` is a waste of bytes. See HTTP header layer division for more details.
If includeCredentials is true, then:
Append a request `Cookie
` header for httpRequest.
If httpRequest’s header list does not contain `Authorization
`, then:
Let authorizationValue be null.
If there’s an authentication entry for httpRequest and either httpRequest’s use-URL-credentials flag is unset or httpRequest’s current URL does not include credentials, then set authorizationValue to authentication entry.
Otherwise, if httpRequest’s current URL does include credentials and isAuthenticationFetch is true, set authorizationValue to httpRequest’s current URL, converted to an `Authorization
` value.
If authorizationValue is non-null, then append (`Authorization
`, authorizationValue) to httpRequest’s header list.
If there’s a proxy-authentication entry, use it as appropriate.
This intentionally does not depend on httpRequest’s credentials mode.
Set httpCache to the result of determining the HTTP cache partition, given httpRequest.
If httpCache is null, then set httpRequest’s cache mode to "no-store
".
If httpRequest’s cache mode is neither "no-store
" nor "reload
", then:
Set storedResponse to the result of selecting a response from the httpCache, possibly needing validation, as per the "Constructing Responses from Caches" chapter of HTTP Caching, if any. [HTTP-CACHING]
As mandated by HTTP, this still takes the `Vary
` header into account.
If storedResponse is non-null, then:
If cache mode is "default
", storedResponse is a stale-while-revalidate response, and httpRequest’s client is non-null, then:
Set response to storedResponse.
Set response’s cache state to "local
".
Let revalidateRequest be a clone of request.
Set revalidateRequest’s cache mode set to "no-cache
".
Set revalidateRequest’s prevent no-cache cache-control header modification flag.
Set revalidateRequest’s service-workers mode set to "none
".
In parallel, run main fetch given a new fetch params whose request is revalidateRequest.
This fetch is only meant to update the state of httpCache and the response will be unused until another cache access. The stale response will be used as the response to current request. This fetch is issued in the context of a client so if it goes away the request will be terminated.
Otherwise:
If storedResponse is a stale response, then set the revalidatingFlag.
If the revalidatingFlag is set and httpRequest’s cache mode is neither "force-cache
" nor "only-if-cached
", then:
If storedResponse’s header list contains `ETag
`, then append (`If-None-Match
`, `ETag
`'s value) to httpRequest’s header list.
If storedResponse’s header list contains `Last-Modified
`, then append (`If-Modified-Since
`, `Last-Modified
`'s value) to httpRequest’s header list.
See also the "Sending a Validation Request" chapter of HTTP Caching. [HTTP-CACHING]
Otherwise, set response to storedResponse and set response’s cache state to "local
".
If aborted, then return the appropriate network error for fetchParams.
If response is null, then:
If httpRequest’s cache mode is "only-if-cached
", then return a network error.
Let forwardResponse be the result of running HTTP-network fetch given httpFetchParams, includeCredentials, and isNewConnectionFetch.
If httpRequest’s method is unsafe and forwardResponse’s status is in the range 200 to 399, inclusive, invalidate appropriate stored responses in httpCache, as per the "Invalidating Stored Responses" chapter of HTTP Caching, and set storedResponse to null. [HTTP-CACHING]
If the revalidatingFlag is set and forwardResponse’s status is 304, then:
Update storedResponse’s header list using forwardResponse’s header list, as per the "Freshening Stored Responses upon Validation" chapter of HTTP Caching. [HTTP-CACHING]
This updates the stored response in cache as well.
Set response to storedResponse.
Set response’s cache state to "validated
".
If response is null, then:
Set response to forwardResponse.
Store httpRequest and forwardResponse in httpCache, as per the "Storing Responses in Caches" chapter of HTTP Caching. [HTTP-CACHING]
If forwardResponse is a network error, this effectively caches the network error, which is sometimes known as "negative caching".
The associated body info is stored in the cache alongside the response.
Set response’s URL list to a clone of httpRequest’s URL list.
If httpRequest’s header list contains `Range
`, then set response’s range-requested flag.
Set response’s request-includes-credentials to includeCredentials.
If response’s status is 401, httpRequest’s response tainting is not "cors
", includeCredentials is true, and request’s traversable for user prompts is a traversable navigable:
Needs testing: multiple `WWW-Authenticate
` headers, missing, parsing issues.
If request’s body is non-null, then:
If request’s body’s source is null, then return a network error.
Set request’s body to the body of the result of safely extracting request’s body’s source.
If request’s use-URL-credentials flag is unset or isAuthenticationFetch is true, then:
If fetchParams is canceled, then return the appropriate network error for fetchParams.
Let username and password be the result of prompting the end user for a username and password, respectively, in request’s traversable for user prompts.
Set the username given request’s current URL and username.
Set the password given request’s current URL and password.
Set response to the result of running HTTP-network-or-cache fetch given fetchParams and true.
If response’s status is 407, then:
If request’s traversable for user prompts is "no-traversable
", then return a network error.
Needs testing: multiple `Proxy-Authenticate
` headers, missing, parsing issues.
If fetchParams is canceled, then return the appropriate network error for fetchParams.
Prompt the end user as appropriate in request’s traversable for user prompts and store the result as a proxy-authentication entry. [HTTP]
Remaining details surrounding proxy authentication are defined by HTTP.
Set response to the result of running HTTP-network-or-cache fetch given fetchParams.
If all of the following are true
response’s status is 421
isNewConnectionFetch is false
request’s body is null, or request’s body is non-null and request’s body’s source is non-null
then:
If fetchParams is canceled, then return the appropriate network error for fetchParams.
Set response to the result of running HTTP-network-or-cache fetch given fetchParams, isAuthenticationFetch, and true.
If isAuthenticationFetch is true, then create an authentication entry for request and the given realm.
Return response. Typically response’s body’s stream is still being enqueued to after returning.
To HTTP-network fetch, given a fetch params fetchParams, an optional boolean includeCredentials (default false), and an optional boolean forceNewConnection (default false), run these steps:
Let request be fetchParams’s request.
If request’s client is offline, then return a network error.
Let response be null.
Let timingInfo be fetchParams’s timing info.
Let networkPartitionKey be the result of determining the network partition key given request.
Let newConnection be "yes
" if forceNewConnection is true; otherwise "no
".
Switch on request’s mode:
websocket
"
Let connection be the result of obtaining a WebSocket connection, given request’s current URL.
Let connection be the result of obtaining a connection, given networkPartitionKey, request’s current URL, includeCredentials, and newConnection.
Run these steps, but abort when fetchParams is canceled:
If connection is failure, then return a network error.
Set timingInfo’s final connection timing info to the result of calling clamp and coarsen connection timing info with connection’s timing info, timingInfo’s post-redirect start time, and fetchParams’s cross-origin isolated capability.
If connection is an HTTP/1.x connection, request’s body is non-null, and request’s body’s source is null, then return a network error.
Set response to the result of making an HTTP request over connection using request with the following caveats:
Follow the relevant requirements from HTTP. [HTTP] [HTTP-CACHING]
If request’s body is non-null, and request’s body’s source is null, then the user agent may have a buffer of up to 64 kibibytes and store a part of request’s body in that buffer. If the user agent reads from request’s body beyond that buffer’s size and the user agent needs to resend request, then instead return a network error.
The resending is needed when the connection is timed out, for example.
The buffer is not needed when request’s body’s source is non-null, because request’s body can be recreated from it.
When request’s body’s source is null, it means body is created from a ReadableStream
object, which means body cannot be recreated and that is why the buffer is needed.
While true:
Set timingInfo’s final network-response start time to the given fetchParams’s cross-origin isolated capability, immediately after the user agent’s HTTP parser receives the first byte of the response (e.g., frame header bytes for HTTP/2 or response status line for HTTP/1.x).
Wait until all the HTTP response headers are transmitted.
Let status be the HTTP response’s status code.
If status is in the range 100 to 199, inclusive:
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.
If request’s mode is "websocket
" and status is 101, then break.
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.
These kind of HTTP responses are eventually followed by a "final" HTTP response.
The exact layering between Fetch and HTTP still needs to be sorted through and therefore response represents both a response and an HTTP response here.
If the HTTP request results in a TLS client certificate dialog, then:
If request’s traversable for user prompts is a traversable navigable, then make the dialog available in request’s traversable for user prompts.
Otherwise, return a network error.
To transmit request’s body body, run these steps:
If body is null and fetchParams’s process request end-of-body is non-null, then queue a fetch task given fetchParams’s process request end-of-body and fetchParams’s task destination.
Otherwise, if body is non-null:
Let processBodyChunk given bytes be these steps:
If fetchParams is canceled, then abort these steps.
Run this step in parallel: transmit bytes.
If fetchParams’s process request body chunk length is non-null, then run fetchParams’s process request body chunk length given bytes’s length.
Let processEndOfBody be these steps:
If fetchParams is canceled, then abort these steps.
If fetchParams’s process request end-of-body is non-null, then run fetchParams’s process request end-of-body.
Let processBodyError given e be these steps:
If fetchParams is canceled, then abort these steps.
If e is an "AbortError
" DOMException
, then abort fetchParams’s controller.
Otherwise, terminate fetchParams’s controller.
Incrementally read request’s body given processBodyChunk, processEndOfBody, processBodyError, and fetchParams’s task destination.
If aborted, then:
If connection uses HTTP/2, then transmit an RST_STREAM
frame.
Return the appropriate network error for fetchParams.
Let buffer be an empty byte sequence.
This represents an internal buffer inside the network layer of the user agent.
Let stream be a new ReadableStream
.
Let pullAlgorithm be the following steps:
Let promise be a new promise.
Run the following steps in parallel:
If the size of buffer is smaller than a lower limit chosen by the user agent and the ongoing fetch is suspended, resume the fetch.
Wait until buffer is not empty.
Queue a fetch task to run the following steps, with fetchParams’s task destination.
Pull from bytes buffer into stream.
If stream is errored, then terminate fetchParams’s controller.
Resolve promise with undefined.
Return promise.
Let cancelAlgorithm be an algorithm that aborts fetchParams’s controller with reason, given reason.
Set up stream with byte reading support with pullAlgorithm set to pullAlgorithm, cancelAlgorithm set to cancelAlgorithm.
If includeCredentials is true, then the user agent should parse and store response `Set-Cookie
` headers given request and response.
Run these steps in parallel:
Run these steps, but abort when fetchParams is canceled:
While true:
If one or more bytes have been transmitted from response’s message body, then:
Let bytes be the transmitted bytes.
Let codings be the result of extracting header list values given `Content-Encoding
` and response’s header list.
Let filteredCoding be "@unknown
".
If codings is null or failure, then set filteredCoding to the empty string.
Otherwise, if codings’s size is greater than 1, then set filteredCoding to "multiple
".
Otherwise, if codings[0] is the empty string, or it is supported by the user agent, and is a byte-case-insensitive match for an entry listed in the HTTP Content Coding Registry, then set filteredCoding to the result of byte-lowercasing codings[0]. [IANA-HTTP-PARAMS]
Set response’s body info’s content encoding to filteredCoding.
Increase response’s body info’s encoded size by bytes’s length.
Set bytes to the result of handling content codings given codings and bytes.
This makes the `Content-Length
` header unreliable to the extent that it was reliable to begin with.
Increase response’s body info’s decoded size by bytes’s length.
If bytes is failure, then terminate fetchParams’s controller.
Append bytes to buffer.
If the size of buffer is larger than an upper limit chosen by the user agent, ask the user agent to suspend the ongoing fetch.
Otherwise, if the bytes transmission for response’s message body is done normally and stream is readable, then close stream, and abort these in-parallel steps.
If aborted, then:
If fetchParams is aborted, then:
Set response’s aborted flag.
If stream is readable, then error stream with the result of deserialize a serialized abort reason given fetchParams’s controller’s serialized abort reason and an implementation-defined realm.
Otherwise, if stream is readable, error stream with a TypeError
.
If connection uses HTTP/2, then transmit an RST_STREAM
frame.
Otherwise, the user agent should close connection unless it would be bad for performance to do so.
For instance, the user agent could keep the connection open if it knows there’s only a few bytes of transfer remaining on a reusable connection. In this case it could be worse to close the connection and go through the handshake process again for the next fetch.
These are run in parallel as at this point it is unclear whether response’s body is relevant (response might be a redirect).
Return response. Typically response’s body’s stream is still being enqueued to after returning.
This is effectively the user agent implementation of the check to see if the CORS protocol is understood. The so-called CORS-preflight request. If successful it populates the CORS-preflight cache to minimize the number of these fetches.
To CORS-preflight fetch, given a request request, run these steps:
Let preflight be a new request whose method is `OPTIONS
`, URL list is a clone of request’s URL list, initiator is request’s initiator, destination is request’s destination, origin is request’s origin, referrer is request’s referrer, referrer policy is request’s referrer policy, mode is "cors
", and response tainting is "cors
".
The service-workers mode of preflight does not matter as this algorithm uses HTTP-network-or-cache fetch rather than HTTP fetch.
Append (`Accept
`, `*/*
`) to preflight’s header list.
Append (`Access-Control-Request-Method
`, request’s method) to preflight’s header list.
Let headers be the CORS-unsafe request-header names with request’s header list.
If headers is not empty, then:
Let value be the items in headers separated from each other by `,
`.
Append (`Access-Control-Request-Headers
`, value) to preflight’s header list.
This intentionally does not use combine, as 0x20 following 0x2C is not the way this was implemented, for better or worse.
Let response be the result of running HTTP-network-or-cache fetch given a new fetch params whose request is preflight.
If a CORS check for request and response returns success and response’s status is an ok status, then:
The CORS check is done on request rather than preflight to ensure the correct credentials mode is used.
Let methods be the result of extracting header list values given `Access-Control-Allow-Methods
` and response’s header list.
Let headerNames be the result of extracting header list values given `Access-Control-Allow-Headers
` and response’s header list.
If either methods or headerNames is failure, return a network error.
If methods is null and request’s use-CORS-preflight flag is set, then set methods to a new list containing request’s method.
This ensures that a CORS-preflight fetch that happened due to request’s use-CORS-preflight flag being set is cached.
If request’s method is not in methods, request’s method is not a CORS-safelisted method, and request’s credentials mode is "include
" or methods does not contain `*
`, then return a network error.
If one of request’s header list’s names is a CORS non-wildcard request-header name and is not a byte-case-insensitive match for an item in headerNames, then return a network error.
For each unsafeName of the CORS-unsafe request-header names with request’s header list, if unsafeName is not a byte-case-insensitive match for an item in headerNames and request’s credentials mode is "include
" or headerNames does not contain `*
`, return a network error.
Let max-age be the result of extracting header list values given `Access-Control-Max-Age
` and response’s header list.
If max-age is failure or null, then set max-age to 5.
If max-age is greater than an imposed limit on max-age, then set max-age to the imposed limit.
If the user agent does not provide for a cache, then return response.
For each method in methods for which there is a method cache entry match using request, set matching entry’s max-age to max-age.
For each method in methods for which there is no method cache entry match using request, create a new cache entry with request, max-age, method, and null.
For each headerName in headerNames for which there is a header-name cache entry match using request, set matching entry’s max-age to max-age.
For each headerName in headerNames for which there is no header-name cache entry match using request, create a new cache entry with request, max-age, null, and headerName.
Return response.
Otherwise, return a network error.
A user agent has an associated CORS-preflight cache. A CORS-preflight cache is a list of cache entries.
A cache entry consists of:
*
`, or a method)*
`, or a header name)Cache entries must be removed after the seconds specified in their max-age field have passed since storing the entry. Cache entries may be removed before that moment arrives.
To clear cache entries, given a request, remove any cache entries in the user agent’s CORS-preflight cache whose key is the result of determining the network partition key given request, byte-serialized origin is the result of byte-serializing a request origin with request, and URL is request’s current URL.
There is a cache entry match for a cache entry entry with request if entry’s key is the result of determining the network partition key given request, entry’s byte-serialized origin is the result of byte-serializing a request origin with request, entry’s URL is request’s current URL, and one of
include
".is true.
There is a method cache entry match for method using request when there is a cache entry in the user agent’s CORS-preflight cache for which there is a cache entry match with request and its method is method or `*
`.
There is a for headerName using request when there is a cache entry in the user agent’s CORS-preflight cache for which there is a cache entry match with request and one of
*
` and headerName is not a CORS non-wildcard request-header nameis true.
4.10. CORS check 4.11. TAO checkTo perform a TAO check for a request and response, run these steps:
If request’s timing allow failed flag is set, then return failure.
Let values be the result of getting, decoding, and splitting `Timing-Allow-Origin
` from response’s header list.
If values contains "*
", then return success.
If values contains the result of serializing a request origin with request, then return success.
If request’s mode is "navigate
" and request’s current URL’s origin is not same origin with request’s origin, then return failure.
This is necessary for navigations of a nested navigable. There, request’s origin would be the container document’s origin and the TAO check would return failure. Since navigation timing never validates the results of the TAO check, the nested document would still have access to the full timing information, but the container document would not.
If request’s response tainting is "basic
", then return success.
Return failure.
Deferred fetching allows callers to request that a fetch is invoked at the latest possible moment, i.e., when a fetch group is terminated, or after a timeout.
The deferred fetch task source is a task source used to update the result of a deferred fetch. User agents must prioritize tasks in this task source before other task sources, specifically task sources that can result in running scripts such as the DOM manipulation task source, to reflect the most recent state of a fetchLater()
call before running any scripts that might depend on it.
This section is non-normative.
The deferred-fetch quota is allocated to a top-level traversable (a "tab"), amounting to 640 kibibytes. The top-level document and its same-origin directly nested documents can use this quota to queue deferred fetches, or delegate some of it to cross-origin nested documents, using permissions policy.
By default, 128 kibibytes out of these 640 kibibytes are allocated to delegating the quota to cross-origin nested documents, each reserving 8 kibibytes.
The top-level document, and subsequently its nested documents, can control how much of their quota is delegates to cross-origin child documents, using permissions policy. By default, the "deferred-fetch-minimal
" policy is enabled for any origin, while "deferred-fetch
" is enabled for the top-level document’s origin only. By relaxing the "deferred-fetch
" policy for particular origins and nested documents, the top-level document can allocate 64 kibibytes to those nested documents. Similarly, by restricting the "deferred-fetch-minimal
" policy for a particular origin or nested document, the document can prevent the document from reserving the 8 kibibytes it would receive by default. By disabling the "deferred-fetch-minimal
" policy for the top-level document itself, the entire 128 kibibytes delegated quota is collected back into the main pool of 640 kibibytes.
Out of the allocated quota for a document, only 64 kibibytes can be used concurrently for the same reporting origin (the request’s URL’s origin). This prevents a situation where particular third-party libraries would reserve quota opportunistically, before they have data to send.
Any of the following calls to fetchLater()
would throw due to the request itself exceeding the 64 kibibytes quota allocated to a reporting origin. Note that the size of the request includes the URL itself, the body, the header list, and the referrer.
fetchLater(a_72_kb_url);
fetchLater("https://origin.example.com", {headers: headers_exceeding_64kb});
fetchLater(a_32_kb_url, {headers: headers_exceeding_32kb});
fetchLater("https://origin.example.com", {method: "POST", body: body_exceeding_64_kb});
fetchLater(a_62_kb_url /* with a 3kb referrer */);
In the following sequence, the first two requests would succeed, but the third one would throw. That’s because the overall 640 kibibytes quota was not exceeded in the first two calls, however the 3rd request exceeds the reporting-origin quota for https://a.example.com
, and would throw.
fetchLater("https://a.example.com", {method: "POST", body: a_64kb_body});
fetchLater("https://b.example.com", {method: "POST", body: a_64kb_body});
fetchLater("https://a.example.com");
Same-origin nested documents share the quota of their parent. However, cross-origin or cross-agent iframes only receive 8kb of quota by default. So in the following example, the first three calls would succeed and the last one would throw.
// In main page
fetchLater("https://a.example.com", {method: "POST", body: a_64kb_body});
// In same-origin nested document
fetchLater("https://b.example.com", {method: "POST", body: a_64kb_body});
// In cross-origin nested document at https://fratop.example.com
fetchLater("https://a.example.com", {body: a_5kb_body});
fetchLater("https://a.example.com", {body: a_12kb_body});
To make the previous example not throw, the top-level document can delegate some of its quota to https://fratop.example.com
, for example by serving the following header:
Permissions-Policy: deferred-fetch=(self "https://fratop.example.com")
Each nested document reserves its own quota. So the following would work, because each frame reserve 8 kibibytes:
// In cross-origin nested document at https://fratop.example.com/frame-1
fetchLater("https://a.example.com", {body: a_6kb_body});
// In cross-origin nested document at https://fratop.example.com/frame-2
fetchLater("https://a.example.com", {body: a_6kb_body});
The following tree illustrates how quota is distributed to different nested documents in a tree:
https://top.example.com
, with permissions policy set to Permissions-policy: deferred-fetch=(self "https://ok.example.com")
https://top.example.com/frame
: shares quota with the top-level traversable, as they are same origin.
https://x.example.com
: receives 8 kibibytes.
https://x.example.com
: receives 8 kibibytes.
https://top.example.com
: 0. Even though it’s same origin with the top-level traversable, it does not automatically share its quota as they are separated by a cross-origin intermediary.
https://ok.example.com/good
: receives 64 kibibytes, granted via the "deferred-fetch
" policy.
https://x.example.com
: receives no quota. Only documents with the same origin as the top-level traversable can grant the 8 kibibytes based on the "deferred-fetch-minimal
" policy.
https://ok.example.com/redirect
, navigated to https://x.example.com
: receives no quota. The reserved 64 kibibytes for https://ok.example.com
are not available for https://x.example.com
.
https://ok.example.com/back
, navigated to https://top.example.com
: shares quota with the top-level traversable, as they’re same origin.
In the above example, the top-level traversable and its same origin descendants share a quota of 384 kibibytes. That value is computed as such:
640 kibibytes are initially granted to the top-level traversable.
128 kibibytes are reserved for the "deferred-fetch-minimal
" policy.
64 kibibytes are reserved for the container navigating to https://ok.example/good
.
64 kibibytes are reserved for the container navigating to https://ok.example/redirect
, and lost when it navigates away.
https://ok.example.com/back
did not reserve 64 kibibytes, because it navigated back to top-level traversable’s origin.640 − 128 − 64 − 64 = 384 kibibytes.
This specification defines a policy-controlled feature identified by the string "deferred-fetch
". Its default allowlist is "self
".
This specification defines a policy-controlled feature identified by the string "deferred-fetch-minimal
". Its default allowlist is "*
".
The quota reserved for deferred-fetch-minimal
is 128 kibibytes.
Each navigable container has an associated number reserved deferred-fetch quota. Its possible values are minimal quota, which is 8 kibibytes, and normal quota, which is 0 or 64 kibibytes. Unless stated otherwise, it is 0.
To reserve deferred-fetch quota for a navigable container container given an origin originToNavigateTo:
This is called on navigation, when the source document of the navigation is the navigable’s parent document. It potentially reserves either 64kb or 8kb of quota for the container and its navigable, if allowed by permissions policy. It is not observable to the cotnainer document whether the reserved quota was used in practice. This algorithm assumes that the container’s document might delegate quota to the navigated container, and the reserved quota would only apply in that case, and would be ignored if it ends up being shared. If quota was reserved and the document ends up being same origin with its parent, the quota would be freed.
Set container’s reserved deferred-fetch quota to 0.
Let controlDocument be container’s node document’s deferred-fetch control document.
If the inherited policy for "deferred-fetch
", container and originToNavigateTo is "Enabled"
, and the available deferred-fetch quota for controlDocument is equal or greater than normal quota, then set container’s reserved deferred-fetch quota to normal quota and return.
If all of the following conditions are true:
controlDocument’s node navigable is a top-level traversable;
the inherited policy for "deferred-fetch-minimal
", container and originToNavigateTo is "Enabled"
; and
the size of controlDocument’s node navigable’s descendant navigables, removing any navigable whose navigable container’s reserved deferred-fetch quota is not minimal quota, is less than quota reserved for deferred-fetch-minimal
/ minimal quota,
then set container’s reserved deferred-fetch quota to minimal quota.
The fetch()
method is relatively low-level API for fetching resources. It covers slightly more ground than XMLHttpRequest
, although it is currently lacking when it comes to request progression (not response progression).
The fetch()
method makes it quite straightforward to fetch a resource and extract its contents as a Blob
:
fetch("/music/pk/altes-kamuffel.flac")
.then(res => res.blob()).then(playBlob)
If you just care to log a particular response header:
fetch("/", {method:"HEAD"})
.then(res => log(res.headers.get("strict-transport-security")))
If you want to check a particular response header and then process the response of a cross-origin resource:
fetch("https://pk.example/berlin-calling.json", {mode:"cors"})
.then(res => {
if(res.headers.get("content-type") &&
res.headers.get("content-type").toLowerCase().indexOf("application/json") >= 0) {
return res.json()
} else {
throw new TypeError()
}
}).then(processJSON)
If you want to work with URL query parameters:
var url = new URL("https://geo.example.org/api"),
params = {lat:35.696233, long:139.570431}
Object.keys(params).forEach(key => url.searchParams.append(key, params[key]))
fetch(url).then(/* … */)
If you want to receive the body data progressively:
function consume(reader) {
var total = 0
return pump()
function pump() {
return reader.read().then(({done, value}) => {
if (done) {
return
}
total += value.byteLength
log(`received ${value.byteLength} bytes (${total} bytes in total)`)
return pump()
})
}
}
fetch("/music/pk/altes-kamuffel.flac")
.then(res => consume(res.body.getReader()))
.then(() => log("consumed the entire body without keeping the whole thing in memory!"))
.catch(e => log("something went wrong: " + e))
typedef (sequence<sequence<ByteString>> or record<ByteString, ByteString>) ; [Exposed=(Window,Worker)] interface { constructor(optional HeadersInit ); undefined append(ByteString , ByteString ); undefined delete(ByteString ); ByteString? get(ByteString ); sequence<ByteString> getSetCookie(); boolean has(ByteString ); undefined set(ByteString , ByteString ); iterable<ByteString, ByteString>; };
A Headers
object has an associated (a header list), which is initially empty. This can be a pointer to the header list of something else, e.g., of a request as demonstrated by Request
objects.
A Headers
object also has an associated , which is a . A headers guard is "immutable
", "request
", "request-no-cors
", "response
" or "none
".
headers = new Headers([init])
Creates a new Headers
object. init can be used to fill its internal header list, as per the example below.
headers . append(name, value)
Appends a header to headers.
headers . delete(name)
Removes a header from headers.
headers . get(name)
Returns as a string the values of all headers whose name is name, separated by a comma and a space.
headers . getSetCookie()
Returns a list of the values for all headers whose name is `Set-Cookie
`.
headers . has(name)
Returns whether there is a header whose name is name.
headers . set(name, value)
Replaces the value of the first header whose name is name with value and removes any remaining headers whose name is name.
for(const [name, value] of headers)
headers can be iterated over.
Steps for "request-no-cors
" are not shared as you cannot have a fake value (for delete()
) that always succeeds in CORS-safelisted request-header.
To a header (name, value) to a Headers
object headers, run these steps:
Normalize value.
If validating (name, value) for headers returns false, then return.
If headers’s guard is "request-no-cors
":
Let temporaryValue be the result of getting name from headers’s header list.
If temporaryValue is null, then set temporaryValue to value.
Otherwise, set temporaryValue to temporaryValue, followed by 0x2C 0x20, followed by value.
If (name, temporaryValue) is not a no-CORS-safelisted request-header, then return.
Append (name, value) to headers’s header list.
If headers’s guard is "request-no-cors
", then remove privileged no-CORS request-headers from headers.
The constructor steps are:
The method steps are to append (name, value) to this.
The value pairs to iterate over are the return value of running sort and combine with this’s header list.
5.2. BodyInit unionstypedef (Blob or BufferSource or FormData or URLSearchParams or USVString)XMLHttpRequestBodyInit
; typedef (ReadableStream or XMLHttpRequestBodyInit)BodyInit
;
To safely extract a body with type from a byte sequence or BodyInit
object object, run these steps:
If object is a ReadableStream
object, then:
Return the result of extracting object.
The safely extract operation is a subset of the extract operation that is guaranteed to not throw an exception.
To extract a body with type from a byte sequence or BodyInit
object object, with an optional boolean keepalive (default false), run these steps:
Let stream be null.
If object is a ReadableStream
object, then set stream to object.
Otherwise, if object is a Blob
object, set stream to the result of running object’s get stream.
Otherwise, set stream to a new ReadableStream
object, and set up stream with byte reading support.
Assert: stream is a ReadableStream
object.
Let action be null.
Let source be null.
Let length be null.
Let type be null.
Switch on object:
Blob
Set source to object.
Set length to object’s size
.
If object’s type
attribute is not the empty byte sequence, set type to its value.
Set source to object.
BufferSource
Set source to a copy of the bytes held by object.
FormData
Set action to this step: run the multipart/form-data
encoding algorithm, with object’s entry list and UTF-8.
Set source to object.
Set length to unclear, see html/6424 for improving this.
Set type to `multipart/form-data; boundary=
`, followed by the multipart/form-data
boundary string generated by the multipart/form-data
encoding algorithm.
URLSearchParams
Set source to the result of running the application/x-www-form-urlencoded
serializer with object’s list.
Set type to `application/x-www-form-urlencoded;charset=UTF-8
`.
Set source to the UTF-8 encoding of object.
Set type to `text/plain;charset=UTF-8
`.
ReadableStream
If source is a byte sequence, then set action to a step that returns source and length to source’s length.
If action is non-null, then run these steps in parallel:
Run action.
Whenever one or more bytes are available and stream is not errored, enqueue the result of creating a Uint8Array
from the available bytes into stream.
When running action is done, close stream.
Let body be a body whose stream is stream, source is source, and length is length.
Return (body, type).
interface mixin Body
{
readonly attribute ReadableStream? body;
readonly attribute boolean bodyUsed;
[NewObject] Promise<ArrayBuffer> arrayBuffer();
[NewObject] Promise<Blob> blob();
[NewObject] Promise<Uint8Array> bytes();
[NewObject] Promise<FormData> formData();
[NewObject] Promise<any> json();
[NewObject] Promise<USVString> text();
};
Formats you would not want a network layer to be dependent upon, such as HTML, will likely not be exposed here. Rather, an HTML parser API might accept a stream in due course.
Objects including the Body
interface mixin have an associated body (null or a body).
An object including the Body
interface mixin is said to be unusable if its body is non-null and its body’s stream is disturbed or locked.
requestOrResponse . body
Returns requestOrResponse’s body as ReadableStream
.
requestOrResponse . bodyUsed
Returns whether requestOrResponse’s body has been read from.
requestOrResponse . arrayBuffer()
Returns a promise fulfilled with requestOrResponse’s body as ArrayBuffer
.
requestOrResponse . blob()
Returns a promise fulfilled with requestOrResponse’s body as Blob
.
requestOrResponse . bytes()
Returns a promise fulfilled with requestOrResponse’s body as Uint8Array
.
requestOrResponse . formData()
Returns a promise fulfilled with requestOrResponse’s body as FormData
.
requestOrResponse . json()
Returns a promise fulfilled with requestOrResponse’s body parsed as JSON.
requestOrResponse . text()
Returns a promise fulfilled with requestOrResponse’s body as string.
The body
getter steps are to return null if this’s body is null; otherwise this’s body’s stream.
The bodyUsed
getter steps are to return true if this’s body is non-null and this’s body’s stream is disturbed; otherwise false.
The consume body algorithm, given an object that includes Body
object and an algorithm that takes a byte sequence and returns a JavaScript value or throws an exception convertBytesToJSValue, runs these steps:
If object is unusable, then return a promise rejected with a TypeError
.
Let promise be a new promise.
If object’s body is null, then run successSteps with an empty byte sequence.
Otherwise, fully read object’s body given successSteps, errorSteps, and object’s relevant global object.
Return promise.
The blob()
method steps are to return the result of running consume body with this and the following step given a byte sequence bytes: return a Blob
whose contents are bytes and whose type
attribute is the result of get the MIME type with this.
The formData()
method steps are to return the result of running consume body with this and the following steps given a byte sequence bytes:
Let mimeType be the result of get the MIME type with this.
If mimeType is non-null, then switch on mimeType’s essence and run the corresponding steps:
multipart/form-data
"
Parse bytes, using the value of the `boundary
` parameter from mimeType, per the rules set forth in Returning Values from Forms: multipart/form-data. [RFC7578]
Each part whose `Content-Disposition
` header contains a `filename
` parameter must be parsed into an entry whose value is a File
object whose contents are the contents of the part. The name
attribute of the File
object must have the value of the `filename
` parameter of the part. The type
attribute of the File
object must have the value of the `Content-Type
` header of the part if the part has such header, and `text/plain
` (the default defined by [RFC7578] section 4.4) otherwise.
Each part whose `Content-Disposition
` header does not contain a `filename
` parameter must be parsed into an entry whose value is the UTF-8 decoded without BOM content of the part. This is done regardless of the presence or the value of a `Content-Type
` header and regardless of the presence or the value of a `charset
` parameter.
A part whose `Content-Disposition
` header contains a `name
` parameter whose value is `_charset_
` is parsed like any other part. It does not change the encoding.
Return a new FormData
object, appending each entry, resulting from the parsing operation, to its entry list.
The above is a rough approximation of what is needed for `multipart/form-data
`, a more detailed parsing specification is to be written. Volunteers welcome.
application/x-www-form-urlencoded
"
Let entries be the result of parsing bytes.
Return a new FormData
object whose entry list is entries.
The text()
method steps are to return the result of running consume body with this and UTF-8 decode.
typedef (Request or USVString)RequestInfo
; [Exposed=(Window,Worker)] interfaceRequest
{ constructor(RequestInfoinput
, optional RequestInitinit
= {}); readonly attribute ByteString method; readonly attribute USVString url; [SameObject] readonly attribute Headers headers; readonly attribute RequestDestination destination; readonly attribute USVString referrer; readonly attribute ReferrerPolicy referrerPolicy; readonly attribute RequestMode mode; readonly attribute RequestCredentials credentials; readonly attribute RequestCache cache; readonly attribute RequestRedirect redirect; readonly attribute DOMString integrity; readonly attribute boolean keepalive; readonly attribute boolean isReloadNavigation; readonly attribute boolean isHistoryNavigation; readonly attribute AbortSignal signal; readonly attribute RequestDuplex duplex; [NewObject] Request clone(); }; Request includes Body; dictionaryRequestInit
{ ByteStringmethod
; HeadersInit ; BodyInit?body
; USVStringreferrer
; ReferrerPolicyreferrerPolicy
; RequestModemode
; RequestCredentialscredentials
; RequestCachecache
; RequestRedirectredirect
; DOMStringintegrity
; booleankeepalive
; AbortSignal?signal
; RequestDuplexduplex
; RequestPrioritypriority
; anywindow
; // can only be set to null }; enumRequestDestination
{""
,"audio"
,"audioworklet"
,"document"
,"embed"
,"font"
,"frame"
,"iframe"
,"image"
,"json"
,"manifest"
,"object"
,"paintworklet"
,"report"
,"script"
, ,"style"
,"track"
,"video"
,"worker"
,"xslt"
}; enumRequestMode
{"navigate"
,"same-origin"
,"no-cors"
,"cors"
}; enumRequestCredentials
{"omit"
,"same-origin"
,"include"
}; enumRequestCache
{"default"
,"no-store"
,"reload"
,"no-cache"
,"force-cache"
,"only-if-cached"
}; enumRequestRedirect
{"follow"
,"error"
,"manual"
}; enumRequestDuplex
{"half"
}; enumRequestPriority
{"high"
,"low"
,"auto"
};
"serviceworker
" is omitted from RequestDestination
as it cannot be observed from JavaScript. Implementations will still need to support it as a destination. "websocket
" is omitted from RequestMode
as it cannot be used nor observed from JavaScript.
A Request
object has an associated request (a request).
A Request
object also has an associated (null or a Headers
object), initially null.
A Request
object has an associated signal (null or an AbortSignal
object), initially null.
A Request
object’s body is its request’s body.
request = new Request(input [, init])
Returns a new request whose url
property is input if input is a string, and input’s url
if input is a Request
object.
The init argument is an object whose properties can be set as follows:
method
method
.
headers
Headers
object, an object literal, or an array of two-item arrays to set request’s headers
.
body
BodyInit
object or null to set request’s body.
referrer
about:client
", or the empty string, to set request’s referrer.
referrerPolicy
referrerPolicy
.
mode
mode
. If input is a string, it defaults to "cors
".
credentials
credentials
. If input is a string, it defaults to "same-origin
".
cache
cache
.
redirect
redirect
.
integrity
integrity
.
keepalive
keepalive
.
signal
AbortSignal
to set request’s signal
.
window
Window
.
duplex
half
" is the only valid value and it is for initiating a half-duplex fetch (i.e., the user agent sends the entire request before processing the response). "full
" is reserved for future use, for initiating a full-duplex fetch (i.e., the user agent can process the response before sending the entire request). This member needs to be set when body
is a ReadableStream
object. See issue #1254 for defining "full
".
priority
request . method
GET
" by default.
request . url
request . headers
Headers
object consisting of the headers associated with request. Note that headers added in the network layer by the user agent will not be accounted for in this object, e.g., the "Host
" header.
request . destination
document
" or "script
".
request . referrer
about:client
" when defaulting to the global’s default. This is used during fetching to determine the value of the `Referer
` header of the request being made.
request . referrerPolicy
request . mode
request . credentials
request . cache
request . redirect
request . integrity
request . keepalive
request . isReloadNavigation
request . isHistoryNavigation
request . signal
AbortSignal
object indicating whether or not request has been aborted, and its abort event handler.
request . duplex
half
", meaning the fetch will be half-duplex (i.e., the user agent sends the entire request before processing the response). In future, it could also return "full
", meaning the fetch will be full-duplex (i.e., the user agent can process the response before sending the entire request) to indicate that the fetch will be full-duplex. See issue #1254 for defining "full
".
request . clone()
Returns a clone of request.
The new Request(input, init)
constructor steps are:
Let request be null.
Let fallbackMode be null.
Let baseURL be this’s relevant settings object’s API base URL.
Let signal be null.
If input is a string, then:
Otherwise:
Let origin be this’s relevant settings object’s origin.
Let traversableForUserPrompts be "client
".
If request’s traversable for user prompts is an environment settings object and its origin is same origin with origin, then set traversableForUserPrompts to request’s traversable for user prompts.
If init["window
"] exists and is non-null, then throw a TypeError
.
If init["window
"] exists, then set traversableForUserPrompts to "no-traversable
".
Set request to a new request with the following properties:
fetch
".
If init is not empty, then:
If request’s mode is "navigate
", then set it to "same-origin
".
Unset request’s reload-navigation flag.
Unset request’s history-navigation flag.
Set request’s origin to "client
".
Set request’s referrer to "client
".
Set request’s referrer policy to the empty string.
Set request’s URL to request’s current URL.
This is done to ensure that when a service worker "redirects" a request, e.g., from an image in a cross-origin style sheet, and makes modifications, it no longer appears to come from the original source (i.e., the cross-origin style sheet), but instead from the service worker that "redirected" the request. This is important as the original source might not even be able to generate the same kind of requests as the service worker. Services that trust the original source could therefore be exploited were this not done, although that is somewhat farfetched.
If init["referrer
"] exists, then:
Let referrer be init["referrer
"].
If referrer is the empty string, then set request’s referrer to "no-referrer
".
Otherwise:
Let parsedReferrer be the result of parsing referrer with baseURL.
If one of the following is true
parsedReferrer’s scheme is "about
" and path is the string "client
"
parsedReferrer’s origin is not same origin with origin
then set request’s referrer to "client
".
Otherwise, set request’s referrer to parsedReferrer.
If init["referrerPolicy
"] exists, then set request’s referrer policy to it.
Let mode be init["mode
"] if it exists, and fallbackMode otherwise.
If mode is non-null, set request’s mode to mode.
If init["credentials
"] exists, then set request’s credentials mode to it.
If init["cache
"] exists, then set request’s cache mode to it.
If request’s cache mode is "only-if-cached
" and request’s mode is not "same-origin
", then throw a TypeError
.
If init["redirect
"] exists, then set request’s redirect mode to it.
If init["integrity
"] exists, then set request’s integrity metadata to it.
If init["keepalive
"] exists, then set request’s keepalive to it.
If init["priority
"] exists, then:
If request’s internal priority is not null, then update request’s internal priority in an implementation-defined manner.
Let signals be « signal » if signal is non-null; otherwise « ».
Set this’s signal to the result of creating a dependent abort signal from signals, using AbortSignal
and this’s relevant realm.
Set this’s headers to a new Headers
object with this’s relevant realm, whose header list is request’s header list and guard is "request
".
If init is not empty, then:
The headers are sanitized as they might contain headers that are not allowed by this mode. Otherwise, they were previously sanitized or are unmodified since they were set by a privileged API.
Let headers be a copy of this’s headers and its associated header list.
If init["headers
"] exists, then set headers to init["headers
"].
Empty this’s headers’s header list.
If headers is a Headers
object, then for each header of its header list, append header to this’s headers.
Let inputBody be input’s request’s body if input is a Request
object; otherwise null.
If either init["body
"] exists and is non-null or inputBody is non-null, and request’s method is `GET
` or `HEAD
`, then throw a TypeError
.
Let initBody be null.
If init["body
"] exists and is non-null, then:
Let bodyWithType be the result of extracting init["body
"], with keepalive set to request’s keepalive.
Set initBody to bodyWithType’s body.
Let type be bodyWithType’s type.
If type is non-null and this’s headers’s header list does not contain `Content-Type
`, then append (`Content-Type
`, type) to this’s headers.
Let inputOrInitBody be initBody if it is non-null; otherwise inputBody.
If inputOrInitBody is non-null and inputOrInitBody’s source is null, then:
Let finalBody be inputOrInitBody.
If initBody is null and inputBody is non-null, then:
Set finalBody to the result of creating a proxy for inputBody.
The method
getter steps are to return this’s request’s method.
The url
getter steps are to return this’s request’s URL, serialized.
The getter steps are to return this’s headers.
The destination
getter are to return this’s request’s destination.
The referrerPolicy
getter steps are to return this’s request’s referrer policy.
The mode
getter steps are to return this’s request’s mode.
The credentials
getter steps are to return this’s request’s credentials mode.
The cache
getter steps are to return this’s request’s cache mode.
The redirect
getter steps are to return this’s request’s redirect mode.
The integrity
getter steps are to return this’s request’s integrity metadata.
The keepalive
getter steps are to return this’s request’s keepalive.
The isReloadNavigation
getter steps are to return true if this’s request’s reload-navigation flag is set; otherwise false.
The isHistoryNavigation
getter steps are to return true if this’s request’s history-navigation flag is set; otherwise false.
The signal
getter steps are to return this’s signal.
This’s signal is always initialized in the constructor and when cloning.
The duplex
getter steps are to return "half
".
[Exposed=(Window,Worker)]interfaceResponse
{ constructor(optional BodyInit?body
= null, optional ResponseInitinit
= {}); [NewObject] static Response error(); [NewObject] static Response redirect(USVStringurl
, optional unsigned shortstatus
= 302); [NewObject] static Response json(anydata
, optional ResponseInitinit
= {}); readonly attribute ResponseType type; readonly attribute USVString url; readonly attribute boolean redirected; readonly attribute unsigned short status; readonly attribute boolean ok; readonly attribute ByteString statusText; [SameObject] readonly attribute Headers headers; [NewObject] Response clone(); }; Response includes Body; dictionaryResponseInit
{ unsigned shortstatus
= 200; ByteStringstatusText
= ""; HeadersInit ; }; enumResponseType
{"basic"
,"cors"
,"default"
,"error"
,"opaque"
,"opaqueredirect"
};
A Response
object has an associated response (a response).
A Response
object also has an associated (null or a Headers
object), initially null.
A Response
object’s body is its response’s body.
response = new Response(body = null [, init])
Creates a Response
whose body is body, and status, status message, and headers are provided by init.
response = Response . error()
Creates network error Response
.
response = Response . redirect(url, status = 302)
Creates a redirect Response
that redirects to url with status status.
response = Response . json(data [, init])
Creates a Response
whose body is the JSON-encoded data, and status, status message, and headers are provided by init.
response . type
Returns response’s type, e.g., "cors
".
response . url
Returns response’s URL, if it has one; otherwise the empty string.
response . redirected
Returns whether response was obtained through a redirect.
response . status
Returns response’s status.
response . ok
Returns whether response’s status is an ok status.
response . statusText
Returns response’s status message.
response . headers
Returns response’s headers as Headers
.
response . clone()
Returns a clone of response.
To initialize a response, given a Response
object response, ResponseInit
init, and null or a body with type body:
If init["status
"] is not in the range 200 to 599, inclusive, then throw a RangeError
.
If init["statusText
"] is not the empty string and does not match the reason-phrase token production, then throw a TypeError
.
Set response’s response’s status message to init["statusText
"].
If init["headers
"] exists, then fill response’s headers with init["headers
"].
If body is non-null, then:
If response’s status is a null body status, then throw a TypeError
.
101 and 103 are included in null body status due to their use elsewhere. They do not affect this step.
If body’s type is non-null and response’s header list does not contain `Content-Type
`, then append (`Content-Type
`, body’s type) to response’s header list.
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 type
getter steps are to return this’s response’s type.
The url
getter steps are to return the empty string if this’s response’s URL is null; otherwise this’s response’s URL, serialized with exclude fragment set to true.
The redirected
getter steps are to return true if this’s response’s URL list’s size is greater than 1; otherwise false.
To filter out responses that are the result of a redirect, do this directly through the API, e.g., fetch(url, { redirect:"error" })
. This way a potentially unsafe response cannot accidentally leak.
The status
getter steps are to return this’s response’s status.
The ok
getter steps are to return true if this’s response’s status is an ok status; otherwise false.
The statusText
getter steps are to return this’s response’s status message.
The getter steps are to return this’s headers.
5.6. Fetch methodspartial interface mixin WindowOrWorkerGlobalScope { [NewObject] Promise<Response> fetch(RequestInfoinput
, optional RequestInitinit
= {}); }; dictionaryDeferredRequestInit
: RequestInit { DOMHighResTimeStampactivateAfter
; }; [Exposed=Window] interfaceFetchLaterResult
{ readonly attribute boolean activated; }; partial interface Window { [NewObject, SecureContext] FetchLaterResult fetchLater(RequestInfoinput
, optional DeferredRequestInitinit
= {}); };
The fetch(input, init)
method steps are:
Let p be a new promise.
Let requestObject be the result of invoking the initial value of Request
as constructor with input and init as arguments. If this throws an exception, reject p with it and return p.
Let request be requestObject’s request.
If requestObject’s signal is aborted, then:
Abort the fetch()
call with p, request, null, and requestObject’s signal’s abort reason.
Return p.
ServiceWorkerGlobalScope
object, then set request’s service-workers mode to "none
".Let responseObject be null.
Let relevantRealm be this’s relevant realm.
Let locallyAborted be false.
This lets us reject promises with predictable timing, when the request to abort comes from the same thread as the call to fetch.
Let controller be null.
Add the following abort steps to requestObject’s signal:
Set locallyAborted to true.
Assert: controller is non-null.
Abort controller with requestObject’s signal’s abort reason.
Abort the fetch()
call with p, request, responseObject, and requestObject’s signal’s abort reason.
Set controller to the result of calling fetch given request and processResponse given response being these steps:
If locallyAborted is true, then abort these steps.
If response’s aborted flag is set, then:
Let deserializedError be the result of deserialize a serialized abort reason given controller’s serialized abort reason and relevantRealm.
Abort the fetch()
call with p, request, responseObject, and deserializedError.
Abort these steps.
If response is a network error, then reject p with a TypeError
and abort these steps.
Set responseObject to the result of creating a Response
object, given response, "immutable
", and relevantRealm.
Resolve p with responseObject.
Return p.
To abort a fetch()
call with a promise, request, responseObject, and an error:
Reject promise with error.
This is a no-op if promise has already fulfilled.
If request’s body is non-null and is readable, then cancel request’s body with error.
If responseObject is null, then return.
Let response be responseObject’s response.
If response’s body is non-null and is readable, then error response’s body with error.
A FetchLaterResult
has an associated activated getter steps, which is an algorithm returning a boolean.
The activated
getter steps are to return the result of running this’s activated getter steps.
The fetchLater(input, init)
method steps are:
Let requestObject be the result of invoking the initial value of Request
as constructor with input and init as arguments.
If requestObject’s signal is aborted, then throw signal’s abort reason.
Let request be requestObject’s request.
Let activateAfter be null.
If init is given and init["activateAfter
"] exists, then set activateAfter to init["activateAfter
"].
If activateAfter is less than 0, then throw a RangeError
.
If this’s relevant global object’s associated document is not fully active, then throw a TypeError
.
If request’s URL’s scheme is not an HTTP(S) scheme, then throw a TypeError
.
If request’s URL is not a potentially trustworthy URL, then throw a TypeError
.
If request’s body is not null, and request’s body length is null, then throw a TypeError
.
Requests whose body is a ReadableStream
object cannot be deferred.
If the available deferred-fetch quota given request’s client and request’s URL’s origin is less than request’s total request length, then throw a "QuotaExceededError
" DOMException
.
Let activated be false.
Let deferredRecord be the result of calling queue a deferred fetch given request, activateAfter, and the following step: set activated to true.
Add the following abort steps to requestObject’s signal: Set deferredRecord’s invoke state to "aborted
".
Return a new FetchLaterResult
whose activated getter steps are to return activated.
The following call would queue a request to be fetched when the document is terminated:
fetchLater("https://report.example.com", {
method: "POST",
body: JSON.stringify(myReport),
headers: { "Content-Type": "application/json" }
})
The following call would also queue this request after 5 seconds, and the returned value would allow callers to observe if it was indeed activated. Note that the request is guaranteed to be invoked, even in cases where the user agent throttles timers.
const result = fetchLater("https://report.example.com", {
method: "POST",
body: JSON.stringify(myReport),
headers: { "Content-Type": "application/json" },
activateAfter: 5000
});
function check_if_fetched() {
return result.activated;
}
The FetchLaterResult
object can be used together with an AbortSignal
. For example:
let accumulated_events = [];
let previous_result = null;
const abort_signal = new AbortSignal();
function accumulate_event(event) {
if (previous_result) {
if (previous_result.activated) {
// The request is already activated, we can start from scratch.
accumulated_events = [];
} else {
// Abort this request, and start a new one with all the events.
signal.abort();
}
}
accumulated_events.push(event);
result = fetchLater("https://report.example.com", {
method: "POST",
body: JSON.stringify(accumulated_events),
headers: { "Content-Type": "application/json" },
activateAfter: 5000,
abort_signal
});
}
Any of the following calls to fetchLater()
would throw:
// Only potentially trustworthy URLs are supported.
fetchLater("http://untrusted.example.com");
// The length of the deferred request has to be known when.
fetchLater("https://origin.example.com", {body: someDynamicStream});
// Deferred fetching only works on active windows.
const detachedWindow = iframe.contentWindow;
iframe.remove();
detachedWindow.fetchLater("https://origin.example.com");
See deferred fetch quota examples for examples portraying how the deferred-fetch quota works.
5.7. Garbage collectionThe user agent may terminate an ongoing fetch if that termination is not observable through script.
"Observable through script" means observable through fetch()
’s arguments and return value. Other ways, such as communicating with the server through a side-channel are not included.
The server being able to observe garbage collection has precedent, e.g., with WebSocket
and XMLHttpRequest
objects.
The user agent can terminate the fetch because the termination cannot be observed.
fetch("https://www.example.com/")
The user agent cannot terminate the fetch because the termination can be observed through the promise.
window.promise = fetch("https://www.example.com/")
The user agent can terminate the fetch because the associated body is not observable.
window.promise = fetch("https://www.example.com/").then(res => res.headers)
The user agent can terminate the fetch because the termination cannot be observed.
fetch("https://www.example.com/").then(res => res.body.getReader().closed)
The user agent cannot terminate the fetch because one can observe the termination by registering a handler for the promise object.
window.promise = fetch("https://www.example.com/")
.then(res => res.body.getReader().closed)
The user agent cannot terminate the fetch as termination would be observable via the registered handler.
fetch("https://www.example.com/")
.then(res => {
res.body.getReader().closed.then(() => console.log("stream closed!"))
})
(The above examples of non-observability assume that built-in properties and functions, such as body.getReader()
, have not been overwritten.)
data:
URLs
For an informative description of data:
URLs, see RFC 2397. This section replaces that RFC’s normative processing requirements to be compatible with deployed content. [RFC2397]
A data:
URL struct is a struct that consists of a MIME type (a MIME type) and a body (a byte sequence).
The data:
URL processor takes a URL dataURL and then runs these steps:
Let input be the result of running the URL serializer on dataURL with exclude fragment set to true.
Remove the leading "data:
" from input.
Let position point at the start of input.
Let mimeType be the result of collecting a sequence of code points that are not equal to U+002C (,), given position.
Strip leading and trailing ASCII whitespace from mimeType.
This will only remove U+0020 SPACE code points, if any.
If position is past the end of input, then return failure.
Advance position by 1.
Let encodedBody be the remainder of input.
Let body be the percent-decoding of encodedBody.
If mimeType ends with U+003B (;), followed by zero or more U+0020 SPACE, followed by an ASCII case-insensitive match for "base64
", then:
Let stringBody be the isomorphic decode of body.
Set body to the forgiving-base64 decode of stringBody.
If body is failure, then return failure.
Remove the last 6 code points from mimeType.
Remove trailing U+0020 SPACE code points from mimeType, if any.
Remove the last U+003B (;) from mimeType.
If mimeType starts with ";
", then prepend "text/plain
" to mimeType.
Let mimeTypeRecord be the result of parsing mimeType.
If mimeTypeRecord is failure, then set mimeTypeRecord to text/plain;charset=US-ASCII
.
Return a new data:
URL struct whose MIME type is mimeTypeRecord and body is body.
This section and its subsections are informative only.
For the purposes of fetching, there is an API layer (HTML’s img
, CSS’s background-image
), early fetch layer, service worker layer, and network & cache layer. `Accept
` and `Accept-Language
` are set in the early fetch layer (typically by the user agent). Most other headers controlled by the user agent, such as `Accept-Encoding
`, `Host
`, and `Referer
`, are set in the network & cache layer. Developers can set headers either at the API layer or in the service worker layer (typically through a Request
object). Developers have almost no control over forbidden request-headers, but can control `Accept
` and have the means to constrain and omit `Referer
` for instance.
Redirects (a response whose status or internal response’s (if any) status is a redirect status) are not exposed to APIs. Exposing redirects might leak information not otherwise available through a cross-site scripting attack.
A fetch to https://example.org/auth
that includes a Cookie
marked HttpOnly
could result in a redirect to https://other-origin.invalid/4af955781ea1c84a3b11
. This new URL contains a secret. If we expose redirects that secret would be available through a cross-site scripting attack.
For resources where data is protected through IP authentication or a firewall (unfortunately relatively common still), using the CORS protocol is unsafe. (This is the reason why the CORS protocol had to be invented.)
However, otherwise using the following header is safe:
Access-Control-Allow-Origin: *
Even if a resource exposes additional information based on cookie or HTTP authentication, using the above header will not reveal it. It will share the resource with APIs such as XMLHttpRequest
, much like it is already shared with curl
and wget
.
Thus in other words, if a resource cannot be accessed from a random device connected to the web using curl
and wget
the aforementioned header is not to be included. If it can be accessed however, it is perfectly fine to do so.
If CORS protocol requirements are more complicated than setting `Access-Control-Allow-Origin
` to *
or a static origin, `Vary
` is to be used. [HTML] [HTTP] [HTTP-CACHING]
Vary: Origin
In particular, consider what happens if `Vary
` is not used and a server is configured to send `Access-Control-Allow-Origin
` for a certain resource only in response to a CORS request. When a user agent receives a response to a non-CORS request for that resource (for example, as the result of a navigation request), the response will lack `Access-Control-Allow-Origin
` and the user agent will cache that response. Then, if the user agent subsequently encounters a CORS request for the resource, it will use that cached response from the previous non-CORS request, without `Access-Control-Allow-Origin
`.
But if `Vary: Origin
` is used in the same scenario described above, it will cause the user agent to fetch a response that includes `Access-Control-Allow-Origin
`, rather than using the cached response from the previous non-CORS request that lacks `Access-Control-Allow-Origin
`.
However, if `Access-Control-Allow-Origin
` is set to *
or a static origin for a particular resource, then configure the server to always send `Access-Control-Allow-Origin
` in responses for the resource — for non-CORS requests as well as CORS requests — and do not use `Vary
`.
As part of establishing a connection, the WebSocket
object initiates a special kind of fetch (using a request whose mode is "websocket
") which allows it to share in many fetch policy decisions, such HTTP Strict Transport Security (HSTS). Ultimately this results in fetch calling into WebSockets to obtain a dedicated connection. [WEBSOCKETS] [HSTS]
Fetch used to define obtain a WebSocket connection and establish a WebSocket connection directly, but both are now defined in WebSockets. [WEBSOCKETS]
Using fetch in other standardsIn its essence fetching is an exchange of a request for a response. In reality it is rather complex mechanism for standards to adopt and use correctly. This section aims to give some advice.
Always ask domain experts for review.
This is a work in progress.
Setting up a requestThe first step in fetching is to create a request, and populate its items.
Start by setting the request’s URL and method, as defined by HTTP. If your `POST
` or `PUT
` request needs a body, you set request’s body to a byte sequence, or to a new body whose stream is a ReadableStream
you created. [HTTP]
Choose your request’s destination using the guidance in the destination table. Destinations affect Content Security Policy and have other implications such as the `Sec-Fetch-Dest
` header, so they are much more than informative metadata. If a new feature requires a destination that’s not in the destination table, please file an issue to discuss. [CSP]
Set your request’s client to the environment settings object you’re operating in. Web-exposed APIs are generally defined with Web IDL, for which every object that implements an interface has a relevant settings object you can use. For example, a request associated with an element would set the request’s client to the element’s node document’s relevant settings object. All features that are directly web-exposed by JavaScript, HTML, CSS, or other Document
subresources should have a client.
If your fetching is not directly web-exposed, e.g., it is sent in the background without relying on a current Window
or Worker
, leave request’s client as null and set the request’s origin, policy container, service-workers mode, and referrer to appropriate values instead, e.g., by copying them from the environment settings object ahead of time. In these more advanced cases, make sure the details of how your fetch handles Content Security Policy and referrer policy are fleshed out. Also make sure you handle concurrency, as callbacks (see Invoking fetch and processing responses) would be posted on a parallel queue. [REFERRER] [CSP]
Think through the way you intend to handle cross-origin resources. Some features may only work in the same origin, in which case set your request’s mode to "same-origin
". Otherwise, new web-exposed features should almost always set their mode to "cors
". If your feature is not web-exposed, or you think there is another reason for it to fetch cross-origin resources without CORS, please file an issue to discuss.
For cross-origin requests, also determines if credentials are to be included with the requests, in which case set your request’s credentials mode to "include
".
Figure out if your fetch needs to be reported to Resource Timing, and with which initiator type. By passing an initiator type to the request, reporting to Resource Timing will be done automatically once the fetch is done and the response is fully downloaded. [RESOURCE-TIMING]
If your request requires additional HTTP headers, set its header list to a header list that contains those headers, e.g., « (`My-Header-Name
`, `My-Header-Value
`) ». Sending custom headers may have implications, such as requiring a CORS-preflight fetch, so handle with care.
If you want to override the default caching mechanism, e.g., disable caching for this request, set the request’s cache mode to a value other than "default
".
Determine whether you want your request to support redirects. If you don’t, set its redirect mode to "error
".
Browse through the rest of the parameters for request to see if something else is relevant to you. The rest of the parameters are used less frequently, often for special purposes, and they are documented in detail in the § 2.2.5 Requests section of this standard.
Invoking fetch and processing responsesAside from a request the fetch operation takes several optional arguments. For those arguments that take an algorithm: the algorithm will be called from a task (or in a parallel queue if useParallelQueue is true).
Once the request is set up, to determine which algorithms to pass to fetch, determine how you would like to process the response, and in particular at what stage you would like to receive a callback:
This is how most callers handle a response, for example scripts and style resources. The response’s body is read in its entirety into a byte sequence, and then processed by the caller.
To process a response upon completion, pass an algorithm as the processResponseConsumeBody argument of fetch. The given algorithm is passed a response and an argument representing the fully read body (of the response’s internal response). The second argument’s values have the following meaning:
Fully reading the contents of the response’s internal response’s body succeeded.
A byte sequence containing the full contents will be passed also for a request whose mode is "no-cors
". Callers have to be careful when handling such content, as it should not be accessible to the requesting origin. For example, the caller may use contents of a "no-cors
" response to display image contents directly to the user, but those image contents should not be directly exposed to scripts in the embedding document.
In some cases, for example when playing video or progressively loading images, callers might want to stream the response, and process it one chunk at a time. The response is handed over to the fetch caller once the headers are processed, and the caller continues from there.
To process a response chunk-by-chunk, pass an algorithm to the processResponse argument of fetch. The given algorithm is passed a response when the response’s headers have been received and is responsible for reading the response’s body’s stream in order to download the rest of the response. For convenience, you may also pass an algorithm to the processResponseEndOfBody argument, which is called once you have finished fully reading the response and its body. Note that unlike processResponseConsumeBody, passing the processResponse or processResponseEndOfBody arguments does not guarantee that the response will be fully read, and callers are responsible to read it themselves.
The processResponse argument is also useful for handling the response’s header list and status without handling the body at all. This is used, for example, when handling responses that do not have an ok status.
In some cases, there is no need for a response at all, e.g., in the case of navigator.sendBeacon()
. Processing a response and passing callbacks to fetch is optional, so omitting the callback would fetch without expecting a response. In such cases, the response’s body’s stream will be discarded, and the caller does not have to worry about downloading the contents unnecessarily.
Fetch a request whose URL is https://fire-and-forget.example.com/
, method is `POST
`, and client is this’s relevant settings object.
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 processRequestEndOfBody notify the caller of request body uploading progress.
Note that the fetch operation starts in the same thread from which it was called, and then breaks off to run its internal operations in parallel. The aforementioned callbacks are posted to a given event loop which is, by default, the client’s global object. To process responses in parallel and handle interactions with the main thread by yourself, fetch with useParallelQueue set to true.
Manipulating an ongoing fetchTo manipulate a fetch operation that has already started, use the fetch controller returned by calling fetch. For example, you may abort the fetch controller due the user or page logic, or terminate it due to browser-internal circumstances.
In addition to terminating and aborting, callers may report timing if this was not done automatically by passing the initiator type, or extract full timing info and handle it on the caller side (this is done only by navigations). The fetch controller is also used to process the next manual redirect for requests with redirect mode set to "manual
".
Thanks to Adam Barth, Adam Lavin, Alan Jeffrey, Alexey Proskuryakov, Andreas Kling, Andrés Gutiérrez, Andrew Sutherland, Andrew Williams, Ángel González, Anssi Kostiainen, Arkadiusz Michalski, Arne Johannessen, Artem Skoretskiy, Arthur Barstow, Arthur Sonzogni, Asanka Herath, Axel Rauschmayer, Ben Kelly, Benjamin Gruenbaum, Benjamin Hawkes-Lewis, Benjamin VanderSloot, Bert Bos, Björn Höhrmann, Boris Zbarsky, Brad Hill, Brad Porter, Bryan Smith, Caitlin Potter, Cameron McCormack, Carlo Cannas, 白丞祐 (Cheng-You Bai), Chirag S Kumar, Chris Needham, Chris Rebert, Clement Pellerin, Collin Jackson, Daniel Robertson, Daniel Veditz, Dave Tapuska, David Benjamin, David Håsäther, David Orchard, Dean Jackson, Devdatta Akhawe, Domenic Denicola, Dominic Farolino, Dominique Hazaël-Massieux, Doug Turner, Douglas Creager, Eero Häkkinen, Ehsan Akhgari, Emily Stark, Eric Lawrence, Eric Orth, Feng Yu, François Marier, Frank Ellerman, Frederick Hirsch, Frederik Braun, Gary Blackwood, Gavin Carothers, Glenn Maynard, Graham Klyne, Gregory Terzian, Guohui Deng(邓国辉), Hal Lockhart, Hallvord R. M. Steen, Harris Hancock, Henri Sivonen, Henry Story, Hiroshige Hayashizaki, Honza Bambas, Ian Hickson, Ilya Grigorik, isonmad, Jake Archibald, James Graham, Jamie Mansfield, Janusz Majnert, Jeena Lee, Jeff Carpenter, Jeff Hodges, Jeffrey Yasskin, Jensen Chappell, Jeremy Roman, Jesse M. Heines, Jianjun Chen, Jinho Bang, Jochen Eisinger, John Wilander, Jonas Sicking, Jonathan Kingston, Jonathan Watt, 최종찬 (Jongchan Choi), Jordan Stephens, Jörn Zaefferer, Joseph Pecoraro, Josh Matthews, jub0bs, Julian Krispel-Samsel, Julian Reschke, 송정기 (Jungkee Song), Jussi Kalliokoski, Jxck, Kagami Sascha Rosylight, Keith Yeung, Kenji Baheux, Lachlan Hunt, Larry Masinter, Liam Brummitt, Linus Groh, Louis Ryan, Luca Casonato, Lucas Gonze, Łukasz Anforowicz, 呂康豪 (Kang-Hao Lu), Maciej Stachowiak, Malisa, Manfred Stock, Manish Goregaokar, Marc Silbey, Marcos Caceres, Marijn Kruisselbrink, Mark Nottingham, Mark S. Miller, Martin Dürst, Martin O’Neal, Martin Thomson, Matt Andrews, Matt Falkenhagen, Matt Menke, Matt Oshry, Matt Seddon, Matt Womer, Mhano Harkness, Michael Ficarra, Michael Kohler, Michael™ Smith, Mike Pennisi, Mike West, Mohamed Zergaoui, Mohammed Zubair Ahmed, Moritz Kneilmann, Ms2ger, Nico Schlömer, Nicolás Peña Moreno, Nidhi Jaju, Nikhil Marathe, Nikki Bee, Nikunj Mehta, Noam Rosenthal, Odin Hørthe Omdal, Olli Pettay, Ondřej Žára, O. Opsec, Patrick Meenan, Perry Jiang, Philip Jägenstedt, R. Auburn, Raphael Kubo da Costa, Robert Linder, Rondinelly, Rory Hewitt, Ross A. Baker, Ryan Sleevi, Sam Atkins, Samy Kamkar, Sébastien Cevey, Sendil Kumar N, Shao-xuan Kang, Sharath Udupa, Shivakumar Jagalur Matt, Shivani Sharma, Sigbjørn Finne, Simon Pieters, Simon Sapin, Simon Wülker, Srirama Chandra Sekhar Mogali, Stephan Paul, Steven Salat, Sunava Dutta, Surya Ismail, Tab Atkins-Bittner, Takashi Toyoshima, 吉野剛史 (Takeshi Yoshino), Thomas Roessler, Thomas Steiner, Thomas Wisniewski, Tiancheng "Timothy" Gu, Tobie Langel, Tom Schuster, Tomás Aparicio, triple-underscore, 保呂毅 (Tsuyoshi Horo), Tyler Close, Ujjwal Sharma, Vignesh Shanmugam, Vladimir Dzhuvinov, Wayne Carr, Xabier Rodríguez, Yehuda Katz, Yoav Weiss, Youenn Fablet, Yoichi Osato, 平野裕 (Yutaka Hirano), and Zhenbin Xu for being awesome.
This standard is written by Anne van Kesteren (Apple, annevk@annevk.nl).
Intellectual property rightsCopyright © WHATWG (Apple, Google, Mozilla, Microsoft). This work is licensed under a Creative Commons Attribution 4.0 International License. To the extent portions of it are incorporated into source code, such portions in the source code are licensed under the BSD 3-Clause License instead.
This is the Living Standard. Those interested in the patent-review version should view the Living Standard Review Draft.
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.5