Fetch

Living Standard — Last Updated 1 August 2014

This Version:
http://fetch.spec.whatwg.org/
Participate:
Send feedback to whatwg@whatwg.org or file a bug (open bugs)
IRC: #whatwg on Freenode
Version History:
https://github.com/whatwg/fetch/commits
Editor:
Anne van Kesteren (Mozilla) <annevk@annevk.nl>

Abstract

The Fetch standard defines requests, responses, and the process that binds them; fetching.

Table of Contents

  1. Goals
  2. 1 Conformance
  3. 2 Terminology
    1. 2.1 HTTP
      1. 2.1.1 Methods
      2. 2.1.2 Headers
      3. 2.1.3 Body
      4. 2.1.4 Requests
      5. 2.1.5 Responses
  4. 3 HTTP extensions
    1. 3.1 `Origin` header
    2. 3.2 CORS protocol
      1. 3.2.1 General
      2. 3.2.2 HTTP requests
      3. 3.2.3 HTTP responses
      4. 3.2.4 HTTP new header syntax
  5. 4 Fetching
    1. 4.1 Basic fetch
    2. 4.2 HTTP fetch
    3. 4.3 HTTP network or cache fetch
    4. 4.4 CORS preflight fetch
    5. 4.5 CORS preflight cache
    6. 4.6 CORS check
  6. 5 Fetch API
    1. 5.1 Headers class
    2. 5.2 Body stream concept
    3. 5.3 Request class
    4. 5.4 Response class
    5. 5.5 Structured cloning of Headers, FetchBodyStream, Request, and Response objects
    6. 5.6 Fetch method
  7. Background reading
    1. HTTP header layer division
    2. Atomic HTTP redirect handling
    3. Basic safe CORS protocol setup
    4. CORS protocol and HTTP caches
  8. References
  9. Acknowledgments

Goals

To unify fetching across the web platform this specification supplants a number of algorithms and specifications:

Unifying fetching provides consistent handling of:

1 Conformance

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]

2 Terminology

This specification uses terminology from the Encoding and URL Standards. [ENCODING] [URL]

A byte sequence with bytes in the range 0x00 to 0x7F is represented as a utf-8 encoded string with code points in the range U+0000 to U+007F. 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 are considered to also match their corresponding byte in the range 0x61 to 0x7A.

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, by 0x20.

2.1 HTTP

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. via data URL).

2.1.1 Methods

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]

A useful method is a method that is not a forbidden method.

2.1.2 Headers

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:

  1. Byte lowercase name.

  2. 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.

  3. 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:

  1. Byte lowercase name.

  2. 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.

  3. 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-value token production and contains no 0x0A or 0x0D bytes.

Allowing 0x0A and 0x0D bytes can lead to reparsing issues.


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

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:


To parse a header value given a name (name) and either a header or a header list (headers), run these steps:

  1. If name is not in headers, return null.

  2. If the ABNF for name allows a single header and headers contains more than one, return failure.

    That if you require different error handling, you need to extract the desired header first.

  3. If parsing all the headers named name in headers, per the ABNF for name, failed, return failure.

  4. 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:

  1. Let MIMEType be the result of parsing `Content-Type` in headers.

  2. If MIMEType is null or failure, return the empty byte sequence.

  3. Return MIMEType, byte lowercased.

2.1.3 Body

A body is a byte stream. It has an associated transmitted and length. Unless stated otherwise these are 0.

To handle content codings given codings and bytes, run these substeps:

  1. If codings are not supported, return bytes.

  2. Return the result of decoding bytes with the given codings as explained in HTTP. [HTTP]

2.1.4 Requests

The input to fetch is a request.

A request has an associated method (a method). Unless stated otherwise it is `GET`.

A request has an associated url (a URL).

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 (a JavaScript global environment).

A request has an associated skip service worker flag. Unless stated otherwise it is unset.

A request has an associated context, which is one of audio, beacon, cspreport, download, embed, eventsource, favicon, fetch, font, form, frame, hyperlink, iframe, image, imageset, import, internal, location, manifest, object, ping, plugin, prefetch, script, serviceworker, sharedworker, subresource, style, track, video, worker, xmlhttprequest, and xslt.

A request has an associated context frame type, which is one of auxiliary, top-level, nested, and none. Unless stated otherwise it is none.

Remove auxiliary? Not sure it is distinctive enough.

The following table illustrates the relationship between a request's context, its context frame type, and CSP directives:

