The Fetch standard defines requests, responses, and the process that binds them: fetching.
To unify fetching across the web platform this specification supplants a number of algorithms and specifications:
Origin
` header semantics
[ORIGIN]
Unifying fetching provides consistent handling of:
Referer
` [REFERRER]
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.
All diagrams, examples, and notes in this specification are non-normative, as are all sections explicitly marked non-normative. Everything else in this specification is normative.
The key words "MUST", "MUST NOT", "REQUIRED", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in the normative parts of this specification are to be interpreted as described in RFC2119. For readability, these words do not appear in all uppercase letters in this specification. [RFC2119]
This specification uses terminology from the ABNF, Encoding, HTML, IDL, Streams, and URL Standards. [ABNF] [ENCODING] [HTML] [WEBIDL] [STREAMS] [URL]
A byte sequence with bytes in the range 0x00 to 0x7F, inclusive, is represented as a utf-8-encoded string with code points in the range U+0000 to U+007F, inclusive. To avoid confusion with an actual string, backticks are used.
"true
" is a
string, while `true
` is a
byte sequence.
Comparing two byte sequences in a byte-case-insensitive manner means comparing them exactly, byte for byte, except that the bytes in the range 0x41 to 0x5A, inclusive, are considered to also match their corresponding byte in the range 0x61 to 0x7A, inclusive.
A case-insensitive byte sequence is a byte sequence that when compared to another byte sequence does so in a byte-case-insensitive manner.
The
case-insensitive byte sequences
`Content-Type
` and `content-TYPE
` are equal.
To byte-lowercase a byte sequence, increase each byte it contains, in the range 0x41 to 0x5A, inclusive, by 0x20.
To byte-uppercase a byte sequence, subtract each byte it contains, in the range 0x61 to 0x7A, inclusive, by 0x20.
A fetch URL is a URL for which implementations need not store the fragment as it is never exposed. When serialized, the exclude fragment flag is set, meaning implementations can store the fragment nonetheless.
Tasks that are queued by this standard are annotated as one of the following:
To queue a fetch task on request request to run an operation, run these steps:
If request's client is null, terminate these steps.
Queue a task to run an operation on request's client's responsible event loop using the networking task source.
To queue a fetch-done task given a request and response, run these steps:
Set request's done flag.
Queue a fetch task on request to process response end-of-file for response.
To wait for a response, wait for either end-of-file to have been pushed to response's body or for response to have a termination reason.
To read a request, if request's body is non-null, whenever request's body is read from (i.e. is transmitted or read by script), increase request's body's transmitted with the amount of payload body bytes transmitted and then queue a fetch task on request to process request body for request.
While 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).
The HTTP whitespace bytes are 0x09, 0x0A, 0x0D, and 0x20.
A method is a byte sequence that matches the method token production.
A simple method is a method that is
`GET
`, `HEAD
`, or `POST
`.
A forbidden method is a method that is a
byte-case-insensitive match for one of `CONNECT
`,
`TRACE
`, and `TRACK
`.
[HTTPVERBSEC]
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".
A header list consists of zero or more headers.
To append a name/value (name/value) pair to a header list (list), append a new header whose name is name, byte-lowercased, and value is value, to list.
To delete a name (name) from a header list (list), remove all headers whose name is name, byte-lowercased, from list.
To set a name/value (name/value) pair in a header list (list), run these steps:
Byte-lowercase name.
If there are any headers in list whose name is name, set the value of the first such header to value and remove the others.
Otherwise, append a new header whose name is name and value is value, to list.
To combine a name/value (name/value) pair in a header list (list), run these steps:
Byte-lowercase name.
If there are any headers in list whose name is name, set the value of the first such header to value, followed by 0x2C 0x20, followed by value.
Otherwise, append a new header whose name is name and value is value, to list.
Combine solely
exists for XMLHttpRequest
.
A header consists of a name and value. A name is a case-insensitive byte sequence that matches the field-name token production. A value is a byte sequence that matches the field-content token production.
field-value allows 0x0A and 0x0D bytes which can lead to reparsing issues.
To normalize a value, remove any leading and trailing HTTP whitespace bytes from it.
A simple header is a header whose
name is either one of `Accept
`,
`Accept-Language
`, and `Content-Language
`, or whose
name is `Content-Type
` and
value,
once parsed, has a MIME type (ignoring parameters)
that is one of `application/x-www-form-urlencoded
`,
`multipart/form-data
`, and `text/plain
`.
A forbidden header name is a header name that either is one of
Accept-Charset
`
Accept-Encoding
`
Access-Control-Request-Headers
`
Access-Control-Request-Method
`
Connection
`
Content-Length
`
Cookie
`
Cookie2
`
Date
`
DNT
`
Expect
`
Host
`
Keep-Alive
`
Origin
`
Referer
`
TE
`
Trailer
`
Transfer-Encoding
`
Upgrade
`
Via
`
or starts with `Proxy-
` or `Sec-
`
(including when it is just `Proxy-
` or `Sec-
`).
These are forbidden so the user agent remains in full control over them.
Names starting with `Sec-
` are
reserved to allow new headers to be minted that are safe
from APIs using fetch that allow control over
headers by developers, such as
XMLHttpRequest
.
[XHR]
A forbidden response-header name is a header name that is one of:
Set-Cookie
`
Set-Cookie2
`
To parse a header value given a name (name) and either a header or a header list (headers), run these steps:
If name is not in headers, return null.
If the ABNF for name allows a single header and headers contains more than one, return failure.
If different error handling is required, extract the desired header first.
If parsing all the headers named name in headers, per the ABNF for name, failed, return failure.
Return one or more values resulting from parsing all the headers named name in headers, per the ABNF for name.
To extract a MIME type from a header list (headers), run these steps:
Let MIMEType be the result of
parsing `Content-Type
` in
headers.
If MIMEType is null or failure, return the empty byte sequence.
Return MIMEType, byte-lowercased.
A status is a code.
A null body status is a status that is one of 101
, 204
, 205
, and 304
.
An ok status is any status in the range 200
to
299
, inclusive.
A redirect status is a status that is one of 301
,
302
, 303
, 307
, and 308
.
A body is a byte stream. It has an associated transmitted which is an integer and initially 0, length which is an integer and initially 0, and error flag which is initially unset.
To handle content codings given codings and bytes, run these substeps:
If codings are not supported, return bytes.
Return the result of decoding bytes with the given codings as explained in HTTP. [HTTP]
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 fetch URL).
A request has an associated local-URLs-only flag. Unless stated otherwise it is unset.
A request has an associated sandboxed-storage-area-URLs flag. Unless stated otherwise it is unset.
A request has an associated header list (a header list). Unless stated otherwise it is empty.
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 header names.
A request has an associated body (null or a body). Unless stated otherwise it is null.
A request has an associated client (null or an environment settings object).
A request has an associated
window ("no-window
",
"client
", or an
environment settings object whose
global object is a
Window
object). Unless stated otherwise it is
"client
".
The "client
" value is changed to either
"no-window
" or request's
client during
fetching. It provides a convenient way for standards to
not have to explicitly set request's
window.
A request has an associated target browsing context (null or a browsing context). Unless stated otherwise it is null.
A request has an associated keep-alive flag. Unless stated otherwise it is unset.
This is used by navigator.sendBeacon
and the HTML
img
element to outlive the
environment settings object.
A request has an associated skip-service-worker flag. Unless stated otherwise it is unset.
A request has an associated
initiator, which is one of
the empty string,
"download
",
"fetch
",
"imageset
",
"manifest
", and
"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. It is primarily a specification device to assist defining CSP and Mixed Content. It is not exposed to JavaScript. [CSP] [MIX]
A request has an associated
type, which is one of
the empty string,
"audio
",
"font
",
"image
",
"script
",
"style
",
"track
", and
"video
". Unless stated otherwise it is the empty string.
A request has an associated
destination, which is one of
the empty string,
"document
",
"serviceworker
",
"sharedworker
",
"subresource
",
"unknown
", and
"worker
".
The following table illustrates the relationship between a request's initiator, type, destination, CSP directives, and features.
Initiator | Type | Destination | CSP directive | Features |
---|---|---|---|---|
"" | "" | "" | ? | CSP, NEL reports. |
"document "
| HTML's navigate algorithm. | |||
"subresource "
| connect-src
| navigator.sendBeacon() , EventSource ,
HTML's ping="" , XMLHttpRequest
| ||
"unknown "
| object-src
| HTML's <embed> and <object>
| ||
"audio "
| "subresource "
| media-src
| HTML's <audio>
| |
"font "
| "subresource "
| font-src
| CSS' @font-face
| |
"image "
| "subresource "
| img-src
| HTML's <img src> , /favicon.ico resource,
SVG's <image> , CSS' background-image , CSS'
cursor , CSS' list-style-image , …
| |
"script "
| "subresource "
| script-src
| HTML's <script> , importScripts()
| |
"serviceworker "
| ? | navigator.serviceWorker.register()
| ||
"sharedworker "
| child-src
| SharedWorker
| ||
"worker "
| child-src
| Worker
| ||
"style "
| "subresource "
| style-src
| HTML's <link rel=stylesheet> , CSS' @import
| |
"track "
| "subresource "
| media-src
| HTML's <track>
| |
"video "
| "subresource "
| media-src
| HTML's <video> element
| |
"download "
| "" | "" | ? | HTML's download="" , "Save Link As…" UI
|
"fetch "
| "" | "subresource "
| connect-src
| fetch() , Cache API?
|
"imageset "
| "image "
| "subresource "
| img-src
| HTML's <img srcset> and <picture>
|
"manifest "
| "" | "subresource "
| manifest-src
| HTML's <link rel=manifest>
|
"xslt "
| "script "
| "subresource "
| 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 browsing context's ancestor browsing contexts for various CSP directives.
A request has an associated priority (null or a user-agent-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.
Request's origin can be
changed during redirects too.
A request has an associated
omit-Origin
-header flag. Unless stated otherwise it is unset.
A request has an associated same-origin data-URL flag. Unless stated otherwise it is unset.
A request has an associated
referrer, which is "no-referrer
",
"client
", or a URL.
Unless stated otherwise it is "client
".
"client
" is changed to either
"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.
This can be used to override a referrer policy associated with an environment settings object. [REFERRER]
A request has an associated synchronous flag. Unless stated otherwise it is unset.
A request has an associated
mode, which is one of "navigate
",
"same-origin
", "no-cors
", "cors
", and
"cors-with-forced-preflight
". Unless stated otherwise, it is
"no-cors
".
A request has an associated
credentials mode, which is
one of "omit
", "same-origin
", and
"include
". Unless stated otherwise, it is "omit
".
A request has an associated use-URL-credentials flag. Unless stated otherwise, it is unset.
A request has an associated
cache mode, which is one of
"default
", "no-store
", "reload
",
"no-cache
", "force-cache
", and
"only-if-cached
". Unless stated otherwise, it is
"default
".
If header list
contains a header whose
name is one of
`If-Modified-Since
`,
`If-None-Match
`,
`If-Unmodified-Since
`,
`If-Match
`, and
`If-Range
`, fetch will set
cache mode to "no-store
"
if it is "default
".
A request has an associated
redirect mode, which is one of
"follow
", "error
", and "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 an associated url list (a list of one or more fetch 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 fetch 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 one of
"basic
", "cors
", and "opaque
".
Unless stated otherwise, it is "basic
".
A request has an associated done flag. Unless stated otherwise, it is unset.
A request's url list, current url, redirect count, response tainting, and done flag are used as bookkeeping details by the fetch algorithm.
A subresource request is a request
whose destination is
"subresource
".
A potential-navigation-or-subresource request is a
request whose
destination is
"unknown
".
A non-subresource request is a request
whose destination is neither
"subresource
" nor "unknown
".
A navigation request is a request whose
destination is
"document
".
See handle fetch for usage of these terms. [SW]
The 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 one of
"basic
",
"cors
",
"default
",
"error
",
"opaque
", and
"opaqueredirect
".
Unless stated otherwise, it is "default
".
A response can have an associated termination reason which is one of end-user abort, fatal, and timeout.
A response has an associated url. It is a pointer to the last fetch URL in response's url list and null if response's url list is the empty list.
A response has an associated url list (a list of zero or more fetch URLs). Unless stated otherwise, it is the empty list.
Except for the last fetch URL, if any, a response's url list cannot be exposed to script. 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 `OK
`.
A response has an associated header list (a header list). Unless stated otherwise it is empty.
A response has an associated body (null or a body). Unless stated otherwise it is null.
A response has an associated
cache state which is one of
"none
",
"local
",
"validated
", and
"partial
". Unless stated otherwise, it is "none
".
A response has an associated
HTTPS state which is one of
"none
", "deprecated
", and
"modern
". Unless stated otherwise, it is "none
".
A response delivered over
HTTPS will typically have its HTTPS state
set to "modern
". A user agent can use "deprecated
"
in a transition period. E.g., while removing support for a hash function, weak cypher
suites, certificates for an "Internal Name", or certificates with an overly long validity
period. How exactly a user agent can use "deprecated
" is not defined by
this specification.
A response has an associated CSP list, which is a list of Content Security Policy objects for the response. The list is empty unless otherwise specified. [CSP]
A response whose
type is "error
" is known as a
network error.
A network error is a
response whose
status is always 0
,
status message is always the empty byte sequence,
header list is always empty,
body is always null, and
cache state is always "none
".
A filtered response is a limited view on a response that is not a network error. This response is referred to as the filtered response's associated internal response.
The fetch algorithm returns such a view to ensure APIs do not accidentally leak information. If the information is required, e.g., to feed image data to a decoder, the associated internal response can be used, which is only "accessible" to internal specification algorithms.
A basic filtered response is a
filtered response whose
type is "basic
",
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
",
header list excludes all
headers in
internal response's
header list, except those whose
name is either one of
`Cache-Control
`, `Content-Language
`,
`Content-Type
`, `Expires
`,
`Last-Modified
`, and `Pragma
`, and except those
whose name is both not a
forbidden response-header name and one of the
values resulting from
parsing
`Access-Control-Expose-Headers
` in
internal response's
header list.
An opaque filtered response is a
filtered response whose
type is "opaque
",
url list is the empty list,
status is 0
,
status message is the empty byte sequence,
header list is the empty list,
body is null, and
cache state is "none
".
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 the empty list,
body is null, and
cache state is "none
".
Exposing the url list for opaque-redirect filtered responses is harmless since no redirects are followed.
In other words, an opaque filtered response is nearly indistinguishable from a network error. When introducing new APIs, do not use the internal response for internal specification algorithms as you will leak information.
An authentication entry and a proxy-authentication entry are tuples of username, password, and realm, associated with one or more requests.
User agents should allow either to be cleared together with HTTP cookies and similar tracking functionality.
Further details are defined by HTTP. [HTTP]
Each environment settings object has an associated fetch group.
A fetch group holds an ordered list of fetch records.
A fetch record has an associated request (a request).
A fetch record has an associated fetch (a fetch algorithm or null).
When a fetch group is terminated, for each associated fetch record whose request's done flag or keep-alive flag is unset, terminate the fetch record's fetch with reason fatal.
A user agent has an associated connection pool. A connection pool consists of zero or more connections. Each connection is identified by an origin (an origin) and credentials (a boolean).
To obtain a connection, given an origin and credentials, run these steps:
If connection pool contains a connection whose origin is origin and credentials is credentials, return that connection.
Let connection be the result of establishing an HTTP connection to origin. [HTTP]
If establishing a connection does not succeed (e.g., a DNS, TCP, or TLS error), return failure.
Add connection to the connection pool with origin being origin and credentials being credentials.
Return connection.
This is intentionally a little vague as the finer points are still
evolving. 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.
A referrer policy is the empty string,
"no-referrer
", "no-referrer-when-downgrade
",
"origin-only
", "origin-when-cross-origin
", or
"unsafe-url
".
enum ReferrerPolicy { "", "no-referrer", "no-referrer-when-downgrade", "origin-only", "origin-when-cross-origin", "unsafe-url" };
The details of referrer policies are discussed in Referrer Policy. [REFERRER]
This section might be integrated into other standards, such as IDL.
A ReadableStream object represents a stream of data. In this section, we define common operations for ReadableStream. [STREAMS]
To enqueue chunk into a
ReadableStream
object stream, run these steps:
Call EnqueueInReadableStream
(stream,
chunk). Rethrow any exceptions.
To close a
ReadableStream
object stream, run these steps:
Call CloseReadableStream
(stream).
Rethrow any exceptions.
To construct a
ReadableStream
object with given strategy,
pull action and cancel action, all of which are optional, run these steps:
Let init be a new object.
Set init["pull"] to a function that runs pull if pull is given.
Set init["cancel"] to a function that runs cancel if cancel is given.
Set init["strategy"] to strategy if strategy is given.
Set init be the result of calling the initial value of
ReadableStream
as constructor with
init as an argument. Rethrow any exceptions.
Return stream.
To construct a fixed
ReadableStream
object with given chunks,
run these steps:
Let stream be the result of
constructing a
ReadableStream
object. Rethrow any exceptions.
For each chunk in chunks, enqueue chunk into stream. Rethrow any exceptions.
Close stream. Rethrow any exceptions.
To construct a
ReadableStream
object with given a byte stream
byteStream, run these steps:
This operation is a workaround and will be deleted when we stop using byte streams.
Let stream be a ReadableStream
object
such that consuming it will result in chunks each of which is a Uint8Array
object wrapping an ArrayBuffer
and the result of concatenating them all will be
equivalent to the byte sequence which would be read from byteStream. Rethrow any
exceptions.
Return stream.
To get a reader from a
ReadableStream
object stream, run these steps:
Let reader be the result of calling
AcquireReadableStreamReader
(stream).
Rethrow any exceptions.
Return reader.
To read all bytes from a
ReadableStream
object with reader, run these
steps:
Let promise be a new promise.
Let bytes be an empty byte sequence.
Let read be the result of calling
ReadFromReadableStreamReader
(reader).
When read is fulfilled with an object whose done
property is false and whose value
property is a
Uint8Array
object, append the value
property to
bytes and run the above step again.
When read is fulfilled with an object whose done
property is true, resolve promise with bytes.
When read is fulfilled with a value that matches with neither of the
above patterns, reject promise with a TypeError
.
When read is rejected with an error, reject promise with that error.
Return promise.
Because the reader grants exclusive access, the actual mechanism of how to read cannot be observed. Implementations could use more direct mechanism if convenient.
To tee a
ReadableStream
object stream, run these steps:
Return the result of calling
TeeReadableStream
(stream, true).
Rethrow any exception.
An empty
ReadableStream
object is the result of
constructing a fixed
ReadableStream
object with an empty list.
Constructing an empty
ReadableStream
object will not throw an exception.
A ReadableStream
object stream is said to be
readable if stream@[[state]] is
"readable".
A ReadableStream
object stream is said to be
closed if stream@[[state]] is "closed".
A ReadableStream
object stream is said to be
errored if stream@[[state]] is
"errored".
A ReadableStream
object stream is said to be
locked if the result of calling
IsReadableStreamLocked
(stream) is true.
A ReadableStream
object stream is said to
need more data if the following conditions
hold:
stream is readable.
The result of calling
GetReadableStreamDesiredSize
(stream) is
positive.
A ReadableStream
object stream is said to be
disturbed if the result of calling
IsReadableStreamDisturbed
(stream) is true.
Origin
` headerThe `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 CORS flag is
set as well as those where request's
method is `POST
`. Due to
compatibility constraints it is not included in all
fetches.
Its value ABNF:
Origin = origin-or-null origin-or-null = origin / %x6E.75.6C.6C ; "null", case-sensitive origin = scheme "://" host [ ":" port ]
This supplants the `Origin
`
header.
[ORIGIN]
To allow sharing resources cross-origin and allow for more versatile HTTP requests than
possible with HTML's form
element, the platform has
a CORS protocol layered on top of HTTP. It allows resources to declare they
can be shared with resources residing on a different
origin.
It needs to be an opt-in mechanism to prevent leaking data from resources behind a firewall (intranets). Additionally, for credentialed HTTP requests it needs to be opt-in to prevent leaking potentially-sensitive data.
This section explains the CORS protocol as it pertains to servers. Requirements for user agents are part of the fetch algorithm.
The CORS protocol consists of a set of headers that indicates whether a particular resource can be shared cross-origin.
For HTTP requests that are more involved than what is possible with HTML's
form
element, a CORS-preflight fetch is
performed, to ensure the resource understands the CORS protocol.
An HTTP request can be identified as pertaining in the CORS protocol if it
includes an `Origin
` header. This is named a
CORS request.
An HTTP request can be identified as being a check to see if the
CORS protocol is understood if it is a CORS request, uses
`OPTIONS
` as method, and includes
these headers:
Access-Control-Request-Method
`
Indicates which method a future CORS request to the same resource might use.
Access-Control-Request-Headers
`
Indicates which headers a future CORS request to the same resource might use.
This is named a CORS-preflight request.
An HTTP response to a CORS request can include the following headers:
Access-Control-Allow-Origin
`
Indicates whether a resource 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 a resource can be shared when
request's
credentials mode is
"include
".
For a CORS-preflight request,
request's
credentials mode is always
"omit
", 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 resource for the purposes of the CORS protocol.
The `Allow
` header is
not relevant for the purposes of the CORS protocol.
Access-Control-Allow-Headers
`
Indicates which headers are supported by the resource for the purposes of the CORS protocol.
Access-Control-Max-Age
`
Indicates how long 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:
Access-Control-Expose-Headers
`
Indicates which headers can be exposed as part of the HTTP response, via listing their names.
ABNF for the values of the headers used by the CORS protocol:
Access-Control-Request-Method = method Access-Control-Request-Headers = #field-name Access-Control-Allow-Origin = origin-or-null / "*" Access-Control-Allow-Credentials = %x74.72.75.65 ; "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
X-Content-Type-Options
` headerThe
`X-Content-Type-Options
`
response header can be used to require checking of a
response's `Content-Type
`
header against the
type of a
request.
Its value ABNF:
X-Content-Type-Options = "nosniff" ; case-insensitive
Run these steps:
If response's
header list has no
header whose
name is
`X-Content-Type-Options
`, return
allowed.
Let nosniff be the result of
parsing the first
header whose
name is
`X-Content-Type-Options
` in
response's header list.
If nosniff is failure, return allowed.
Let MIMEType be the result of extracting a MIME type from response's header list.
Let type be request's type.
"audio
", "video
" ...
If type is "image
", and
MIMEType (ignoring parameters) is not an
image MIME type,
return blocked.
If type is "font
" and
MIMEType (ignoring parameters) is not a
font MIME type,
return blocked.
If type is "script
", and MIMEType
(ignoring parameters) is not a JavaScript MIME type,
return blocked.
If type is "style
" and
MIMEType (ignoring parameters) is not
`text/css
`, return blocked.
If type is "track
" and
MIMEType (ignoring parameters) is not
`text/vtt
`, return blocked.
Return allowed.
The algorithm below defines fetching. In broad strokes, it takes a request and outputs a response.
That is, it either returns a response if request's synchronous flag is set, or it queues tasks annotated process response, process response body, and process response end-of-file for the response.
To capture uploads, if request's synchronous flag is unset, tasks annotated process request body and process request end-of-file for the request can be queued.
To perform a fetch using request, run the steps below. An ongoing fetch can be terminated with reason reason, which must be one of end-user abort, fatal, timeout, or garbage collection.
The user agent may be asked to suspend the ongoing fetch. The user agent may either accept or ignore the suspension request. The susppended 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 agant 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]
If request's window is
"client
", set request's
window to request's
client, if request's
client's
global object is a
Window
object, and to "no-window
"
otherwise.
If request's origin is
"client
", set request's
origin to request's
client's origin.
If request's initiator
is not "fetch
" and request's
header list does not contain a
header whose
name is `Accept
`, run these
substeps:
This is accounting for XMLHttpRequest
, which like
fetch()
can set this header, but has a default value
for it.
Let value be `*/*
`.
If request is a navigation request, set
value to
`text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
`.
Otherwise, set value to the first matching statement, if any, switching on request's type:
image
"
image/png,image/svg+xml,image/*;q=0.8,*/*;q=0.5
`
style
"
text/css,*/*;q=0.1
`
User agents should append
`Accept
`/value to
request's header list.
If request's
initiator is not "fetch
"
and request's header list
does not contain a header whose
name is
`Accept-Language
`, user agents should
append
`Accept-Language
`/an appropriate value
to request's header list.
If request's priority is null, use request's initiator, type, and destination appropriately in setting it to a user-agent-defined object.
The user-agent-defined object could encompass stream weight and dependency for HTTP/2, and equivalent information used to prioritize dispatch and processing of HTTP/1 fetches.
If request is a subresource request, run these substeps:
Let record be a new fetch record consisting of request and this instance of the fetch algorithm.
Append record to request's client's fetch group list of fetch records.
Return the result of performing a main fetch using request.
To perform a main fetch using request, optionally with a CORS flag, run these steps:
The CORS flag is a bookkeeping detail for handling redirects.
Let response be null.
If request's local-URLs-only flag is set and request's current url is not local, set response to a network error.
Upgrade request to a potentially secure URL, if appropriate. [UPGRADE]
If should fetching request be blocked as mixed content or should fetching request be blocked by Content Security Policy returns blocked, set response to a network error. [MIX] [CSP]
If request's referrer
is not "no-referrer
", 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.
If request's current url contains a Known HSTS Host, modify it per the requirements of the "URI [sic] Loading and Port Mapping" chapter of HTTP Strict Transport Security. [HSTS]
If request's synchronous flag is unset and main fetch is not invoked recursively, run the remaining steps in parallel.
If response is null, set response to the value corresponding to the first matching statement:
data
" and request's
same-origin data-URL flag is set
about
"
navigate
"
The result of performing a basic fetch using request.
same-origin
"
no-cors
"
Set request's
response tainting to
"opaque
".
The result of performing a basic fetch using request.
http
" and "https
"
cors-with-forced-preflight
"
Set request's
response tainting to
"cors
" and request's
redirect mode to
"error
".
The result of performing an HTTP fetch using request with the CORS flag and CORS-preflight flag set. If the result is a network error, clear cache entries using request.
Set request's
response tainting to
"cors
".
The result of performing an HTTP fetch using request with the CORS flag set.
If main fetch is invoked recursively, return response.
If response is not a network error and response is not a filtered response, 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's internal response.
If should internalResponse to request be blocked as mixed content, should internalResponse to request be blocked by Content Security Policy, or should internalResponse to request be blocked due to nosniff returns blocked, set response to a network error. [MIX] [CSP]
If 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 pushing toward it (if any).
This standardizes the error handling for servers that violate HTTP.
If request's integrity metadata is not the empty string and response is not a network error, run these substeps:
If response does not have a termination reason and response does not match request's integrity metadata, set response to a network error. [SRI]
This operates on response as this algorithm is not supposed to observe internalResponse.
Set internalResponse's url list to a copy of request's url list.
If request's synchronous flag is set, wait for internalResponse, and then return response.
This terminates fetch.
If request's body is
non-null and request's
current url's
scheme is
"http
" or "https
",
queue a fetch task on request to
process request end-of-file for request.
Queue a fetch task on request to process response for response.
If internalResponse's body is null, run these substeps:
Queue a fetch-done task using request and response.
Otherwise, if internalResponse's body is non-null, run these substeps:
Whenever internalResponse's body's is pushed to, for and as long as internalResponse has no termination reason and end-of-file has not been pushed, queue a fetch task on request to process response body for response.
Once end-of-file has been pushed to internalResponse's body or internalResponse has a termination reason, queue a fetch-done task using request and response.
Ideally FTP/HTTP define this in more detail and this becomes a set of simple hooks.
To perform a basic fetch using request, switch on request's current url's scheme, and run the associated steps:
about
"
If request's
current url's
non-relative flag is set and
path contains a single string
"blank
", return a response whose
header list consist of a single
header whose
name is `Content-Type
` and
value is
`text/html;charset=utf-8
`,
body is the empty byte sequence, and
HTTPS state is request's
client's HTTPS state
if request's client is non-null.
Otherwise, if request's
current url's
non-relative flag is set and
path contains a single string
"unicorn
", return a response
whose header list consist of a single
header whose
name is `Content-Type
` and
value is
`image/svg+xml
`,
body is
`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 2361 1572" fill="hotpink"><path d="m1648 1570c-42-12 6-93 55-94 46 0 50-10 46-123-5-122-7-126-119-202-81-55-145-128-175-201-12-30-26-59-31-63s-58-4-119 0c-70 6-131 5-170-2-59-10-84-21-220-93-68-36-72-37-145-31-41 4-100 11-131 17-55 10-57 12-62 47-16 95 3 152 49 152 14 0 29 8 34 19 14 25 13 101-0 101-12 0-60-46-60-58 0-4-17-18-38-31l-38-23-2-115c-1-64 2-124 8-133s24-21 42-25c59-12 128-37 128-46 0-5-4-9-10-9-14 0-28-30-45-95-12-47-13-69-3-124 11-62 10-71-10-109-12-23-22-50-22-60s-7-27-15-37c-18-23-19-18-5 24 8 24 7 50-5 110-10 48-14 96-10 120 8 47-9 72-48 72-40 0-66-26-77-81-6-28-30-88-53-133-23-45-45-88-48-96-4-8-22-20-41-26-26-9-34-17-34-36 0-22 4-24 37-21l37 3-9-33c-12-43-6-47 31-20l30 22 26-20c14-11 39-38 55-61 39-53 63-62 139-49 46 8 64 8 75-2 8-7 15-8 15-4-0 15-14 30-34 37-37 14-6 19 44 7 49-12 53-11 90 15 28 19 48 26 69 23 37-6 29 10-16 28-19 8-32 19-28 24 4 6 15 5 30-2 18-8 35-7 71 5 27 9 58 16 71 16 32 0 29 17-7 35-16 9-30 17-30 20 0 2 22 2 49-2 44-5 52-3 96 31 27 20 54 34 62 32 25-10 14 4-16 19-16 8-39 15-50 15-29 0-26 16 20 87 45 68 96 101 189 123 149 35 239 59 268 71 27 12 36 11 67-4 21-10 41-29 47-45 23-59 39-78 80-101 60-32 141-27 175 12 23 28 25 34 43 178 15 118 36 182 72 224 28 32 35 35 90 35 75 0 125-21 167-68l33-37-17 40c-16 41-65 98-100 117-11 6-42 17-70 24l-50 12 62 1c48 0 72-5 116-28 50-25 55-26 45-8-17 33-98 115-136 139-29 18-51 22-113 22-71 1-80-2-115-30-21-17-86-28-99-128-7-56 0-176 0-176s18-102-6-175c-19-57-81-86-123-20-19 30-43 60-54 67-18 12-18 13 6 59 34 67 38 144 14 260l-20 95 24 35c13 20 40 51 59 70 40 38 41 50 29 252-6 92-9 107-25 111-10 3-19 12-19 20s-7 18-17 20c-32 10-87 15-105 10zm-1228-1255c0-18-2-19-16-8-12 10-13 15-3 21 18 11 18 11 18-13zm743 1151c-12-5-23-14-23-20 0-17 57-69 76-69 21 0 130-65 167-99 47-43 36-101-38-198-30-39-73-148-63-158 2-2 30-5 63-7l60-3 32 60c41 77 38 69 63 145 40 115 41 112-31 166-34 27-79 62-98 79-20 17-43 34-53 38-10 3-22 17-27 30-5 14-13 27-17 29-19 12-90 16-111 7zm-913-440c0-23 28-113 44-145 6-11 32-51 57-90 26-39 50-81 53-95 5-21 22-30 103-59 53-19 102-36 108-38 6-2 18 11 27 30l16 34-92 28c-105 32-126 47-161 122-16 34-35 58-50 63-32 13-40 42-22 85l15 36-37 25c-45 30-62 31-62 4zm-48-843c-41-18-25-52 19-39 21 6 23 10 14 28-9 17-15 19-33 11zm-74-25c-28-6-31-32-4-32 13 0 26 4 29 8 8 13-8 28-25 24zm-78-37c0-9 6-12 15-9 19 7 19 24 0 24-8 0-15-7-15-15zm-50-15c0-5 7-7 15-4 19 7 19 14 0 14-8 0-15-4-15-10z"/></svg>
`,
and HTTPS state is
request's client's
HTTPS state if request's
client is non-null.
View
"about:unicorn
".
Otherwise, return a network error.
URLs such
as "about:config
" are handled during
navigation and result in a
network error in the context of
fetching.
blob
"
Let blob be request's current url's object.
If request's method is not
`GET
` or blob is null, return a
network error.
Let response be a new response.
Append
`Content-Length
`/blob's
size
attribute value to
response's
header list.
Append
`Content-Type
`/blob's
type
attribute value to
response's
header list.
Set response's HTTPS state to request's client's HTTPS state if request's client is non-null.
Set response's body to the result of performing the read operation on blob.
Return response.
data
"
If request's method is
`GET
` and
obtaining a resource from
request's current url
does not return failure, return a response whose
header list consist of a single
header whose
name is `Content-Type
` and
value is the MIME type and parameters returned
from obtaining a resource,
body is the data returned from
obtaining a resource, and
HTTPS state is request's
client's HTTPS state
if request's client is non-null.
[DATAURL]
Otherwise, return a network error.
file
"
ftp
"
For now, unfortunate as it is, file
and ftp
URLs are left as an exercise for the
reader.
When in doubt, return a network error.
filesystem
"If request's sandboxed-storage-area-URLs flag is set, return a network error.
Otherwise, … this scheme still needs to be defined.
http
"
https
"
Return the result of performing an HTTP fetch using request.
Return a network error.
To perform an HTTP fetch using request with an optional CORS flag, CORS-preflight flag, and authentication-fetch flag, run these steps:
The CORS flag is still a bookkeeping detail. The CORS-preflight flag and authentication-fetch flag are too. The former indicates a CORS-preflight request is required and the latter indicates an attempt to authenticate.
Let response be null.
If request's skip-service-worker flag is unset and
either request's client is
null or request's client's
global object is not a
ServiceWorkerGlobalScope
object, run these substeps:
[HTML]
[SW]
Set response to the result of invoking handle fetch for request. [SW]
If one of the following conditions is true, return a network error:
error
".
no-cors
" and response's
type is "opaque
".
manual
" and response's
type is "opaqueredirect
".
If response is a filtered response, then execute set response's CSP list on response's internal response. Otherwise, execute set response's CSP list on response. [CSP]
If response is null, run these substeps:
If the CORS-preflight flag is set and one of these conditions is true:
cors-with-forced-preflight
".
Then run these subsubsteps:
Let preflightResponse be the result of performing a CORS-preflight fetch using request.
If preflightResponse is a network error, return preflightResponse.
Set request's skip-service-worker flag.
There might be redirects. Alternatively, request's window is an environment settings object and the CORS flag is unset.
Let credentials flag be set if one of
include
"
same-origin
" and either the CORS flag is unset or
response tainting is
"opaque
"
is true, and unset otherwise.
If request's
cache mode is "default
" and
request's header list
contains a header
named
`If-Modified-Since
`,
`If-None-Match
`,
`If-Unmodified-Since
`,
`If-Match
`, or
`If-Range
`, set request's
cache mode to "no-store
".
Set response to the result of performing an HTTP-network-or-cache fetch using request with credentials flag if set and authentication-fetch flag if set.
If the CORS flag is set and a CORS check for request and response returns failure, return a network error.
There is no need to apply this to a response from a service worker.
Switch on actualResponse's status:
304
If request's
cache mode is neither
"default
" nor "no-cache
", do nothing.
Otherwise, run these subsubsteps:
If there is no entry in the HTTP cache for request and response, return a network error.
Set response to the result of obtaining a response from the HTTP cache using request and response.
This changes response entirely,
including its status which is most
likely 200
now.
Set response's
cache state to
"validated
".
Unclear how to rework this in terms of actualResponse. See also 206/304 handling broken?
If request's
redirect mode is
"error
", return a
network error.
Let location be the result of
parsing `Location
` in
actualResponse's
header list.
If location is null, return response.
If location is failure, return a network error.
Let locationURL be the result of parsing location with request's current url.
If locationURL is failure or its
scheme is "data
",
return a network error.
If request's redirect count is twenty, return a network error.
Increase request's redirect count by one.
If request's
redirect mode is
"manual
", set response to an
opaque-redirect filtered response
whose internal response is
actualResponse.
Otherwise, request's
redirect mode is
"follow
", run these substeps:
If request's mode is
either "cors
" or "cors-with-forced-preflight
",
request's origin is
not same origin with
locationURL's
origin, and
locationURL
includes credentials,
return a network error.
If the CORS flag is set and locationURL includes credentials, return a network error.
This catches a cross-origin resource redirecting to a same-origin URL.
If the CORS flag is set and locationURL's origin is not same origin with request's current url's origin, set request's origin to an opaque identifier.
If either actualResponse's
status is
301
or 302
and request's
method is `POST
`, or
actualResponse's status is
303
, set request's
method to `GET
`.
Append locationURL to request's url list.
Return the result of performing a main fetch using request, with the CORS flag set if set.
This has to invoke main fetch to get response tainting correct.
401
If request's window
is "no-window
" or the CORS flag is set, return
response.
Needs testing: multiple `WWW-Authenticate
` headers,
missing, parsing issues.
If request's use-URL-credentials flag is unset, or the authentication-fetch flag is set, run these substeps:
Let username and password be the result of prompting the end user for a username and password, respectively, in request's window.
Set the username given request's current url and username.
Set the password given request's current url and password.
Return the result of performing an HTTP fetch using request, with the authentication-fetch flag set.
407
If request's window
is "no-window
", return a
network error.
Needs testing: multiple `Proxy-Authenticate
` headers,
missing, parsing issues.
Prompt the end user as appropriate in request's window and store the result as a proxy-authentication entry. [HTTP]
Remaining details surrounding proxy authentication are defined by HTTP.
Return the result of performing an HTTP fetch using request.
Do nothing.
If the authentication-fetch flag is set, create an authentication entry for request and the given realm.
Return response. Typically actualResponse's body is still being pushed to after returning.
To perform an HTTP-network-or-cache fetch using request with an optional credentials flag and authentication-fetch flag, run these steps:
The authentication-fetch flag is still a bookkeeping detail. The credentials flag is one too.
Let httpRequest be request if
request's window is
"no-window
" and request's
redirect mode is not
"follow
", and a copy of request, with
httpRequest's body being a tee
of request's body, otherwise.
A request is typically copied as it needs to be possible to add headers and read its body without affecting request. As request is reused with redirects, authentication, proxy authentication.
Let contentLengthValue be null.
If httpRequest's body is
null and httpRequest's method
is `HEAD
`, `POST
`, or `PUT
`, set
contentLengthValue to `0
`.
If httpRequest's body is non-null, set contentLengthValue to httpRequest's body's length, utf-8 encoded.
If contentLengthValue is non-null,
append
`Content-Length
`/contentLengthValue to
httpRequest's
header list.
Append
`Referer
`/empty byte sequence, if httpRequest's
referrer is "no-referrer
", and
`Referer
`/httpRequest's
referrer,
serialized and
utf-8 encoded, otherwise, to
httpRequest's
header list.
If httpRequest's omit-Origin
-header flag is
unset, append
`Origin
`/httpRequest's
origin,
serialized
and utf-8 encoded, to
httpRequest's
header list.
If httpRequest's
header list does not contain a
header whose
name is
`User-Agent
`, user agents should
append
`User-Agent
`/an appropriate value to
httpRequest's
header list.
Modify httpRequest's header list per HTTP.
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-Charset
` must not be included.
`Accept
` and
`Accept-Language
` are already included at this
point (unless fetch()
is used, which can omit them).
See HTTP header layer division.
If credentials flag is set, run these substeps:
Modify httpRequest's header list per HTTP State Management Mechanism. [COOKIES]
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, set authorizationValue to authentication entry.
Otherwise, if httpRequest's
current url does
include credentials and the
authentication-fetch flag is set, set
authorizationValue to httpRequest's
current url,
converted to an `Authorization
` value.
If authorizationValue is non-null,
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.
Let response be null.
If httpRequest's
cache mode is neither
"no-store
" nor "reload
", and there is a complete
response in the HTTP cache for
httpRequest run these substeps:
If httpRequest's
cache mode is either
"force-cache
" or "only-if-cached
", set response
to the response in the HTTP cache for
httpRequest.
Otherwise, if httpRequest's
cache mode is "default
" and
the response in the HTTP cache for
httpRequest does not require revalidation, set
response to that response and set
response's cache state
to "local
".
Otherwise, if httpRequest's
cache mode is either "default
"
or "no-cache
", and the response in the
HTTP cache for httpRequest does require revalidation, modify
httpRequest's
header list with revalidation
headers.
Otherwise, if httpRequest's
cache mode is either
"default
" or "force-cache
", and there is a
partial response in the HTTP cache for
httpRequest, modify httpRequest's
header list with resume
headers.
If response is null, run these substeps:
If httpRequest's
cache mode is
"only-if-cached
", return a
network error.
Set response to the result of making an HTTP-network fetch using httpRequest with the credentials flag set if set.
Return response. Typically response's body is still being pushed to after returning.
To perform an HTTP-network fetch using request with an optional credentials flag, run these steps:
Let credentials be true if credentials flag is set, and false otherwise.
Let connection be the result of obtaining a connection, given request's current url's origin and credentials.
If connection is failure, return a network error.
Let response be the result of making an HTTP request over connection using request, following the relevant requirements from HTTP, and waiting until all the headers are transmitted or fetch is being terminated with reason reason. If fetch is being terminated, set response's termination reason to reason. [HTTP]
If the HTTP request results in a TLS client certificate dialog, run these substeps:
If request's window is an environment settings object, make the dialog available in request's window.
Otherwise, return a network error.
If response was retrieved over HTTPS, set its
HTTPS state to either
"deprecated
" or "modern
".
[TLS]
The exact determination here is up to user agents for the
time being. User agents are strongly encouraged to only succeed HTTPS connections with
strong security properties and return
network errors otherwise. Using the
"deprecated
" state value ought to be a temporary and last resort kind
of option.
Run these substeps in parallel, after the outer set of steps has returned:
If response's body is non-null, set response's body's length to response's body's payload body length.
Whenever one or more bytes are transmitted, let bytes be the transmitted bytes and run these subsubsteps:
Increase response's body's transmitted with bytes' length.
Let codings be the result of
parsing `Content-Encoding
`
in response's
header list.
Set bytes to the result of handling content codings given codings and bytes.
Push bytes to response's body.
This means that the `Content-Length
`
header is no longer reliable. A
response will still include it, but it cannot be
used, except for debugging and logging purposes.
These are run in parallel as at this point it is unclear whether response's body is relevant (response might be a redirect).
Delete
`Content-Encoding
` from response's
header list if one of the following
conditions is true:
Content-Encoding
` in response's
header list returns
`gzip
` and parsing
`Content-Type
in response's
header list returns
`application/gzip
`, `application/x-gunzip
`, or
`application/x-gzip
`.
Content-Encoding
` in response's
header list returns
`compress
` and parsing
`Content-Type
in response's
header list returns
`application/compress
` or
`application/x-compress
.
This deals with broken Apache configurations. Ideally HTTP would define this.
Gecko bug 1030660 looks into whether this quirk can be removed.
Execute set response's CSP list on response. [CSP]
If response is not a
network error and request's
cache mode is not "no-store
",
update response in the HTTP cache for request.
If credentials flag is set and response's
header list contains one or more
headers named
`Set-Cookie
`, run these substeps:
Wait until ownership of the storage mutex can be taken by this instance of the fetch algorithm.
Take ownership of the storage mutex.
Update the cookies. [COOKIES]
This is a fingerprinting vector.
Release the storage mutex so that it is once again free.
Return response. Typically response's body is still being pushed to after returning.
To perform a CORS-preflight fetch using request, run these steps:
Let preflight be a new request
whose method is `OPTIONS
`,
url is request's
current url,
initiator is request's
initiator,
type is request's
type,
destination is request's
destination,
origin is request's
origin,
referrer is request's
referrer, and
referrer policy is
request's
referrer policy.
Set
`Access-Control-Request-Method
` to
request's method in
preflight's header list.
Let headers be the names of request's header list's headers, excluding duplicates, sorted lexicographically, and byte-lowercased.
Let value be the items in headers separated from each other by 0x2C 0x20.
Set
`Access-Control-Request-Headers
`
to value in
preflight's header list.
Let response be the result of performing an HTTP-network-or-cache fetch using preflight.
If a CORS check for request and response returns success and response's status is an ok status, run these substeps:
The CORS check is done on request rather than preflight to ensure the correct credentials mode is used.
Let methods be the result of
parsing
`Access-Control-Allow-Methods
` in
response's
header list.
Let headerNames be the result of
parsing
`Access-Control-Allow-Headers
` in
response's
header list.
If either methods or headerNames is failure, return a network error.
If methods is null and request's
mode is
"cors-with-forced-preflight
", set methods to
request's method.
This ensures that a CORS-preflight fetch that
happened due to request's
mode being
"cors-with-forced-preflight
" is cached.
If request's method is not in methods and is not a simple method, return a network error.
If one of request's header list' names is not in headerNames and its corresponding header is not a simple header, return a network error.
Let max-age be the result of
parsing
`Access-Control-Max-Age
` in
response's
header list.
If max-age is failure or null, set max-age to zero.
If max-age is greater than an imposed limit on max-age, set max-age to the imposed limit.
If the user agent does not provide for a cache, return response.
For each method in methods for which there is a method cache match using request, set matching entry's max-age to max-age.
For each method in methods for which there is no method cache match using request, create a new entry in CORS-preflight cache as follows:
include
", and true otherwise
For each headerName in headerNames for which there is a header-name cache 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 match using request, create a new entry in CORS-preflight cache as follows:
include
", and true otherwise
Return response.
Otherwise, return a network error.
A CORS-preflight cache consists of a collection of entries where each entry has these fields: origin, url, max-age, credentials, method, and header name.
Entries must be removed after the seconds specified in the max-age field have passed since storing the entry. Entries may be removed before that moment arrives.
To clear cache entries given a request, remove any entries in the CORS-preflight cache whose origin is request's origin and whose url is request's current url.
There is a cache match for
request if origin is
request's origin,
url is request's
current url, and either
credentials is false and
request's
credentials mode is not
"include
" or credentials is true.
There is a method cache match for method using request when there is an entry in CORS-preflight cache for which there is a cache match for request and its method is method.
There is a header-name cache match for headerName using request when there is an entry in CORS-preflight cache for which there is a cache match for request and its header name is headerName.
To perform a CORS check for a request and response, run these steps:
Let origin be the result of
parsing
`Access-Control-Allow-Origin
` in
response's header list.
If origin is null or failure, return failure.
Null is not `null
`.
If request's
credentials mode is not
"include
" and origin is `*
`, return success.
If request's origin, serialized and utf-8 encoded, is not origin, return failure.
If request's
credentials mode is not
"include
", return success.
Let credentials be the result of
parsing
`Access-Control-Allow-Credentials
`
in response's
header list.
If credentials is `true
`, return success.
It has been suggested to check for origin not being
`null
` here as that would be equal to allowing credentials and
`*
` which is also forbidden.
Return failure.
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 resources:
fetch("https://pk.example/berlin-calling.json", {mode:"cors"}) .then(res => { if(res.headers.get("content-type") == "application/json") { 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 new Promise((resolve, reject) => { function pump() { reader.read().then(({done, value}) => { if (done) { resolve() return } total += value.byteLength log(`received ${value.byteLength} bytes (${total} bytes in total)`) pump() }).catch(reject) } 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 (Headers or sequence<sequence<ByteString>> or OpenEndedDictionary<ByteString>) HeadersInit;
OpenEndedDictionary<T> is a future IDL construct. Expect it to be used as such:
var meta = { "Content-Type": "text/xml", "Breaking-Bad": "<3" } new Headers(meta)
[Constructor(optional HeadersInit init), Exposed=(Window,Worker)] interface Headers { void append(ByteString name, ByteString value); void delete(ByteString name); ByteString? get(ByteString name); sequence<ByteString> getAll(ByteString name); boolean has(ByteString name); void set(ByteString name, ByteString value); iterable<ByteString, ByteString>; };
A Headers
object has an associated
header list (a
header list), which is initially empty.
A Headers
object also has an associated
guard, which is one of
"immutable
", "request
",
"request-no-cors
", "response
" and
"none
".
"immutable
" exists for service workers.
[SW]
To append a
name/value
(name/value) pair to a
Headers
object (headers), run these steps:
Normalize value.
If name is not a name or
value is not a value,
throw a TypeError
.
Otherwise, if guard is
"request
" and name is a forbidden header name,
return.
Otherwise, if guard is
"request-no-cors
" and name/value is not a
simple header, return.
Otherwise, if guard is
"response
" and name is a
forbidden response-header name, return.
Append name/value to header list.
To fill a Headers
object
(headers) with a given object (object), run these steps:
If object is a Headers
object, copy its
header list as
headerListCopy and then for each header in
headerListCopy, retaining order,
append
header's name/header's value
to headers. Rethrow any exception.
Once Headers.prototype[Symbol.iterator]
is defined this
special casing will no longer be needed.
Otherwise, if object is a sequence, then for each header in object, run these substeps:
Otherwise, if object is an open-ended dictionary, then for each header in object, run these substeps:
Set header's key to header's key, converted to ByteString. Rethrow any exception.
Append header's key/header's value to headers. Rethrow any exception.
The Headers(init)
constructor,
when invoked, must run these steps:
If init is given, fill headers with init. Rethrow any exception.
Return headers.
The
append(name, value)
method, when invoked, must append
name/value to the
context object and rethrow any exception.
The delete(name)
method, when invoked, must run these steps:
Otherwise, if guard is
"request
" and name is a forbidden header name,
return.
Otherwise, if guard is
"request-no-cors
" and name/`invalid
` is
not a simple header, return.
Otherwise, if guard is
"response
" and name is a
forbidden response-header name, return.
Delete name from header list.
The get(name)
method, when
invoked, must run these steps:
Return the value of the first header in header list whose name is name, and null otherwise.
The getAll(name)
method,
when invoked, must run these steps:
Return the values of all headers in header list whose name is name, in list order, and the empty sequence otherwise.
The has(name)
method,
when invoked, must run these steps:
Return true if there is a header in header list whose name is name, and false otherwise.
The
set(name, value)
method, when invoked, must run these steps:
Normalize value.
If name is not a name or
value is not a value,
throw a TypeError
.
Otherwise, if guard is
"request
" and name is a forbidden header name,
return.
Otherwise, if guard is
"request-no-cors
" and name/value is not a
simple header, return.
Otherwise, if guard is
"response
" and name is a
forbidden response-header name, return.
Set name/value in header list.
The value pairs to iterate over are the headers in the header list with the key being the name and value the value.
typedef any JSON; typedef (Blob or BufferSource or FormData or URLSearchParams or USVString) BodyInit;
To extract a byte stream and a
`Content-Type
` value from
object, run these steps:
Let stream be an empty byte stream.
Let Content-Type be null.
Switch on object's type:
Blob
Push a copy of object's contents to stream.
If object's
type
attribute is not the
empty byte sequence, set Content-Type to its value.
BufferSource
Push a copy of object to stream.
FormData
Push the result of running the
multipart/form-data
encoding algorithm,
with object as form data set and with
utf-8 as the explicit character encoding, to
stream.
Set Content-Type to `multipart/form-data;boundary=
`,
followed by the
multipart/form-data
boundary string
generated by the
multipart/form-data
encoding algorithm.
URLSearchParams
Push the result of running the
application/x-www-form-urlencoded
serializer,
with object's
list, to
stream.
Set Content-Type to
`application/x-www-form-urlencoded;charset=UTF-8
`.
USVString
Push the result of running utf-8 encode on object to stream.
Set Content-Type to `text/plain;charset=UTF-8
`.
Return stream and Content-Type.
[NoInterfaceObject, Exposed=(Window,Worker)] interface Body { readonly attribute boolean bodyUsed; [NewObject] Promise<ArrayBuffer> arrayBuffer(); [NewObject] Promise<Blob> blob(); [NewObject] Promise<FormData> formData(); [NewObject] Promise<JSON> 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 implementing the Body
mixin gain a
MIME type (initially the empty byte sequence).
Objects implementing the Body
mixin must define an associated
disturbed predicate and a
consume body algorithm.
The bodyUsed
attribute's getter must
return true if disturbed, and false otherwise.
Objects implementing the Body
mixin also have an associated
package data algorithm, which given
bytes, a type and a MIME type, switches on type, and
runs the associated steps:
Return an ArrayBuffer
whose contents are bytes. Rethrow any
exceptions.
Return a Blob
whose contents are
bytes and type
is MIME type.
If MIME type (ignoring parameters) is `multipart/form-data
`,
run these substeps:
Parse bytes, using the value of the
`boundary
` parameter from MIME type and
utf-8 as encoding, per the rules set forth
in Returning Values from Forms: multipart/form-data.
[RFC2388]
If that fails for some reason, throw a
TypeError
.
Return a new FormData
object, appending each entry,
resulting from the parsing operation, to
entries.
The above is a rough approximation of what is required for
`multipart/form-data
`, a more detailed parsing specification is to be
written. Volunteers welcome.
Otherwise, if MIME type (ignoring parameters) is
`application/x-www-form-urlencoded
`, run these substeps:
Otherwise, throw aTypeError
.
Return the result of invoking the initial value of the parse
property of
the JSON
object with the result of running
utf-8 decode on bytes as argument.
Rethrow any exceptions.
Return the result of running utf-8 decode on bytes.
The arrayBuffer()
method, when invoked, must return the result of running
consume body with ArrayBuffer.
The blob()
method, when
invoked, must return the result of running
consume body with Blob.
The formData()
method,
when invoked, must return the result of running
consume body with FormData.
The json()
method, when
invoked, must return the result of running
consume body with JSON.
The text()
method, when
invoked, must return the result of running
consume body with text.
typedef (Request or USVString) RequestInfo; [Constructor(RequestInfo input, optional RequestInit init), Exposed=(Window,Worker)] interface Request { readonly attribute ByteString method; readonly attribute USVString url; [SameObject] readonly attribute Headers headers; readonly attribute RequestType type; 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; [NewObject] Request clone(); }; Request implements Body; dictionary RequestInit { ByteString method; HeadersInit headers; BodyInit body; USVString referrer; ReferrerPolicy referrerPolicy; RequestMode mode; RequestCredentials credentials; RequestCache cache; RequestRedirect redirect; DOMString integrity; any window; // can only be set to null }; enum RequestType { "", "audio", "font", "image", "script", "style", "track", "video" }; enum RequestDestination { "", "document", "sharedworker", "subresource", "unknown", "worker" }; enum RequestMode { "navigate", "same-origin", "no-cors", "cors" }; enum RequestCredentials { "omit", "same-origin", "include" }; enum RequestCache { "default", "no-store", "reload", "no-cache", "force-cache", "only-if-cached" }; enum RequestRedirect { "follow", "error", "manual" };
"serviceworker
" is omitted from
RequestDestination
as it cannot be observed from JavaScript. Implementations
will still need to support it as a
destination.
A Request
object has an associated
request (a
request).
A Request
object also has an associated Headers
object which
is itself associated with request's
header list.
A Request
object also has an associated
disturbed flag which is initially unset.
A Request
object's disturbed predicate
returns true if the associated request's
body is not null and the associated
disturbed flag is set.
A Request
object's consume body
algorithm, which given a type, runs these steps:
If this Request
object is disturbed,
return a new promise rejected with a TypeError
.
Set disturbed flag.
Let p be a new promise.
Run these substeps in parallel:
Let bytes be the empty byte sequence.
If request's body is not null, set bytes to the result of reading from request's body until it returns end-of-stream.
Resolve p with the result of running the package data algorithm with bytes, type and MIME type. If that threw an exception, reject p with that exception.
Return p.
The
Request(input, init)
constructor must run these steps:
If input is a Request
object and it is
disturbed,
throw a TypeError
.
Let temporaryBody be input's
request's body
if input is a Request
object, and null otherwise.
Let request be input's
request, if input is a
Request
object, and a new request
otherwise.
Let window be "client
".
If request's window is an environment settings object and its origin is same origin with entry settings object's origin, set window to request's window.
If init's window
member is present and it is
not null, throw a TypeError
.
If init's window
member is present, set
window to "no-window
".
Set request to a new request
whose url is request's
current url,
method is request's
method,
header list is a copy of
request's header list,
unsafe-request flag is set,
client is
entry settings object,
window is window,
origin is "client
",
omit-Origin
-header flag is request's
omit-Origin
-header flag,
same-origin data-URL flag is set,
referrer is request's
referrer,
referrer policy is
request's
referrer policy,
destination is the empty string,
mode is request's
mode,
credentials mode is
request's
credentials mode,
cache mode is
request's
cache mode,
redirect mode is
request's
redirect mode, and
integrity metadata is
request's
integrity metadata.
Let fallbackMode be null.
Let fallbackCredentials be null.
Let baseURL be entry settings object's API base URL.
If input is a string, run these substeps:
Let parsedURL be the result of parsing input with baseURL.
If parsedURL is failure,
throw a TypeError
.
If parsedURL
includes credentials,
throw a TypeError
.
Set request's url to parsedURL and replace request's url list single URL with a copy of parsedURL.
Set fallbackMode to "cors
".
Set fallbackCredentials to "omit
".
If any of init's members are present, run these substeps:
Unset request's omit-Origin
-header flag.
Set request's referrer to
"client
"
Set request's referrer policy to the empty string.
If init's referrer
member is present, run these
substeps:
Let referrer be init's referrer
member.
If referrer is the empty string, set request's
referrer to "no-referrer
" and
terminate these substeps.
Let parsedReferrer be the result of parsing referrer with baseURL.
If parsedReferrer is failure,
throw a TypeError
.
If parsedReferrer's
non-relative flag is set,
scheme is
"about
", and
path contains a single string
"client
", set request's
referrer to "client
" and
terminate these substeps.
If parsedReferrer's
origin is not
same origin with origin,
throw a TypeError
.
Set request's referrer to parsedReferrer.
If init's referrerPolicy
member is present, set
request's
referrer policy to it.
Let mode be init's mode
member if it is present, and fallbackMode otherwise.
If mode is "navigate
",
throw a TypeError
.
If mode is non-null, set request's mode to mode.
Let credentials be init's
credentials
member if it is present, and
fallbackCredentials otherwise.
If credentials is non-null, set request's credentials mode to credentials.
If init's cache
member is present, set
request's cache mode to
it.
If init's redirect
member is present, set
request's redirect mode
to it.
If init's integrity
member is present, set
request's
integrity metadata to it.
If init's method
member is present, let
method be it and run these substeps:
If method is not a method or
method is a forbidden method,
throw a TypeError
.
Normalize method.
Set request's method to method.
Let r be a new Request
object associated with
request and a new Headers
object whose
guard is "request
".
Let headers be a copy of r's
Headers
object.
If init's headers
member is present, set
headers to init's headers
member.
Empty r's request's header list.
If r's request's
mode is "no-cors
", run these
substeps:
If r's request's
method is not a simple method,
throw a TypeError
.
If request's
integrity metadata is not
the empty string, throw a
TypeError
.
Fill r's
Headers
object with headers. Rethrow any exceptions.
If either init's body
member is present or
temporaryBody is non-null, and request's
method is `GET
` or
`HEAD
`, throw a
TypeError
.
If init's body
member is present, run these
substeps:
Let stream and Content-Type be the result of
extracting init's
body
member.
Set temporaryBody to stream.
If Content-Type is non-null and r's
request's
header list contains no
header named
`Content-Type
`, append
`Content-Type
`/Content-Type to r's
Headers
object. Rethrow any exception.
Set r's MIME type to the result of extracting a MIME type from r's request's header list.
If input is a Request
object and
input's request's
body is non-null, run these substeps:
Set input's disturbed flag.
Return r.
The method
attribute's getter must
return request's
method.
The url
attribute's getter must
return request's
url,
serialized with the
exclude-fragment flag set.
The headers
attribute's getter must
return the associated Headers
object.
The type
attribute's getter must return
request's
type.
The destination
attribute's
getter must return request's
destination.
The referrer
attribute's getter must
return the empty string if request's
referrer is "no-referrer
",
"about:client
" if request's
referrer is "client
", and
request's
referrer,
serialized, otherwise.
The referrerPolicy
attribute's
getter must return request's
referrer policy.
The mode
attribute's getter must
return the value corresponding to the first matching statement, switching on
request's
mode:
cors-with-forced-preflight
"
cors
"
The credentials
attribute's
getter must return request's
credentials mode.
The cache
attribute's getter must
return request's
cache mode.
The redirect
attribute's getter must
return request's
redirect mode.
The integrity
attribute's getter
must return request's
integrity metadata.
The clone()
method, when invoked, must
run these steps:
Let newRequest be a copy of request, with newRequest's body being a tee of request's body.
Let r be a new Request
object associated with
newRequest and a new Headers
object whose
guard is
context object's Headers
'
guard.
Return r.
[Constructor(optional BodyInit body, optional ResponseInit init),
Exposed=(Window,Worker)]
interface Response {
[NewObject] static Response error();
[NewObject] static Response redirect(USVString url, optional unsigned short status = 302);
readonly attribute ResponseType type;
readonly attribute USVString url;
readonly attribute unsigned short status;
readonly attribute boolean ok;
readonly attribute ByteString statusText;
[SameObject] readonly attribute Headers headers;
[SameObject] readonly attribute ReadableStream
body;
[NewObject] Response clone();
};
Response implements Body;
dictionary ResponseInit {
unsigned short status = 200;
ByteString statusText = "OK";
HeadersInit headers;
};
enum ResponseType { "basic", "cors", "default", "error", "opaque", "opaqueredirect" };
A Response
object has an associated
response (a
response).
A Response
object also has an associated Headers
object which
is itself associated with response's
header list.
A Response
object also has an associated
readable stream which is null or a
ReadableStream
object. Its initial value is null.
This might become a
ReadableByteStream
object. While the type might change, the behavior specified will
be equivalent since the hypothetical ReadableByteStream
object will have the same
members as the ReadableStream
object has today.
A Response
object is said to be locked if
the associated readable stream is not null and
it is locked.
A Response
object's disturbed predicate
returns true if the associated readable stream
is not null and it is disturbed.
A Response
object's consume body
algorithm, which given a type, runs these steps:
If this Response
object is disturbed
or locked, return a new promise rejected with a
TypeError
.
Let stream be readable stream.
If stream is null, set stream to an
empty
ReadableStream
object.
Let reader be the result of getting a reader from stream. If that threw an exception, return a new promise rejected with that exception.
Let promise be the result of reading all bytes from stream with reader.
Return the result of transforming promise by a fulfillment handler that returns the result of the package data algorithm with its first argument, type and MIME type.
The
Response(body, init)
constructor, when invoked, must run these steps:
If init's status
member is not in the range
200
to 599
, inclusive,
throw a RangeError
.
If init's statusText
member does not match the
reason-phrase token production,
throw a TypeError
.
Let r be a new Response
object, associated with a
new response and a new Headers
object
whose guard is "response
".
Set r's response's
status message to
init's statusText
member.
If init's headers
member is present, run these
substeps:
Empty r's response's header list.
Fill r's
Headers
object with init's headers
member. Rethrow any exceptions.
If body is given, run these substeps:
If init's status
member is a
null body status, throw a
TypeError
.
101
is included in
null body status due to its use elsewhere. It does not affect this step.
Let byteStream and Content-Type be the result of extracting body.
Set r's
readable stream to the result of
constructing a
ReadableStream
object with byteStream.
Rethrow any exceptions.
If Content-Type is non-null and r's
response's
header list contains no
header named
`Content-Type
`, append
`Content-Type
`/Content-Type to
r's response's
header list.
Set r's MIME type to the result of extracting a MIME type from r's response's header list.
Set r's response's HTTPS state to entry settings object's HTTPS state.
Return r.
The static error()
method, when
invoked, must return a new Response
object, associated with a new
network error and a new Headers
object whose guard is
"immutable
".
The static
redirect(url, status)
method, when invoked, must run these steps:
Let parsedURL be the result of parsing url with entry settings object's API base URL.
If parsedURL is failure,
throw a TypeError
.
If status is not a redirect status,
throw a RangeError
.
Let r be a new Response
object, associated with a
new response and a new Headers
object
whose guard is "immutable
".
Set `Location
` to
parsedURL,
serialized and
utf-8 encoded, in
r's response's
header list.
Return r.
The type
attribute's getter must return
response's
type.
The url
attribute's getter must return
the empty string if response's
url is null and
response's
url,
serialized with the
exclude-fragment flag set, otherwise.
[URL]
The status
attribute's getter must
return response's
status.
The ok
attribute's getter must
return true if response's
status is an ok status, and false otherwise.
The statusText
attribute's getter
must return response's
status message.
The headers
attribute's getter must
return the associated Headers
object.
The body
attribute's getter must return the
associated readable stream.
The clone()
method, when invoked, must
run these steps:
If this Response
object is disturbed
or locked, throw a
TypeError
.
Let r be a new Response
object associated with
newResponse and a new Headers
object whose
guard is
context object's Headers
'
guard.
If readable stream is null, Return r.
Let «out1, out2» be the result of teeing readable stream. Rethrow any exceptions.
Set readable stream to out1.
Set r's readable stream to out2.
Return r.
Headers
, Request
, and Response
objectsUnlikely to happen anytime soon due to difficulty of cloning promises and streams. See SW #313 for details.
[NoInterfaceObject, Exposed=(Window,Worker)] interface GlobalFetch { [NewObject] Promise<Response> fetch(RequestInfo input, optional RequestInit init); }; Window implements GlobalFetch; WorkerGlobalScope implements GlobalFetch;
The
fetch(input, init)
method, must run these steps:
Let p be a new promise.
Let request be the associated
request of 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.
Set request's initiator to
"fetch
".
Set request's destination to
"subresource
".
Let stream be null.
Run the following in parallel:
Fetch request.
To process response for response, run these substeps:
If response's type is
"error
", reject p with a TypeError
and terminate
these substeps.
Let responseObject be a new Response
object associated with
response and a new Headers
object whose
guard is "immutable
".
If response's body is null, resolve p with responseObject and terminate these substeps.
Let pull be an action that resumes the ongoing fetch if it is suspended.
Let cancel be an action that terminates the ongoing fetch with reason end-user abort.
Let strategy be an object. The user agent may choose any object.
strategy is used to control the queuing strategy of stream constructed below.
Set stream to the result of
constructing a
ReadableStream
object with strategy,
pull and cancel. If that threw an exception, run the following
subsubsteps and terminate these substeps:
Reject p with that exception.
Terminate the ongoing fetch with reason fatal.
Set responseObject's readable stream to stream.
Resolve p with responseObject.
To process response body for response, run these substeps:
If stream is null, terminate these substeps.
Enqueue a Uint8Array
object wrapping an ArrayBuffer
containing the result of reading
response's body into stream. If
that threw an exception, run the following subsubsteps and terminate these substeps:
Reject p with that exception.
Terminate the ongoing fetch with reason fatal.
If stream doesn't need more data, ask the user agent to suspend the ongoing fetch.
To process response end-of-file for response, close stream if stream is not null.
Return p.
The user agent may terminate an ongoing fetch with reason garbage collection 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
.
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!")) })
This section and its subsections are informative only.
For the purposes of fetching, the platform has an API layer (HTML's
img
, CSS' 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 headers, but can control
`Accept
` and have the means to constrain and disable
`Referer
` for instance.
Throughout the platform, 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]
Vary: Access-Control-Allow-Origin
Thanks to Adam Barth, Alexey Proskuryakov, Ángel González, Anssi Kostiainen, Arkadiusz Michalski, Arne Johannessen, Arthur Barstow, Axel Rauschmayer, Ben Kelly, Benjamin Hawkes-Lewis, Bert Bos, Björn Höhrmann, Boris Zbarsky, Brad Hill, Brad Porter, Bryan Smith, Caitlin Potter, Cameron McCormack, Clement Pellerin, Collin Jackson, David Håsäther, David Orchard, Domenic Denicola, Dean Jackson, Ehsan Akhgari, Eric Lawrence, Frank Ellerman, Frederick Hirsch, Gavin Carothers, Glenn Maynard, Graham Klyne, Hal Lockhart, Hallvord R. M. Steen, Henri Sivonen, Hiroshige Hayashizaki, Honza Bambas, Ian Hickson, Ilya Grigorik, Jake Archibald, James Graham, Janusz Majnert, Jeff Hodges, Jeffrey Yasskin, Jesse M. Heines, Jonas Sicking, Jonathan Kingston, Jörn Zaefferer, Julian Reschke, 송정기 (Jungkee Song), Jussi Kalliokoski, Jxck, Kenji Baheux, Lachlan Hunt, Lucas Gonze, 呂康豪 (Kang-Hao Lu), Maciej Stachowiak, Marc Silbey, Marcos Caceres, Mark Nottingham, Mark S. Miller, Martin Dürst, Matt Andrews, Matt Falkenhagen, Matt Oshry, Matt Womer, Mhano Harkness, Michael™ Smith, Mike West, Mohamed Zergaoui, Ms2ger, Nikhil Marathe, Nikunj Mehta, Odin Hørthe Omdal, Ondřej Žára, Philip Jägenstedt, R. Auburn, Ryan Sleevi, Sébastien Cevey, Sharath Udupa, Shivakumar Jagalur Matt, Simon Pieters, Srirama Chandra Sekhar Mogali, Sunava Dutta, Surya Ismail, 吉野剛史 (Takeshi Yoshino), Thomas Roessler, Tobie Langel, Tomás Aparicio, 保呂毅 (Tsuyoshi Horo), Tyler Close, Vladimir Dzhuvinov, Wayne Carr, Youenn Fablet, 平野裕 (Yutaka Hirano), and Zhenbin Xu for being awesome.
This standard is written by Anne van Kesteren (Mozilla, annevk@annevk.nl).
Per CC0, to the extent possible under law, the editor has waived all copyright and related or neighboring rights to this work.