context context frame type CSP directive Platform feature example
audio none media-src HTML's audio element
beacon none connect-src navigator.sendBeacon()
cspreport none connect-src CSP's report feature
download none HTML's a element when its download attribute is set
embed none object-src HTML's embed element
eventsource none connect-src EventSource
favicon none /favicon.ico resource
fetch none connect-src fetch()
font none font-src CSS' @font-face
form any but none form-action, potentially child-src HTML's form element
frame nested child-src HTML's frame element
hyperlink any but none potentially child-src HTML's a element
iframe nested child-src HTML's iframe element
image none img-src SVG's image element
imageset none img-src HTML's picture element
import none script-src HTML's link element when its rel attribute is set to "import"
internal any User agent actions such as refresh, back, forward; other user agent usage
location any but none potentially child-src window.location
manifest none HTML's link element when its rel attribute is set to "manifest"
object none object-src HTML's object element
ping none connect-src HTML's ping attribute
plugin none A fetch from a plugin
prefetch none HTML's link element when its rel attribute is set to "prefetch"
script none script-src HTML's script element
serviceworker none navigator.serviceWorker.register()
sharedworker none child-src SharedWorker
subresource none HTML's link element when its rel attribute is set to "subresource"
style none style-src HTML's link element when its rel attribute is set to "stylesheet"
track none media-src HTML's track element
video none media-src HTML's video element
worker none child-src Worker
xmlhttprequest none connect-src XMLHttpRequest
xslt none script-src <?xml-stylesheet>

A request has an associated origin (an origin). Unless stated otherwise it is an opaque identifier.

A request has an associated force 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 none, client, or a URL. Unless stated otherwise it is client.

A request has an associated authentication flag. Unless stated otherwise it is unset.

A request has an associated synchronous flag. Unless stated otherwise it is unset.

A request has an associated mode, which is one of 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 manual redirect flag. Unless stated otherwise, it is unset.


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's redirect count and response tainting are used as bookkeeping details by the fetch algorithm.

2.1.5 Responses

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, and opaque. 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, status, status message, header list, and a body. Unless stated otherwise, a response's url is null, status is 200, status message is `OK`, header list is an empty header list, and body is null.


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 aways an empty list, and body is always null.


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.

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 `Set-Cookie` or `Set-Cookie2`.

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 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, status is 0, status message is the empty byte sequence, header list is an empty list, and body is null.

In other words, an opaque filtered response is nearly indistinguishable from a network error. When introducing new APIs, do not use the internal response as you will leak information.

3 HTTP extensions

3.1 `Origin` 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 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]

3.2 CORS protocol

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.

3.2.1 General

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.

3.2.2 HTTP requests

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.

3.2.3 HTTP responses

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.

3.2.4 HTTP new header syntax

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

4 Fetching

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 on the networking task source.

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 on the networking task source.

To perform a fetch using request, optionally with a CORS flag, run the steps below. An ongoing fetch can be terminated with reason reason, which must be one of end-user abort, fatal, or timeout.

The CORS flag is a bookkeeping detail for handling redirects. Only use the request parameter in other standards.

  1. If request's 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]

  2. If request's referrer is not none, 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 always set request's referrer to none or have it expose less sensitive information.

  3. If request's synchronous flag is unset and fetch is not invoked recursively, run the remaining steps asynchronously.

  4. Let response be the value corresponding to the first matching statement:

    should fetching request be blocked as mixed content returns blocked [MIX]
    should fetching request be blocked as content security returns blocked [CSP]

    A network error.

    request's url's origin is request's origin and the CORS flag is unset
    request's url's scheme is "data" and request's same-origin data URL flag is set
    request's url's scheme is "about"

    The result of performing a basic fetch using request.

    request's mode is same-origin

    A network error.

    request's mode is no CORS

    Set request's response tainting to opaque.

    The result of performing a basic fetch using request.

    request's url's scheme is not one of "http" and "https"

    A network error.

    request's mode is CORS-with-forced-preflight
    request's unsafe request flag is set and either request's method is not a simple method or a header in request's header list is not a simple header

    Set request's response tainting to CORS.

    The result of performing an HTTP fetch using request with the CORS flag and CORS preflight flag set.

    Otherwise

    Set request's response tainting to CORS.

    The result of performing an HTTP fetch using request with the CORS flag set.

  5. If fetch is invoked recursively, return response.

  6. Set response's url to request's url.

  7. If should response to request be blocked as mixed content returns blocked, set response to a network error. [MIX]

  8. If response is not a network error, set response to the following filtered response with response as its internal response, depending on request's response tainting:

    basic
    basic filtered response
    CORS
    CORS filtered response
    opaque
    opaque filtered response
  9. If request's synchronous flag is set, wait for either end-of-file to have been pushed to response's body or for response to have a termination reason, and then return response.

    This terminates fetch.

  10. If request's body is non-null and request's url's scheme is "http" or "https", queue a task to process request end-of-file for request.

  11. Queue a task to process response for response.

  12. If response's body is null, run these substeps:

    1. queue a task to process response body for response.
    2. queue a task to process response end-of-file for response.

  13. Otherwise, if response's body is non-null, run these substeps:

    1. Every 50ms or whenever response's body's is pushed to, whichever is least frequent and as long as response has no termination reason and end-of-file has not been pushed, queue a task to process response body for response.

    2. Once end-of-file has been pushed to response's body or response has a termination reason, queue a task to process response end-of-file for response.

      Ideally FTP/HTTP define this in more detail and this becomes a set of simple hooks.

    Use the networking task source for these tasks.

4.1 Basic fetch

To perform a basic fetch using request, switch on request's url's scheme, and run the associated steps:

"about"

If request's url's scheme data is "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`, and body is the empty byte sequence.

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"
  1. Let blob be request's url's object.

  2. If blob is null, return a network error.

  3. Let length be blob's size attribute value.

  4. Let response be a new response.

  5. Set response's body to a new body whose length is length.

  6. Append `Content-Length`/length to response's header list.

  7. Append `Content-Type`/blob's type attribute value to response's header list.

  8. Read the blob somehow.

  9. Return response.

"data"

If request's method is `GET` and obtaining a resource from request's 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, and body is the data returned from obtaining a resource. [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.

"http"
"https"

Return the result of performing an HTTP fetch using request.

Otherwise

Return a network error.

4.2 HTTP fetch

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.

  1. Let response be null.

  2. If request's skip service worker flag is unset and request's client is not a service worker environment, set response to the result of invoking handle a fetch for request. [HTML] [SW]

  3. If response is null, run these substeps:

    1. Set request's skip service worker flag.

      There might be redirects. Alternatively, request's authentication flag is set and the CORS flag is unset.

    2. If the CORS preflight flag is set and

      then run these substeps:

      1. Let response be the result of performing a CORS preflight fetch using request.

      2. If response is a network error, return response.

    3. Set response to the result of performing an HTTP network or cache fetch using request with authentication fetch flag if set.

    4. 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.

  4. Then, switch on response's status:

    304

    For responses that are a result of a user agent generated conditional request the user agent must act as if the server gave a 200 OK response with the appropriate content. The user agent must allow a request's header list to override automatic cache validation (e.g. `If-None-Match` or `If-Modified-Since`), in which case 304 Not Modified responses must be passed through.

    301
    302
    303
    307
    308
    1. Let location be the result of parsing `Location` in response's header list.

    2. If location is null, return response.

    3. If location is failure, return a network error.

    4. Let locationURL be the result of parsing location with request's url.

    5. If locationURL is failure, return a network error.

    6. If request's redirect count is twenty, return a network error.

    7. Increase request's redirect count by one.

    8. Unset request's same-origin data URL flag.

    9. If the CORS preflight flag is set, set response's type to error and set request's manual redirect flag. This way we avoid running the substeps below.

    10. If request's manual redirect flag is unset, run these substeps:

      1. If the CORS flag is set and locationURL's origin is not request's url's origin, set request's origin to an opaque identifier.

      2. If the CORS flag is set and locationURL's username or password is non-null, return a network error.

      3. Set request's url to locationURL.

      4. Return the result of performing a fetch using request, with the CORS flag set if set.

    401
    1. If request's authentication flag is unset or the CORS flag is set, return response.

    2. Needs testing: multiple `WWW-Authenticate` headers, missing, parsing issues.

    3. If request's use URL credentials flag is unset, or the authentication fetch flag is set, run these substeps:

      1. Prompt the end user for a username and password.

      2. Set request's url's username and password to the given values.

    4. Return the result of performing an HTTP fetch using request, with the authentication fetch flag set.

    407
    1. Needs testing: multiple `Proxy-Authenticate` headers, missing, parsing issues.

    2. Prompt the end user as appropriate and store the result as appropriate as a proxy authentication entry. [HTTP]

      Remaining details surrounding proxy authentication are defined by HTTP.

    3. Return the result of performing an HTTP fetch using request.

    Otherwise

    Do nothing.

  5. If the authentication fetch flag is set, create an authentication entry for request and the given realm. [HTTPAUTH]

  6. If the CORS preflight flag is set and response is a network error, clear cache entries using request.

  7. Return response. Typically response's body is still being pushed to after returning.

4.3 HTTP network or cache fetch

To perform a HTTP network or cache fetch using request with an optional authentication fetch flag, run these steps:

The authentication fetch flag is still a bookkeeping detail.

  1. Let HTTPRequest be a copy of request, except that HTTPRequest's body is a tee of request's body.

    Headers need to be added without affecting request. Due to redirects or authentication failure, it can get reused.

  2. Append `Referer`/empty byte sequence, if HTTPRequest's referrer is none, and `Referer`/HTTPRequest's referrer, serialized and utf-8 encoded, otherwise, to HTTPRequest's header list.

  3. If HTTPRequest's force Origin header flag is set, append `Origin`/HTTPRequest's origin, serialized and utf-8 encoded, to HTTPRequest's header list.

  4. Let credentials flag be set if either HTTPRequest's credentials mode is include, or HTTPRequest's credentials mode is same-origin and the CORS flag is unset, and unset otherwise.

  5. If credentials flag is set, run these substeps:

    1. Modify HTTPRequest's header list per HTTP State Management Mechanism. [COOKIES]

    2. Let authorizationValue be null.

    3. If there's an authentication entry for HTTPRequest and either HTTPRequest's use URL credentials flag is unset or HTTPRequest's url does not include credentials, set authorizationValue to authentication entry.

    4. Otherwise, if HTTPRequest's url does include credentials and the authentication fetch flag is set, set authorizationValue to HTTPRequest's url, converted to an `Authorization` value.

    5. If authorizationValue is non-null, append `Authorization`/authorizationValue to HTTPRequest's header list.

  6. If there's a proxy authentication entry, use it as appropriate. [HTTP]

    This intentionally does not depend on HTTPRequest's credentials mode.

  7. 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` must not be included at this point. See HTTP header layer division.

  8. Handle caches.

  9. Let response be the result of making an HTTP request, using HTTPRequest, following the requirements from HTTP as appropriate, and waiting until either all the headers are transmitted or a network error was returned. If a network error was returned due to fetch being terminated with reason reason, set response's termination reason to reason. [HTTP]

    If HTTPRequest's body is non-null, run these substeps:

    1. If HTTPRequest's body's payload body length is known, set HTTPRequest's body's length to HTTPRequest's body's payload body length.

    2. queue a task every 50ms or for each byte of HTTPRequest's body transmitted, whichever is least frequent, to increase HTTPRequest's body's transmitted with the amount of payload body bytes transmitted and process request body for HTTPRequest.

      Use the networking task source.

    Run these substeps asynchronously, after the outer set of steps has returned:

    1. If response's body is non-null, set response's body's length to response's body's payload body length.

    2. Whenever one or more bytes are transmitted, let bytes be the transmitted bytes and run these subsubsteps:

      1. Increase response's body's transmitted with bytes' length.

      2. Let codings be the result of parsing `Content-Encoding` in response's header list.

      3. Set bytes to the result of handling content codings given codings and bytes.

      4. Push bytes to response's body.

    3. If at any point fetch is terminated with reason reason, set response's termination reason to reason.

    These are run asynchronously as at this point it is unclear whether response's body is relevant (response might be a redirect).

  10. Delete `Content-Encoding` from response's header list if one of the following conditions is true:

    This deals with broken Apache configurations. Ideally HTTP would define this.

    Gecko bug 1030660 looks into whether this quirk can be removed.

  11. If credentials flag is set and response's header list contains one or more headers named `Set-Cookie`, run these substeps:

    1. Wait until ownership of the storage mutex can be taken by this instance of the fetch algorithm.

    2. Take ownership of the storage mutex.

    3. Update the cookies. [COOKIES]

      This is a fingerprinting vector.

    4. Release the storage mutex so that it is once again free.

  12. Return response. Typically response's body is still being pushed to after returning.

4.4 CORS preflight fetch

To perform a CORS preflight fetch using request, run these steps:

  1. Let preflight be a copy of request.

  2. Set preflight's method to `OPTIONS`.

  3. Empty preflight's header list.

  4. Set `Access-Control-Request-Method` to request's method in preflight's header list.

  5. Let headers be the names of request's header list's headers, excluding duplicates, sorted lexicographically, and byte lowercased.

  6. Let value be the items in headers separated from each other by 0x2C 0x20.

  7. Set `Access-Control-Request-Headers` to value in preflight's header list.

  8. Set preflight's body to null.

  9. Set preflight's manual redirect flag.

  10. Set preflight's credentials mode to omit.

  11. Let response be the result of performing an HTTP fetch using preflight with the CORS flag set.

  12. If response's status is in the range 200 to 299, run these substeps:

    1. Let methods be the result of parsing `Access-Control-Allow-Methods` in response's header list.

    2. Let headerNames be the result of parsing `Access-Control-Allow-Headers` in response's header list.

    3. If either methods or headerNames is failure, return a network error.

    4. 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.

    5. If request's method is not in methods and is not a simple method, return a network error.

    6. 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.

    7. Let max-age be the result of parsing `Access-Control-Max-Age` in response's header list.

    8. If max-age is failure or null, set max-age to zero.

    9. If max-age is greater than an imposed limit on max-age, set max-age to the imposed limit.

    10. If the user agent does not provide for a cache, return response.

    11. For each method in methods for which there is a method cache match using request, set matching entry's max-age to max-age.

    12. 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:

      origin
      request's origin
      url
      request's url
      max-age
      max-age
      credentials
      False if request's credentials mode is not include, and true otherwise
      method
      method
    13. 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.

    14. 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:

      origin
      request's origin
      url
      request's url
      max-age
      max-age
      credentials
      False if request's credentials mode is not include, and true otherwise
      header name
      headerName
    15. Return response.

  13. Otherwise, return a network error.

4.5 CORS preflight cache

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 url.

There is a cache match for request if origin is request's origin, url is request's url, and either credentials is false and request's credentials mode is not include or credentials is true and request's credentials mode is include.

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.

4.6 CORS check

To perform a CORS check for a request and response, run these steps:

  1. Let origin be the result of parsing `Access-Control-Allow-Origin` in response's header list.

  2. If origin is null or failure, return failure.

    Null is not `null`.

  3. If request's credentials mode is not include and origin is `*`, return success.

  4. If request's origin, serialized and utf-8 encoded, is not origin, return failure.

  5. If request's credentials mode is not include, return success.

  6. Let credentials be the result of parsing `Access-Control-Allow-Credentials` in response's header list.

  7. 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.

  8. Return failure.

5 Fetch API

This is a work-in-progress section covering a new API that handles slightly more modes of fetching than XMLHttpRequest. The main driver behind this API is service workers, but it is applicable elsewhere too.

5.1 Headers class

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);
};

A Headers object has an associated header list (a header list).

A Headers object also has an associated guard, which is one of immutable, request, request-no-CORS, response and none (initially none).

immutable exists for service workers. [SW]

To fill a Headers object (headers) with a given object (object), run these steps:

  1. 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.

  2. Otherwise, if object is a sequence, then for each header in object, run these substeps:

    1. If header does not contain exactly two items, throw a TypeError.

    2. Append header's first item/header's second item to headers. Rethrow any exception.

  3. Otherwise, if object is an open-ended dictionary, then for each header in object, run these substeps:

    1. Set header's key to header's key, converted to ByteString. Rethrow any exception.

    2. Append header's key/header's value to headers. Rethrow any exception.

The Headers(init) constructor, when invoked, must run these steps:

  1. Let headers be a new Headers object.

  2. If init is given, fill headers with init. Rethrow any exception.

  3. Return headers.

To append a name/value (name/value) pair to a Headers object (headers), run these steps:

  1. If name is not a name or value is not a value, throw a TypeError.

  2. If guard is immutable, throw a TypeError.

  3. Otherwise, if guard is request and name is a forbidden header name, return.

  4. Otherwise, if guard is request-no-CORS and name/value is not a simple header, return.

  5. Otherwise, if guard is response and name is a forbidden response header name, return.

  6. Append name/value to header list.

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:

  1. If name is not a name, throw a TypeError.

  2. If guard is immutable, throw a TypeError.

  3. Otherwise, if guard is request and name is a forbidden header name, return.

  4. Otherwise, if guard is request-no-CORS and name/`invalid` is not a simple header, return.

  5. Otherwise, if guard is response and name is a forbidden response header name, return.

  6. Delete name from header list.

The get(name) method, when invoked, must run these steps:

  1. If name is not a name, throw a TypeError.

  2. 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:

  1. If name is not a name, throw a TypeError.

  2. 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:

  1. If name is not a name, throw a TypeError.

  2. 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:

  1. If name is not a name or value is not a value, throw a TypeError.

  2. If guard is immutable, throw a TypeError.

  3. Otherwise, if guard is request and name is a forbidden header name, return.

  4. Otherwise, if guard is request-no-CORS and name/value is not a simple header, return.

  5. Otherwise, if guard is response and name is a forbidden response header name, return.

  6. Set name/value in header list.

Symbol.iterator support is bug 26102.

5.2 Body stream concept

The interface in this section is to become a subclass of a future native JavaScript IO stream class. For now all it offers is a single method for getting all the data out of the underlying stream in a chosen representation.

typedef object JSON;
typedef (ArrayBuffer or ArrayBufferView or Blob or FormData or ScalarValueString or URLSearchParams) FetchBodyInit;

To extract a byte stream and a `Content-Type` value from object, run these steps:

  1. Let stream be an empty byte stream.

  2. Let Content-Type be an empty byte sequence.

  3. Switch on object's type:

    ArrayBuffer
    ArrayBufferView

    Push a copy of object's contents to stream.

    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.

    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.

    ScalarValueString

    Push the result of running utf-8 encode on object to stream.

    Set Content-Type to `text/plain;charset=UTF-8`.

    URLSearchParams

    Push the result of running the application/x-www-form-urlencoded serializer, with data's associated list of name-value pairs as pairs, to stream.

    Set Content-Type to `application/x-www-form-urlencoded;charset=UTF-8`.

  4. Return stream and Content-Type.

[NoInterfaceObject,
 Exposed=(Window,Worker)]
interface FetchBodyStream {
  Promise<ArrayBuffer> asArrayBuffer();
  Promise<Blob> asBlob();
  Promise<FormData> asFormData();
  Promise<JSON> asJSON();
  Promise<ScalarValueString> asText();
};

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.

A FetchBodyStream object has an associated byte stream.

A FetchBodyStream object also has an associated read flag (initially unset).

A FetchBodyStream object also has an associated MIME type (initially the empty byte sequence).

The as generic algorithm, given an object and type, runs these steps:

  1. Let p be a new promise.

  2. If object's read flag is set, reject p with a TypeError.

  3. Set object's read flag.

  4. Run these substeps asynchronously:

    1. Let stream be object's byte stream.

    2. If stream is null, set stream to an empty byte sequence.

    3. Let bytes be the result of reading from stream until it returns end-of-stream.

    4. Switch on type:

      ArrayBuffer

      Resolve p with an ArrayBuffer whose contents are bytes.

      Blob

      Resolve p with a Blob whose contents are bytes and type is object's MIME type.

      FormData

      If object's MIME type (ignoring parameters) is `multipart/form-data`, run these subsubsteps:

      1. Parse bytes, using the value of the `boundary` parameter from object's MIME type and utf-8 as encoding, per the rules set forth in Returning Values from Forms: multipart/form-data. [RFC2388]

      2. If that fails for some reason, reject p with a TypeError.

      3. Otherwise, resolve p with a new FormData object, running create an entry for each entry as the result of the parsing operation and appending it 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 object's MIME type (ignoring parameters) is `application/x-www-form-urlencoded`, run these subsubsteps:

      1. Let entries be the result of parsing bytes.

      2. If entries is failure, reject p with a TypeError.

      3. Resolve p with a new FormData object whose entries are entries.

      Otherwise, reject p with a TypeError.

      JSON

      Let JSON be 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.

      If that threw an exception, reject p with that exception.

      Otherwise, resolve p with JSON.

      text

      Resolve p with the result of running utf-8 decode on bytes.

  5. Return p.

The asArrayBuffer() method, when invoked, must return the result of running as generic with context object and ArrayBuffer.

The asBlob() method, when invoked, must return the result of running as generic with context object and Blob.

The asFormData() method, when invoked, must return the result of running as generic with context object and FormData.

The asJSON() method, when invoked, must return the result of running as generic with context object and JSON.

The asText() method, when invoked, must return the result of running as generic with context object and text.

5.3 Request class

Expose client/context members? See SW #318.

typedef (Request or ScalarValueString) RequestInfo;

[Constructor(RequestInfo input, optional RequestInit init),
 Exposed=(Window,Worker)]
interface Request {
  readonly attribute ByteString method;
  readonly attribute ScalarValueString url;
  readonly attribute Headers headers;
  readonly attribute FetchBodyStream body;

  readonly attribute DOMString referrer;
  readonly attribute RequestMode mode;
  readonly attribute RequestCredentials credentials;
};

dictionary RequestInit {
  ByteString method;
  HeadersInit headers;
  FetchBodyInit body;
  RequestMode mode;
  RequestCredentials credentials;
};

enum RequestMode { "same-origin", "no-cors", "cors" };
enum RequestCredentials { "omit", "same-origin", "include" };

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 and whose guard is request.

A Request object also has an associated FetchBodyStream object which is itself associated with request's body.

To make a restricted copy of a request request, run these steps:

  1. Let r be a new request whose url is request's url, method is request's method, header list is a copy of request's header list, body is a tee of request's body, client is entry settings object's global object, origin is entry settings object's origin, referrer is client, context is fetch, mode is request's mode, and credentials mode is request's credentials mode.

  2. Return r.


The Request(input, init) constructor must run these steps:

  1. Let request be input's associated request, if input is a Request object, and a new request otherwise.

  2. Set request to a restricted copy of itself.

  3. Let fallbackMode be null.

  4. Let fallbackCredentials be null.

  5. If input is a string, run these substeps:

    1. Let parsedURL be the result of parsing input with entry settings object's API base URL.

    2. If parsedURL is failure, throw a TypeError.

    3. Set request's url to parsedURL.

    4. Set fallbackMode to CORS.

    5. Set fallbackCredentials to omit.

  6. Let mode be init's mode member if it is present, and fallbackMode otherwise.

  7. If mode is non-null, set request's mode to mode.

  8. Let credentials be init's credentials member if it is present, and fallbackCredentials otherwise.

  9. If credentials is non-null, set request's credentials mode to credentials.

  10. If init's method member is present, let method be it and run these substeps:

    1. If method is not a useful method, throw a TypeError.

    2. Add case correction as in XMLHttpRequest? See SW #120.

    3. Set request's method to method.

  11. Let r be a new Request object associated with request, Headers object, and FetchBodyStream object.

  12. Let headers be a copy of r's Headers object.

  13. If init's headers member is present, set headers to init's headers member.

  14. Empty r's request's header list.

  15. If r's request's mode is no CORS, run these substeps:

    1. If r's request's method is not a simple method, throw a TypeError.

    2. Set r's Headers object's guard to request-no-CORS.

  16. Fill r's Headers object with headers. Rethrow any exceptions.

  17. If init's body member is present, run these substeps:

    1. Let stream and Content-Type be the result of extracting init's body member.

    2. Set r's request's body to stream.

    3. If 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.

  18. Set r's FetchBodyStream object's MIME type to the result of extracting a MIME type from r's request's header list.

  19. 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 body attribute's getter must return the associated FetchBodyStream object.

The context attribute's getter must return request's context.

The referrer attribute's getter must return the empty string if request's referrer is none, and request's referrer, serialized, otherwise.

The mode attribute's getter must return the value corresponding to the first matching statement, switching on request's mode:

same-origin
"same-origin"
no CORS
"no-cors"
CORS
CORS-with-forced-preflight
"cors"

The credentials attribute's getter must return the value corresponding to the first matching statement, switching on request's credentials mode:

omit
"omit"
same-origin
"same-origin"
include
"include"

5.4 Response class

[Constructor(optional FetchBodyInit body, optional ResponseInit init),
 Exposed=(Window,Worker)]
interface Response {
  static Response redirect(ScalarValueString url, optional unsigned short status = 302);

  readonly attribute ResponseType type;

  readonly attribute ScalarValueString url;
  readonly attribute unsigned short status;
  readonly attribute ByteString statusText;
  readonly attribute Headers headers;
  readonly attribute FetchBodyStream body;
};

dictionary ResponseInit {
  unsigned short status = 200;
  ByteString statusText = "OK";
  HeadersInit headers;
};

enum ResponseType { "basic", "cors", "default", "error", "opaque" };

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 and whose guard is response.

A Response object also has an associated FetchBodyStream object which is itself associated with response's body.

The Response(body, init) constructor, when invoked, must run these steps:

  1. If init's status member is not in the range 200 to 599, throw a RangeError.

  2. If init's statusText member does not match the Reason-Phrase token production, throw a TypeError.

  3. Let r be a new Response object, associated with a new response, Headers object, and FetchBodyStream object.

  4. Set r's response's status to init's status member.

  5. Set r's response's status message to init's statusText member.

  6. If init's headers member is present, run these substeps:

    1. Empty r's response's header list.

    2. Fill r's Headers object with init's headers member. Rethrow any exceptions.

  7. If body is given, run these substeps:

    1. Let stream and Content-Type be the result of extracting body.

    2. Set r's response's body to stream.

    3. If r's response's header list contains no header named `Content-Type`, append `Content-Type`/Content-Type to r's response's header list.

  8. Set r's FetchBodyStream object's MIME type to the result of extracting a MIME type from r's response's header list.

  9. Return r.

The static redirect(url, status) method, when invoked, must run these steps:

  1. Let parsedURL be the result of parsing url with entry settings object's API base URL.

  2. If parsedURL is failure, throw a TypeError.

  3. If status is not one of 301, 302, 303, 307, and 308, throw a RangeError.

  4. Let r be a new Response object, associated with a new response, Headers object, and FetchBodyStream object.

  5. Set r's response's status to status.

  6. Set `Location` to parsedURL, serialized and utf-8 encoded, in r's response's header list.

  7. 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 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 FetchBodyStream object.

5.5 Structured cloning of Headers, FetchBodyStream, Request, and Response objects

See SW #313.

5.6 Fetch method

[NoInterfaceObject]
interface GlobalFetch {
  Promise<Response> fetch(RequestInfo input, optional RequestInit init);
};
Window implements GlobalFetch;
WorkerGlobalScope implements GlobalFetch;

The fetch(input, init) method, must run these steps:

  1. Let p be a new promise.

  2. Let r 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.

  3. Run the following asynchronously:

    Fetch r.

    To process response for response, run these substeps:

    1. If response's type is error, reject p with a TypeError.

    2. Resolve p with new Response object associated with response.

    To process response body for response, do nothing.

    To process response end-of-file for response, do nothing.

  4. Return p.

Background reading

This section and its subsections are informative only.

HTTP header layer division

For the purposes of fetching, the platform has an API layer (HTML's img, CSS' background-image), service worker layer, and network & cache layer. `Accept` and `Accept-Language` are set at the API 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.

Atomic HTTP redirect handling

Throughout the platform, redirects (a response whose status is one of 301, 302, 303, 307, and 308) are not exposed to APIs. Exposing redirects might leak information not otherwise available through a cross-site scripting attack.

A fetch to http://example.org/auth that includes a Cookie marked HttpOnly could result in a redirect to http://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.

Basic safe CORS protocol setup

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:

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.

CORS protocol and HTTP caches

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

References

[COOKIES]
HTTP State Management Mechanism, Adam Barth. IETF.
[CORS]
(Non-normative) CORS (obsolete), Anne van Kesteren. W3C.
[CSP]
Content Security Policy, Mike West, Adam Barth and Dan Veditz. W3C.
[DATAURL]
The data URL scheme, Simon Sapin.
[ENCODING]
Encoding, Anne van Kesteren. WHATWG.
[HSTS]
HTTP Strict Transport Security, Jeff Hodges, Collin Jackson and Adam Barth. IETF.
[HTML]
HTML, Ian Hickson. WHATWG.
[HTTP]
Hypertext Transfer Protocol -- HTTP/1.1, Roy Fielding, James Gettys, Jeffrey Mogul et al.. IETF.
[HTTPAUTH]
HTTP Authentication: Basic and Digest Access Authentication, J. Franks, Phillip Hallam-Baker, J. Hostetler et al.. IETF.
[HTTPVERBSEC]
Multiple vendors' web servers enable HTTP TRACE method by default. US-CERT.
Microsoft Internet Information Server (IIS) vulnerable to cross-site scripting via HTTP TRACK method. US-CERT.
HTTP proxy default configurations allow arbitrary TCP connections. US-CERT.
[MIX]
Mixed Content, Mike West. W3C.
[ORIGIN]
(Non-normative) The Web Origin Concept, Adam Barth. IETF.
[REFERRER]
Referrer Policy, Jochen Eisinger and Mike West. W3C.
[RFC2119]
Key words for use in RFCs to Indicate Requirement Levels, Scott Bradner. IETF.
[RFC2388]
Returning Values from Forms: multipart/form-data, L. Masinter. IETF.
[SW]
Service Workers, Alex Russell and Jungkee Song. W3C.
[URL]
URL, Anne van Kesteren. WHATWG.
[XHR]
(Non-normative) XMLHttpRequest, Anne van Kesteren. WHATWG.

Acknowledgments

The editor would like to thank Adam Barth, Alexey Proskuryakov, Anssi Kostiainen, Arne Johannessen, Arthur Barstow, Ben Kelly, Benjamin Hawkes-Lewis, Bert Bos, Björn Höhrmann, Boris Zbarsky, Brad Hill, Brad Porter, Cameron McCormack, Clement Pellerin, Collin Jackson, David Håsäther, David Orchard, Domenic Denicola, Dean Jackson, Eric Lawrence, Frank Ellerman, Frederick Hirsch, Gavin Carothers, Glenn Maynard, Graham Klyne, Hal Lockhart, Hallvord R. M. Steen, Henri Sivonen, Ian Hickson, Jake Archibald, James Graham, Janusz Majnert, Jeff Hodges, Jesse M. Heines, Jonas Sicking, Julian Reschke, Jussi Kalliokoski, Lachlan Hunt, Lucas Gonze, 呂康豪 (Kang-Hao Lu), Maciej Stachowiak, Marc Silbey, Marcos Caceres, Mark Nottingham, Mark S. Miller, Martin Dürst, Matt Falkenhagen, Matt Oshry, Matt Womer, Mhano Harkness, Michael Smith, Mike West, Mohamed Zergaoui, Nikhil Marathe, Nikunj Mehta, Odin Hørthe Omdal, Ondřej Žára, Philip Jägenstedt, R. Auburn, Sharath Udupa, Simon Pieters, Sunava Dutta, Surya Ismail, Takeshi Yoshino, Thomas Roessler, 保呂毅 (Tsuyoshi Horo), Tyler Close, Vladimir Dzhuvinov, Wayne Carr, and Zhenbin Xu for being awesome.