window.fetch polyfill

OpenSSF Scorecard

The fetch() function is a Promise-based mechanism for programmatically making web requests in the browser. This project is a polyfill that implements a subset of the standard Fetch specification, enough to make fetch a viable replacement for most uses of XMLHttpRequest in traditional web applications.

Table of Contents

Read this first

  • If you believe you found a bug with how fetch behaves in your browser, please don't open an issue in this repository unless you are testing in an old version of a browser that doesn't support window.fetch natively. Make sure you read this entire readme, especially the Caveats section, as there's probably a known work-around for an issue you've found. This project is a polyfill, and since all modern browsers now implement the fetch function natively, no code from this project actually takes any effect there. See Browser support for detailed information.

  • If you have trouble making a request to another domain (a different subdomain or port number also constitutes another domain), please familiarize yourself with all the intricacies and limitations of CORS requests. Because CORS requires participation of the server by implementing specific HTTP response headers, it is often nontrivial to set up or debug. CORS is exclusively handled by the browser's internal mechanisms which this polyfill cannot influence.

  • This project doesn't work under Node.js environments. It's meant for web browsers only. You should ensure that your application doesn't try to package and run this on the server.

  • If you have an idea for a new feature of fetch, submit your feature requests to the specification's repository. We only add features and APIs that are part of the Fetch specification.

Installation

npm install whatwg-fetch --save

You will also need a Promise polyfill for older browsers. We recommend taylorhakes/promise-polyfill for its small size and Promises/A+ compatibility.

Usage

Importing

Importing will automatically polyfill window.fetch and related APIs:

import 'whatwg-fetch'

window.fetch(...)

If for some reason you need to access the polyfill implementation, it is available via exports:

import {fetch as fetchPolyfill} from 'whatwg-fetch'

window.fetch(...)   // use native browser version
fetchPolyfill(...)  // use polyfill implementation

This approach can be used to, for example, use abort functionality in browsers that implement a native but outdated version of fetch that doesn't support aborting.

For use with webpack, add this package in the entry configuration option before your application entry point:

entry: ['whatwg-fetch', ...]

HTML

fetch('/users.html')
  .then(function(response) {
    return response.text()
  }).then(function(body) {
    document.body.innerHTML = body
  })

JSON

fetch('/users.json')
  .then(function(response) {
    return response.json()
  }).then(function(json) {
    console.log('parsed json', json)
  }).catch(function(ex) {
    console.log('parsing failed', ex)
  })

Response metadata

fetch('/users.json').then(function(response) {
  console.log(response.headers.get('Content-Type'))
  console.log(response.headers.get('Date'))
  console.log(response.status)
  console.log(response.statusText)
})

Post form

var form = document.querySelector('form')

fetch('/users', {
  method: 'POST',
  body: new FormData(form)
})

Post JSON

fetch('/users', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    name: 'Hubot',
    login: 'hubot',
  })
})

File upload

var input = document.querySelector('input[type="file"]')

var data = new FormData()
data.append('file', input.files[0])
data.append('user', 'hubot')

fetch('/avatars', {
  method: 'POST',
  body: data
})

Caveats

  • The Promise returned from fetch() won't reject on HTTP error status even if the response is an HTTP 404 or 500. Instead, it will resolve normally, and it will only reject on network failure or if anything prevented the request from completing.

  • For maximum browser compatibility when it comes to sending & receiving cookies, always supply the credentials: 'same-origin' option instead of relying on the default. See Sending cookies.

  • Not all Fetch standard options are supported in this polyfill. For instance, redirect and cache directives are ignored.

  • keepalive is not supported because it would involve making a synchronous XHR, which is something this project is not willing to do. See issue #700 for more information.

Handling HTTP error statuses

To have fetch Promise reject on HTTP error statuses, i.e. on any non-2xx status, define a custom response handler:

function checkStatus(response) {
  if (response.status >= 200 && response.status < 300) {
    return response
  } else {
    var error = new Error(response.statusText)
    error.response = response
    throw error
  }
}

function parseJSON(response) {
  return response.json()
}

fetch('/users')
  .then(checkStatus)
  .then(parseJSON)
  .then(function(data) {
    console.log('request succeeded with JSON response', data)
  }).catch(function(error) {
    console.log('request failed', error)
  })

Sending cookies

For CORS requests, use credentials: 'include' to allow sending credentials to other domains:

fetch('https://example.com:1234/users', {
  credentials: 'include'
})

The default value for credentials is "same-origin".

The default for credentials wasn't always the same, though. The following versions of browsers implemented an older version of the fetch specification where the default was "omit":

  • Firefox 39-60
  • Chrome 42-67
  • Safari 10.1-11.1.2

If you target these browsers, it's advisable to always specify credentials: 'same-origin' explicitly with all fetch requests instead of relying on the default:

fetch('/users', {
  credentials: 'same-origin'
})

Note: due to limitations of XMLHttpRequest, using credentials: 'omit' is not respected for same domains in browsers where this polyfill is active. Cookies will always be sent to same domains in older browsers.

Receiving cookies

As with XMLHttpRequest, the Set-Cookie response header returned from the server is a forbidden header name and therefore can't be programmatically read with response.headers.get(). Instead, it's the browser's responsibility to handle new cookies being set (if applicable to the current URL). Unless they are HTTP-only, new cookies will be available through document.cookie.

Redirect modes

The Fetch specification defines these values for the redirect option: "follow" (the default), "error", and "manual".

Due to limitations of XMLHttpRequest, only the "follow" mode is available in browsers where this polyfill is active.

Obtaining the Response URL

Due to limitations of XMLHttpRequest, the response.url value might not be reliable after HTTP redirects on older browsers.

The solution is to configure the server to set the response HTTP header X-Request-URL to the current URL after any redirect that might have happened. It should be safe to set it unconditionally.

# Ruby on Rails controller example
response.headers['X-Request-URL'] = request.url

This server workaround is necessary if you need reliable response.url in Firefox < 32, Chrome < 37, Safari, or IE.

Aborting requests

This polyfill supports the abortable fetch API. However, aborting a fetch requires use of two additional DOM APIs: AbortController and AbortSignal. Typically, browsers that do not support fetch will also not support AbortController or AbortSignal. Consequently, you will need to include an additional polyfill for these APIs to abort fetches:

import 'yet-another-abortcontroller-polyfill'
import {fetch} from 'whatwg-fetch'

// use native browser implementation if it supports aborting
const abortableFetch = ('signal' in new Request('')) ? window.fetch : fetch

const controller = new AbortController()

abortableFetch('/avatars', {
  signal: controller.signal
}).catch(function(ex) {
  if (ex.name === 'AbortError') {
    console.log('request aborted')
  }
})

// some time later...
controller.abort()

Browser Support

  • Chrome
  • Firefox
  • Safari 6.1+
  • Internet Explorer 10+

Note: modern browsers such as Chrome, Firefox, Microsoft Edge, and Safari contain native implementations of window.fetch, therefore the code from this polyfill doesn't have any effect on those browsers. If you believe you've encountered an error with how window.fetch is implemented in any of these browsers, you should file an issue with that browser vendor instead of this project.

JakeChampion/fetch

{
"props": {
"initialPayload": {
"allShortcutsEnabled": false,
"path": "/",
"repo": {
"id": 25136308,
"defaultBranch": "main",
"name": "fetch",
"ownerLogin": "JakeChampion",
"currentUserCanPush": false,
"isFork": false,
"isEmpty": false,
"createdAt": "2014-10-13T00:26:19.000Z",
"ownerAvatar": "https://avatars.githubusercontent.com/u/1569131?v=4",
"public": true,
"private": false,
"isOrgOwned": false
},
"currentUser": null,
"refInfo": {
"name": "main",
"listCacheKey": "v0:1708910100.0",
"canEdit": false,
"refType": "branch",
"currentOid": "c1c13ff5dfb96796563ad630a5d4361a1d1c2054"
},
"tree": {
"items": [
{
"name": ".github",
"path": ".github",
"contentType": "directory"
},
{
"name": "test",
"path": "test",
"contentType": "directory"
},
{
"name": ".eslintignore",
"path": ".eslintignore",
"contentType": "file"
},
{
"name": ".eslintrc.js",
"path": ".eslintrc.js",
"contentType": "file"
},
{
"name": ".gitignore",
"path": ".gitignore",
"contentType": "file"
},
{
"name": ".npmignore",
"path": ".npmignore",
"contentType": "file"
},
{
"name": "CHANGELOG.md",
"path": "CHANGELOG.md",
"contentType": "file"
},
{
"name": "CODE_OF_CONDUCT.md",
"path": "CODE_OF_CONDUCT.md",
"contentType": "file"
},
{
"name": "CONTRIBUTING.md",
"path": "CONTRIBUTING.md",
"contentType": "file"
},
{
"name": "LICENSE",
"path": "LICENSE",
"contentType": "file"
},
{
"name": "Makefile",
"path": "Makefile",
"contentType": "file"
},
{
"name": "README.md",
"path": "README.md",
"contentType": "file"
},
{
"name": "SECURITY.md",
"path": "SECURITY.md",
"contentType": "file"
},
{
"name": "bower.json",
"path": "bower.json",
"contentType": "file"
},
{
"name": "fetch.js",
"path": "fetch.js",
"contentType": "file"
},
{
"name": "fetch.js.flow",
"path": "fetch.js.flow",
"contentType": "file"
},
{
"name": "package.json",
"path": "package.json",
"contentType": "file"
},
{
"name": "prettier.config.js",
"path": "prettier.config.js",
"contentType": "file"
},
{
"name": "rollup.config.js",
"path": "rollup.config.js",
"contentType": "file"
}
],
"templateDirectorySuggestionUrl": null,
"readme": null,
"totalCount": 19,
"showBranchInfobar": false
},
"fileTree": null,
"fileTreeProcessingTime": null,
"foldersToFetch": [],
"treeExpanded": false,
"symbolsExpanded": false,
"isOverview": true,
"overview": {
"banners": {
"shouldRecommendReadme": false,
"isPersonalRepo": false,
"showUseActionBanner": false,
"actionSlug": null,
"actionId": null,
"showProtectBranchBanner": false,
"recentlyTouchedDataChannel": null,
"publishBannersInfo": {
"dismissActionNoticePath": "/settings/dismiss-notice/publish_action_from_repo",
"releasePath": "/JakeChampion/fetch/releases/new?marketplace=true",
"showPublishActionBanner": false
},
"interactionLimitBanner": null,
"showInvitationBanner": false,
"inviterName": null
},
"codeButton": {
"contactPath": "/contact",
"isEnterprise": false,
"local": {
"protocolInfo": {
"httpAvailable": true,
"sshAvailable": null,
"httpUrl": "https://github.com/JakeChampion/fetch.git",
"showCloneWarning": null,
"sshUrl": null,
"sshCertificatesRequired": null,
"sshCertificatesAvailable": null,
"ghCliUrl": "gh repo clone JakeChampion/fetch",
"defaultProtocol": "http",
"newSshKeyUrl": "/settings/ssh/new",
"setProtocolPath": "/users/set_protocol"
},
"platformInfo": {
"cloneUrl": "https://desktop.github.com",
"showVisualStudioCloneButton": false,
"visualStudioCloneUrl": "https://windows.github.com",
"showXcodeCloneButton": false,
"xcodeCloneUrl": "https://developer.apple.com",
"zipballUrl": "/JakeChampion/fetch/archive/refs/heads/main.zip"
}
},
"newCodespacePath": "/codespaces/new?hide_repo_select=true&repo=25136308"
},
"popovers": {
"rename": null,
"renamedParentRepo": null
},
"commitCount": "714",
"overviewFiles": [
{
"displayName": "README.md",
"repoName": "fetch",
"refName": "main",
"path": "README.md",
"preferredFileType": "readme",
"tabName": "README",
"richText": "<article class=\"markdown-body entry-content container-lg\" itemprop=\"text\"><h1 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-windowfetch-polyfill\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#windowfetch-polyfill\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>window.fetch polyfill</h1>\n<p dir=\"auto\"><a href=\"https://securityscorecards.dev/viewer/?uri=github.com/JakeChampion/fetch\" rel=\"nofollow\"><img src=\"https://camo.githubusercontent.com/d600a50a3a63ed94e4175b3127d58c692c713b34df69e044c0cb33cf808dabf5/68747470733a2f2f6170692e736563757269747973636f726563617264732e6465762f70726f6a656374732f6769746875622e636f6d2f4a616b654368616d70696f6e2f66657463682f6261646765\" alt=\"OpenSSF Scorecard\" data-canonical-src=\"https://api.securityscorecards.dev/projects/github.com/JakeChampion/fetch/badge\" style=\"max-width: 100%;\"></a></p>\n<p dir=\"auto\">The <code>fetch()</code> function is a Promise-based mechanism for programmatically making\nweb requests in the browser. This project is a polyfill that implements a subset\nof the standard <a href=\"https://fetch.spec.whatwg.org\" rel=\"nofollow\">Fetch specification</a>, enough to make <code>fetch</code> a viable\nreplacement for most uses of XMLHttpRequest in traditional web applications.</p>\n<h2 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-table-of-contents\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#table-of-contents\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>Table of Contents</h2>\n<ul dir=\"auto\">\n<li><a href=\"#read-this-first\">Read this first</a></li>\n<li><a href=\"#installation\">Installation</a></li>\n<li><a href=\"#usage\">Usage</a>\n<ul dir=\"auto\">\n<li><a href=\"#importing\">Importing</a></li>\n<li><a href=\"#html\">HTML</a></li>\n<li><a href=\"#json\">JSON</a></li>\n<li><a href=\"#response-metadata\">Response metadata</a></li>\n<li><a href=\"#post-form\">Post form</a></li>\n<li><a href=\"#post-json\">Post JSON</a></li>\n<li><a href=\"#file-upload\">File upload</a></li>\n<li><a href=\"#caveats\">Caveats</a>\n<ul dir=\"auto\">\n<li><a href=\"#handling-http-error-statuses\">Handling HTTP error statuses</a></li>\n<li><a href=\"#sending-cookies\">Sending cookies</a></li>\n<li><a href=\"#receiving-cookies\">Receiving cookies</a></li>\n<li><a href=\"#redirect-modes\">Redirect modes</a></li>\n<li><a href=\"#obtaining-the-response-url\">Obtaining the Response URL</a></li>\n<li><a href=\"#aborting-requests\">Aborting requests</a></li>\n</ul>\n</li>\n</ul>\n</li>\n<li><a href=\"#browser-support\">Browser Support</a></li>\n</ul>\n<h2 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-read-this-first\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#read-this-first\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>Read this first</h2>\n<ul dir=\"auto\">\n<li>\n<p dir=\"auto\">If you believe you found a bug with how <code>fetch</code> behaves in your browser,\nplease <strong>don't open an issue in this repository</strong> unless you are testing in\nan old version of a browser that doesn't support <code>window.fetch</code> natively.\nMake sure you read this <em>entire</em> readme, especially the <a href=\"#caveats\">Caveats</a>\nsection, as there's probably a known work-around for an issue you've found.\nThis project is a <em>polyfill</em>, and since all modern browsers now implement the\n<code>fetch</code> function natively, <strong>no code from this project</strong> actually takes any\neffect there. See <a href=\"#browser-support\">Browser support</a> for detailed\ninformation.</p>\n</li>\n<li>\n<p dir=\"auto\">If you have trouble <strong>making a request to another domain</strong> (a different\nsubdomain or port number also constitutes another domain), please familiarize\nyourself with all the intricacies and limitations of <a href=\"https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS\" title=\"Cross-origin resource sharing\" rel=\"nofollow\">CORS</a> requests.\nBecause CORS requires participation of the server by implementing specific\nHTTP response headers, it is often nontrivial to set up or debug. CORS is\nexclusively handled by the browser's internal mechanisms which this polyfill\ncannot influence.</p>\n</li>\n<li>\n<p dir=\"auto\">This project <strong>doesn't work under Node.js environments</strong>. It's meant for web\nbrowsers only. You should ensure that your application doesn't try to package\nand run this on the server.</p>\n</li>\n<li>\n<p dir=\"auto\">If you have an idea for a new feature of <code>fetch</code>, <strong>submit your feature\nrequests</strong> to the <a href=\"https://github.com/whatwg/fetch/issues\">specification's repository</a>.\nWe only add features and APIs that are part of the <a href=\"https://fetch.spec.whatwg.org\" rel=\"nofollow\">Fetch specification</a>.</p>\n</li>\n</ul>\n<h2 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-installation\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#installation\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>Installation</h2>\n<div class=\"snippet-clipboard-content notranslate position-relative overflow-auto\" data-snippet-clipboard-copy-content=\"npm install whatwg-fetch --save\"><pre class=\"notranslate\"><code>npm install whatwg-fetch --save\n</code></pre></div>\n<p dir=\"auto\">You will also need a Promise polyfill for <a href=\"https://caniuse.com/promises\" rel=\"nofollow\">older browsers</a>.\nWe recommend <a href=\"https://github.com/taylorhakes/promise-polyfill\">taylorhakes/promise-polyfill</a>\nfor its small size and Promises/A+ compatibility.</p>\n<h2 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-usage\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#usage\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>Usage</h2>\n<h3 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-importing\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#importing\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>Importing</h3>\n<p dir=\"auto\">Importing will automatically polyfill <code>window.fetch</code> and related APIs:</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"import 'whatwg-fetch'\n\nwindow.fetch(...)\"><pre><span class=\"pl-k\">import</span> <span class=\"pl-s\">'whatwg-fetch'</span>\n\n<span class=\"pl-smi\">window</span><span class=\"pl-kos\">.</span><span class=\"pl-en\">fetch</span><span class=\"pl-kos\">(</span>...<span class=\"pl-kos\">)</span></pre></div>\n<p dir=\"auto\">If for some reason you need to access the polyfill implementation, it is\navailable via exports:</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"import {fetch as fetchPolyfill} from 'whatwg-fetch'\n\nwindow.fetch(...) // use native browser version\nfetchPolyfill(...) // use polyfill implementation\"><pre><span class=\"pl-k\">import</span> <span class=\"pl-kos\">{</span><span class=\"pl-s1\">fetch</span> <span class=\"pl-k\">as</span> <span class=\"pl-s1\">fetchPolyfill</span><span class=\"pl-kos\">}</span> <span class=\"pl-k\">from</span> <span class=\"pl-s\">'whatwg-fetch'</span>\n\n<span class=\"pl-smi\">window</span><span class=\"pl-kos\">.</span><span class=\"pl-en\">fetch</span><span class=\"pl-kos\">(</span>...<span class=\"pl-kos\">)</span> <span class=\"pl-c\">// use native browser version</span>\n<span class=\"pl-en\">fetchPolyfill</span><span class=\"pl-kos\">(</span>...<span class=\"pl-kos\">)</span> <span class=\"pl-c\">// use polyfill implementation</span></pre></div>\n<p dir=\"auto\">This approach can be used to, for example, use <a href=\"#aborting-requests\">abort\nfunctionality</a> in browsers that implement a native but\noutdated version of fetch that doesn't support aborting.</p>\n<p dir=\"auto\">For use with webpack, add this package in the <code>entry</code> configuration option\nbefore your application entry point:</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"entry: ['whatwg-fetch', ...]\"><pre>entry: <span class=\"pl-kos\">[</span><span class=\"pl-s\">'whatwg-fetch'</span><span class=\"pl-kos\">,</span> ...<span class=\"pl-kos\">]</span></pre></div>\n<h3 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-html\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#html\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>HTML</h3>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"fetch('/users.html')\n .then(function(response) {\n return response.text()\n }).then(function(body) {\n document.body.innerHTML = body\n })\"><pre><span class=\"pl-en\">fetch</span><span class=\"pl-kos\">(</span><span class=\"pl-s\">'/users.html'</span><span class=\"pl-kos\">)</span>\n <span class=\"pl-kos\">.</span><span class=\"pl-en\">then</span><span class=\"pl-kos\">(</span><span class=\"pl-k\">function</span><span class=\"pl-kos\">(</span><span class=\"pl-s1\">response</span><span class=\"pl-kos\">)</span> <span class=\"pl-kos\">{</span>\n <span class=\"pl-k\">return</span> <span class=\"pl-s1\">response</span><span class=\"pl-kos\">.</span><span class=\"pl-en\">text</span><span class=\"pl-kos\">(</span><span class=\"pl-kos\">)</span>\n <span class=\"pl-kos\">}</span><span class=\"pl-kos\">)</span><span class=\"pl-kos\">.</span><span class=\"pl-en\">then</span><span class=\"pl-kos\">(</span><span class=\"pl-k\">function</span><span class=\"pl-kos\">(</span><span class=\"pl-s1\">body</span><span class=\"pl-kos\">)</span> <span class=\"pl-kos\">{</span>\n <span class=\"pl-smi\">document</span><span class=\"pl-kos\">.</span><span class=\"pl-c1\">body</span><span class=\"pl-kos\">.</span><span class=\"pl-c1\">innerHTML</span> <span class=\"pl-c1\">=</span> <span class=\"pl-s1\">body</span>\n <span class=\"pl-kos\">}</span><span class=\"pl-kos\">)</span></pre></div>\n<h3 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-json\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#json\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>JSON</h3>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"fetch('/users.json')\n .then(function(response) {\n return response.json()\n }).then(function(json) {\n console.log('parsed json', json)\n }).catch(function(ex) {\n console.log('parsing failed', ex)\n })\"><pre><span class=\"pl-en\">fetch</span><span class=\"pl-kos\">(</span><span class=\"pl-s\">'/users.json'</span><span class=\"pl-kos\">)</span>\n <span class=\"pl-kos\">.</span><span class=\"pl-en\">then</span><span class=\"pl-kos\">(</span><span class=\"pl-k\">function</span><span class=\"pl-kos\">(</span><span class=\"pl-s1\">response</span><span class=\"pl-kos\">)</span> <span class=\"pl-kos\">{</span>\n <span class=\"pl-k\">return</span> <span class=\"pl-s1\">response</span><span class=\"pl-kos\">.</span><span class=\"pl-en\">json</span><span class=\"pl-kos\">(</span><span class=\"pl-kos\">)</span>\n <span class=\"pl-kos\">}</span><span class=\"pl-kos\">)</span><span class=\"pl-kos\">.</span><span class=\"pl-en\">then</span><span class=\"pl-kos\">(</span><span class=\"pl-k\">function</span><span class=\"pl-kos\">(</span><span class=\"pl-s1\">json</span><span class=\"pl-kos\">)</span> <span class=\"pl-kos\">{</span>\n <span class=\"pl-smi\">console</span><span class=\"pl-kos\">.</span><span class=\"pl-en\">log</span><span class=\"pl-kos\">(</span><span class=\"pl-s\">'parsed json'</span><span class=\"pl-kos\">,</span> <span class=\"pl-s1\">json</span><span class=\"pl-kos\">)</span>\n <span class=\"pl-kos\">}</span><span class=\"pl-kos\">)</span><span class=\"pl-kos\">.</span><span class=\"pl-en\">catch</span><span class=\"pl-kos\">(</span><span class=\"pl-k\">function</span><span class=\"pl-kos\">(</span><span class=\"pl-s1\">ex</span><span class=\"pl-kos\">)</span> <span class=\"pl-kos\">{</span>\n <span class=\"pl-smi\">console</span><span class=\"pl-kos\">.</span><span class=\"pl-en\">log</span><span class=\"pl-kos\">(</span><span class=\"pl-s\">'parsing failed'</span><span class=\"pl-kos\">,</span> <span class=\"pl-s1\">ex</span><span class=\"pl-kos\">)</span>\n <span class=\"pl-kos\">}</span><span class=\"pl-kos\">)</span></pre></div>\n<h3 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-response-metadata\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#response-metadata\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>Response metadata</h3>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"fetch('/users.json').then(function(response) {\n console.log(response.headers.get('Content-Type'))\n console.log(response.headers.get('Date'))\n console.log(response.status)\n console.log(response.statusText)\n})\"><pre><span class=\"pl-en\">fetch</span><span class=\"pl-kos\">(</span><span class=\"pl-s\">'/users.json'</span><span class=\"pl-kos\">)</span><span class=\"pl-kos\">.</span><span class=\"pl-en\">then</span><span class=\"pl-kos\">(</span><span class=\"pl-k\">function</span><span class=\"pl-kos\">(</span><span class=\"pl-s1\">response</span><span class=\"pl-kos\">)</span> <span class=\"pl-kos\">{</span>\n <span class=\"pl-smi\">console</span><span class=\"pl-kos\">.</span><span class=\"pl-en\">log</span><span class=\"pl-kos\">(</span><span class=\"pl-s1\">response</span><span class=\"pl-kos\">.</span><span class=\"pl-c1\">headers</span><span class=\"pl-kos\">.</span><span class=\"pl-en\">get</span><span class=\"pl-kos\">(</span><span class=\"pl-s\">'Content-Type'</span><span class=\"pl-kos\">)</span><span class=\"pl-kos\">)</span>\n <span class=\"pl-smi\">console</span><span class=\"pl-kos\">.</span><span class=\"pl-en\">log</span><span class=\"pl-kos\">(</span><span class=\"pl-s1\">response</span><span class=\"pl-kos\">.</span><span class=\"pl-c1\">headers</span><span class=\"pl-kos\">.</span><span class=\"pl-en\">get</span><span class=\"pl-kos\">(</span><span class=\"pl-s\">'Date'</span><span class=\"pl-kos\">)</span><span class=\"pl-kos\">)</span>\n <span class=\"pl-smi\">console</span><span class=\"pl-kos\">.</span><span class=\"pl-en\">log</span><span class=\"pl-kos\">(</span><span class=\"pl-s1\">response</span><span class=\"pl-kos\">.</span><span class=\"pl-c1\">status</span><span class=\"pl-kos\">)</span>\n <span class=\"pl-smi\">console</span><span class=\"pl-kos\">.</span><span class=\"pl-en\">log</span><span class=\"pl-kos\">(</span><span class=\"pl-s1\">response</span><span class=\"pl-kos\">.</span><span class=\"pl-c1\">statusText</span><span class=\"pl-kos\">)</span>\n<span class=\"pl-kos\">}</span><span class=\"pl-kos\">)</span></pre></div>\n<h3 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-post-form\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#post-form\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>Post form</h3>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"var form = document.querySelector('form')\n\nfetch('/users', {\n method: 'POST',\n body: new FormData(form)\n})\"><pre><span class=\"pl-k\">var</span> <span class=\"pl-s1\">form</span> <span class=\"pl-c1\">=</span> <span class=\"pl-smi\">document</span><span class=\"pl-kos\">.</span><span class=\"pl-en\">querySelector</span><span class=\"pl-kos\">(</span><span class=\"pl-s\">'form'</span><span class=\"pl-kos\">)</span>\n\n<span class=\"pl-en\">fetch</span><span class=\"pl-kos\">(</span><span class=\"pl-s\">'/users'</span><span class=\"pl-kos\">,</span> <span class=\"pl-kos\">{</span>\n <span class=\"pl-c1\">method</span>: <span class=\"pl-s\">'POST'</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-c1\">body</span>: <span class=\"pl-k\">new</span> <span class=\"pl-v\">FormData</span><span class=\"pl-kos\">(</span><span class=\"pl-s1\">form</span><span class=\"pl-kos\">)</span>\n<span class=\"pl-kos\">}</span><span class=\"pl-kos\">)</span></pre></div>\n<h3 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-post-json\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#post-json\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>Post JSON</h3>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"fetch('/users', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json'\n },\n body: JSON.stringify({\n name: 'Hubot',\n login: 'hubot',\n })\n})\"><pre><span class=\"pl-en\">fetch</span><span class=\"pl-kos\">(</span><span class=\"pl-s\">'/users'</span><span class=\"pl-kos\">,</span> <span class=\"pl-kos\">{</span>\n <span class=\"pl-c1\">method</span>: <span class=\"pl-s\">'POST'</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-c1\">headers</span>: <span class=\"pl-kos\">{</span>\n <span class=\"pl-s\">'Content-Type'</span>: <span class=\"pl-s\">'application/json'</span>\n <span class=\"pl-kos\">}</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-c1\">body</span>: <span class=\"pl-c1\">JSON</span><span class=\"pl-kos\">.</span><span class=\"pl-en\">stringify</span><span class=\"pl-kos\">(</span><span class=\"pl-kos\">{</span>\n <span class=\"pl-c1\">name</span>: <span class=\"pl-s\">'Hubot'</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-c1\">login</span>: <span class=\"pl-s\">'hubot'</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-kos\">}</span><span class=\"pl-kos\">)</span>\n<span class=\"pl-kos\">}</span><span class=\"pl-kos\">)</span></pre></div>\n<h3 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-file-upload\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#file-upload\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>File upload</h3>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"var input = document.querySelector('input[type=&quot;file&quot;]')\n\nvar data = new FormData()\ndata.append('file', input.files[0])\ndata.append('user', 'hubot')\n\nfetch('/avatars', {\n method: 'POST',\n body: data\n})\"><pre><span class=\"pl-k\">var</span> <span class=\"pl-s1\">input</span> <span class=\"pl-c1\">=</span> <span class=\"pl-smi\">document</span><span class=\"pl-kos\">.</span><span class=\"pl-en\">querySelector</span><span class=\"pl-kos\">(</span><span class=\"pl-s\">'input[type=\"file\"]'</span><span class=\"pl-kos\">)</span>\n\n<span class=\"pl-k\">var</span> <span class=\"pl-s1\">data</span> <span class=\"pl-c1\">=</span> <span class=\"pl-k\">new</span> <span class=\"pl-v\">FormData</span><span class=\"pl-kos\">(</span><span class=\"pl-kos\">)</span>\n<span class=\"pl-s1\">data</span><span class=\"pl-kos\">.</span><span class=\"pl-en\">append</span><span class=\"pl-kos\">(</span><span class=\"pl-s\">'file'</span><span class=\"pl-kos\">,</span> <span class=\"pl-s1\">input</span><span class=\"pl-kos\">.</span><span class=\"pl-c1\">files</span><span class=\"pl-kos\">[</span><span class=\"pl-c1\">0</span><span class=\"pl-kos\">]</span><span class=\"pl-kos\">)</span>\n<span class=\"pl-s1\">data</span><span class=\"pl-kos\">.</span><span class=\"pl-en\">append</span><span class=\"pl-kos\">(</span><span class=\"pl-s\">'user'</span><span class=\"pl-kos\">,</span> <span class=\"pl-s\">'hubot'</span><span class=\"pl-kos\">)</span>\n\n<span class=\"pl-en\">fetch</span><span class=\"pl-kos\">(</span><span class=\"pl-s\">'/avatars'</span><span class=\"pl-kos\">,</span> <span class=\"pl-kos\">{</span>\n <span class=\"pl-c1\">method</span>: <span class=\"pl-s\">'POST'</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-c1\">body</span>: <span class=\"pl-s1\">data</span>\n<span class=\"pl-kos\">}</span><span class=\"pl-kos\">)</span></pre></div>\n<h3 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-caveats\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#caveats\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>Caveats</h3>\n<ul dir=\"auto\">\n<li>\n<p dir=\"auto\">The Promise returned from <code>fetch()</code> <strong>won't reject on HTTP error status</strong>\neven if the response is an HTTP 404 or 500. Instead, it will resolve normally,\nand it will only reject on network failure or if anything prevented the\nrequest from completing.</p>\n</li>\n<li>\n<p dir=\"auto\">For maximum browser compatibility when it comes to sending &amp; receiving\ncookies, always supply the <code>credentials: 'same-origin'</code> option instead of\nrelying on the default. See <a href=\"#sending-cookies\">Sending cookies</a>.</p>\n</li>\n<li>\n<p dir=\"auto\">Not all Fetch standard options are supported in this polyfill. For instance,\n<a href=\"#redirect-modes\"><code>redirect</code></a> and\n<code>cache</code> directives are ignored.</p>\n</li>\n<li>\n<p dir=\"auto\"><code>keepalive</code> is not supported because it would involve making a synchronous XHR, which is something this project is not willing to do. See <a href=\"https://github.com/github/fetch/issues/700#issuecomment-484188326\" data-hovercard-type=\"issue\" data-hovercard-url=\"/JakeChampion/fetch/issues/700/hovercard\">issue #700</a> for more information.</p>\n</li>\n</ul>\n<h4 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-handling-http-error-statuses\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#handling-http-error-statuses\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>Handling HTTP error statuses</h4>\n<p dir=\"auto\">To have <code>fetch</code> Promise reject on HTTP error statuses, i.e. on any non-2xx\nstatus, define a custom response handler:</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"function checkStatus(response) {\n if (response.status &gt;= 200 &amp;&amp; response.status &lt; 300) {\n return response\n } else {\n var error = new Error(response.statusText)\n error.response = response\n throw error\n }\n}\n\nfunction parseJSON(response) {\n return response.json()\n}\n\nfetch('/users')\n .then(checkStatus)\n .then(parseJSON)\n .then(function(data) {\n console.log('request succeeded with JSON response', data)\n }).catch(function(error) {\n console.log('request failed', error)\n })\"><pre><span class=\"pl-k\">function</span> <span class=\"pl-en\">checkStatus</span><span class=\"pl-kos\">(</span><span class=\"pl-s1\">response</span><span class=\"pl-kos\">)</span> <span class=\"pl-kos\">{</span>\n <span class=\"pl-k\">if</span> <span class=\"pl-kos\">(</span><span class=\"pl-s1\">response</span><span class=\"pl-kos\">.</span><span class=\"pl-c1\">status</span> <span class=\"pl-c1\">&gt;=</span> <span class=\"pl-c1\">200</span> <span class=\"pl-c1\">&amp;&amp;</span> <span class=\"pl-s1\">response</span><span class=\"pl-kos\">.</span><span class=\"pl-c1\">status</span> <span class=\"pl-c1\">&lt;</span> <span class=\"pl-c1\">300</span><span class=\"pl-kos\">)</span> <span class=\"pl-kos\">{</span>\n <span class=\"pl-k\">return</span> <span class=\"pl-s1\">response</span>\n <span class=\"pl-kos\">}</span> <span class=\"pl-k\">else</span> <span class=\"pl-kos\">{</span>\n <span class=\"pl-k\">var</span> <span class=\"pl-s1\">error</span> <span class=\"pl-c1\">=</span> <span class=\"pl-k\">new</span> <span class=\"pl-v\">Error</span><span class=\"pl-kos\">(</span><span class=\"pl-s1\">response</span><span class=\"pl-kos\">.</span><span class=\"pl-c1\">statusText</span><span class=\"pl-kos\">)</span>\n <span class=\"pl-s1\">error</span><span class=\"pl-kos\">.</span><span class=\"pl-c1\">response</span> <span class=\"pl-c1\">=</span> <span class=\"pl-s1\">response</span>\n <span class=\"pl-k\">throw</span> <span class=\"pl-s1\">error</span>\n <span class=\"pl-kos\">}</span>\n<span class=\"pl-kos\">}</span>\n\n<span class=\"pl-k\">function</span> <span class=\"pl-en\">parseJSON</span><span class=\"pl-kos\">(</span><span class=\"pl-s1\">response</span><span class=\"pl-kos\">)</span> <span class=\"pl-kos\">{</span>\n <span class=\"pl-k\">return</span> <span class=\"pl-s1\">response</span><span class=\"pl-kos\">.</span><span class=\"pl-en\">json</span><span class=\"pl-kos\">(</span><span class=\"pl-kos\">)</span>\n<span class=\"pl-kos\">}</span>\n\n<span class=\"pl-en\">fetch</span><span class=\"pl-kos\">(</span><span class=\"pl-s\">'/users'</span><span class=\"pl-kos\">)</span>\n <span class=\"pl-kos\">.</span><span class=\"pl-en\">then</span><span class=\"pl-kos\">(</span><span class=\"pl-s1\">checkStatus</span><span class=\"pl-kos\">)</span>\n <span class=\"pl-kos\">.</span><span class=\"pl-en\">then</span><span class=\"pl-kos\">(</span><span class=\"pl-s1\">parseJSON</span><span class=\"pl-kos\">)</span>\n <span class=\"pl-kos\">.</span><span class=\"pl-en\">then</span><span class=\"pl-kos\">(</span><span class=\"pl-k\">function</span><span class=\"pl-kos\">(</span><span class=\"pl-s1\">data</span><span class=\"pl-kos\">)</span> <span class=\"pl-kos\">{</span>\n <span class=\"pl-smi\">console</span><span class=\"pl-kos\">.</span><span class=\"pl-en\">log</span><span class=\"pl-kos\">(</span><span class=\"pl-s\">'request succeeded with JSON response'</span><span class=\"pl-kos\">,</span> <span class=\"pl-s1\">data</span><span class=\"pl-kos\">)</span>\n <span class=\"pl-kos\">}</span><span class=\"pl-kos\">)</span><span class=\"pl-kos\">.</span><span class=\"pl-en\">catch</span><span class=\"pl-kos\">(</span><span class=\"pl-k\">function</span><span class=\"pl-kos\">(</span><span class=\"pl-s1\">error</span><span class=\"pl-kos\">)</span> <span class=\"pl-kos\">{</span>\n <span class=\"pl-smi\">console</span><span class=\"pl-kos\">.</span><span class=\"pl-en\">log</span><span class=\"pl-kos\">(</span><span class=\"pl-s\">'request failed'</span><span class=\"pl-kos\">,</span> <span class=\"pl-s1\">error</span><span class=\"pl-kos\">)</span>\n <span class=\"pl-kos\">}</span><span class=\"pl-kos\">)</span></pre></div>\n<h4 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-sending-cookies\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#sending-cookies\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>Sending cookies</h4>\n<p dir=\"auto\">For <a href=\"https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS\" title=\"Cross-origin resource sharing\" rel=\"nofollow\">CORS</a> requests, use <code>credentials: 'include'</code> to allow sending credentials\nto other domains:</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"fetch('https://example.com:1234/users', {\n credentials: 'include'\n})\"><pre><span class=\"pl-en\">fetch</span><span class=\"pl-kos\">(</span><span class=\"pl-s\">'https://example.com:1234/users'</span><span class=\"pl-kos\">,</span> <span class=\"pl-kos\">{</span>\n <span class=\"pl-c1\">credentials</span>: <span class=\"pl-s\">'include'</span>\n<span class=\"pl-kos\">}</span><span class=\"pl-kos\">)</span></pre></div>\n<p dir=\"auto\">The default value for <code>credentials</code> is \"same-origin\".</p>\n<p dir=\"auto\">The default for <code>credentials</code> wasn't always the same, though. The following\nversions of browsers implemented an older version of the fetch specification\nwhere the default was \"omit\":</p>\n<ul dir=\"auto\">\n<li>Firefox 39-60</li>\n<li>Chrome 42-67</li>\n<li>Safari 10.1-11.1.2</li>\n</ul>\n<p dir=\"auto\">If you target these browsers, it's advisable to always specify <code>credentials: 'same-origin'</code> explicitly with all fetch requests instead of relying on the\ndefault:</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"fetch('/users', {\n credentials: 'same-origin'\n})\"><pre><span class=\"pl-en\">fetch</span><span class=\"pl-kos\">(</span><span class=\"pl-s\">'/users'</span><span class=\"pl-kos\">,</span> <span class=\"pl-kos\">{</span>\n <span class=\"pl-c1\">credentials</span>: <span class=\"pl-s\">'same-origin'</span>\n<span class=\"pl-kos\">}</span><span class=\"pl-kos\">)</span></pre></div>\n<p dir=\"auto\">Note: due to <a href=\"https://github.com/github/fetch/pull/56#issuecomment-68835992\" data-hovercard-type=\"pull_request\" data-hovercard-url=\"/JakeChampion/fetch/pull/56/hovercard\">limitations of\nXMLHttpRequest</a>,\nusing <code>credentials: 'omit'</code> is not respected for same domains in browsers where\nthis polyfill is active. Cookies will always be sent to same domains in older\nbrowsers.</p>\n<h4 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-receiving-cookies\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#receiving-cookies\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>Receiving cookies</h4>\n<p dir=\"auto\">As with XMLHttpRequest, the <code>Set-Cookie</code> response header returned from the\nserver is a <a href=\"https://developer.mozilla.org/en-US/docs/Glossary/Forbidden_header_name\" rel=\"nofollow\">forbidden header name</a> and therefore can't be programmatically\nread with <code>response.headers.get()</code>. Instead, it's the browser's responsibility\nto handle new cookies being set (if applicable to the current URL). Unless they\nare HTTP-only, new cookies will be available through <code>document.cookie</code>.</p>\n<h4 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-redirect-modes\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#redirect-modes\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>Redirect modes</h4>\n<p dir=\"auto\">The Fetch specification defines these values for <a href=\"https://fetch.spec.whatwg.org/#concept-request-redirect-mode\" rel=\"nofollow\">the <code>redirect</code>\noption</a>: \"follow\"\n(the default), \"error\", and \"manual\".</p>\n<p dir=\"auto\">Due to limitations of XMLHttpRequest, only the \"follow\" mode is available in\nbrowsers where this polyfill is active.</p>\n<h4 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-obtaining-the-response-url\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#obtaining-the-response-url\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>Obtaining the Response URL</h4>\n<p dir=\"auto\">Due to limitations of XMLHttpRequest, the <code>response.url</code> value might not be\nreliable after HTTP redirects on older browsers.</p>\n<p dir=\"auto\">The solution is to configure the server to set the response HTTP header\n<code>X-Request-URL</code> to the current URL after any redirect that might have happened.\nIt should be safe to set it unconditionally.</p>\n<div class=\"highlight highlight-source-ruby notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"# Ruby on Rails controller example\nresponse.headers['X-Request-URL'] = request.url\"><pre><span class=\"pl-c\"># Ruby on Rails controller example</span>\n<span class=\"pl-en\">response</span><span class=\"pl-kos\">.</span><span class=\"pl-en\">headers</span><span class=\"pl-kos\">[</span><span class=\"pl-s\">'X-Request-URL'</span><span class=\"pl-kos\">]</span> <span class=\"pl-c1\">=</span> <span class=\"pl-en\">request</span><span class=\"pl-kos\">.</span><span class=\"pl-en\">url</span></pre></div>\n<p dir=\"auto\">This server workaround is necessary if you need reliable <code>response.url</code> in\nFirefox &lt; 32, Chrome &lt; 37, Safari, or IE.</p>\n<h4 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-aborting-requests\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#aborting-requests\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>Aborting requests</h4>\n<p dir=\"auto\">This polyfill supports\n<a href=\"https://developers.google.com/web/updates/2017/09/abortable-fetch\" rel=\"nofollow\">the abortable fetch API</a>.\nHowever, aborting a fetch requires use of two additional DOM APIs:\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/API/AbortController\" rel=\"nofollow\">AbortController</a> and\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal\" rel=\"nofollow\">AbortSignal</a>.\nTypically, browsers that do not support fetch will also not support\nAbortController or AbortSignal. Consequently, you will need to include\n<a href=\"https://www.npmjs.com/package/yet-another-abortcontroller-polyfill\" rel=\"nofollow\">an additional polyfill</a>\nfor these APIs to abort fetches:</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"import 'yet-another-abortcontroller-polyfill'\nimport {fetch} from 'whatwg-fetch'\n\n// use native browser implementation if it supports aborting\nconst abortableFetch = ('signal' in new Request('')) ? window.fetch : fetch\n\nconst controller = new AbortController()\n\nabortableFetch('/avatars', {\n signal: controller.signal\n}).catch(function(ex) {\n if (ex.name === 'AbortError') {\n console.log('request aborted')\n }\n})\n\n// some time later...\ncontroller.abort()\"><pre><span class=\"pl-k\">import</span> <span class=\"pl-s\">'yet-another-abortcontroller-polyfill'</span>\n<span class=\"pl-k\">import</span> <span class=\"pl-kos\">{</span><span class=\"pl-s1\">fetch</span><span class=\"pl-kos\">}</span> <span class=\"pl-k\">from</span> <span class=\"pl-s\">'whatwg-fetch'</span>\n\n<span class=\"pl-c\">// use native browser implementation if it supports aborting</span>\n<span class=\"pl-k\">const</span> <span class=\"pl-s1\">abortableFetch</span> <span class=\"pl-c1\">=</span> <span class=\"pl-kos\">(</span><span class=\"pl-s\">'signal'</span> <span class=\"pl-k\">in</span> <span class=\"pl-k\">new</span> <span class=\"pl-v\">Request</span><span class=\"pl-kos\">(</span><span class=\"pl-s\">''</span><span class=\"pl-kos\">)</span><span class=\"pl-kos\">)</span> ? <span class=\"pl-smi\">window</span><span class=\"pl-kos\">.</span><span class=\"pl-c1\">fetch</span> : <span class=\"pl-s1\">fetch</span>\n\n<span class=\"pl-k\">const</span> <span class=\"pl-s1\">controller</span> <span class=\"pl-c1\">=</span> <span class=\"pl-k\">new</span> <span class=\"pl-v\">AbortController</span><span class=\"pl-kos\">(</span><span class=\"pl-kos\">)</span>\n\n<span class=\"pl-s1\">abortableFetch</span><span class=\"pl-kos\">(</span><span class=\"pl-s\">'/avatars'</span><span class=\"pl-kos\">,</span> <span class=\"pl-kos\">{</span>\n <span class=\"pl-c1\">signal</span>: <span class=\"pl-s1\">controller</span><span class=\"pl-kos\">.</span><span class=\"pl-c1\">signal</span>\n<span class=\"pl-kos\">}</span><span class=\"pl-kos\">)</span><span class=\"pl-kos\">.</span><span class=\"pl-en\">catch</span><span class=\"pl-kos\">(</span><span class=\"pl-k\">function</span><span class=\"pl-kos\">(</span><span class=\"pl-s1\">ex</span><span class=\"pl-kos\">)</span> <span class=\"pl-kos\">{</span>\n <span class=\"pl-k\">if</span> <span class=\"pl-kos\">(</span><span class=\"pl-s1\">ex</span><span class=\"pl-kos\">.</span><span class=\"pl-c1\">name</span> <span class=\"pl-c1\">===</span> <span class=\"pl-s\">'AbortError'</span><span class=\"pl-kos\">)</span> <span class=\"pl-kos\">{</span>\n <span class=\"pl-smi\">console</span><span class=\"pl-kos\">.</span><span class=\"pl-en\">log</span><span class=\"pl-kos\">(</span><span class=\"pl-s\">'request aborted'</span><span class=\"pl-kos\">)</span>\n <span class=\"pl-kos\">}</span>\n<span class=\"pl-kos\">}</span><span class=\"pl-kos\">)</span>\n\n<span class=\"pl-c\">// some time later...</span>\n<span class=\"pl-s1\">controller</span><span class=\"pl-kos\">.</span><span class=\"pl-en\">abort</span><span class=\"pl-kos\">(</span><span class=\"pl-kos\">)</span></pre></div>\n<h2 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-browser-support\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#browser-support\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>Browser Support</h2>\n<ul dir=\"auto\">\n<li>Chrome</li>\n<li>Firefox</li>\n<li>Safari 6.1+</li>\n<li>Internet Explorer 10+</li>\n</ul>\n<p dir=\"auto\">Note: modern browsers such as Chrome, Firefox, Microsoft Edge, and Safari contain native\nimplementations of <code>window.fetch</code>, therefore the code from this polyfill doesn't\nhave any effect on those browsers. If you believe you've encountered an error\nwith how <code>window.fetch</code> is implemented in any of these browsers, you should file\nan issue with that browser vendor instead of this project.</p>\n</article>",
"loaded": true,
"timedOut": false,
"errorMessage": null,
"headerInfo": {
"toc": [
{
"level": 1,
"text": "window.fetch polyfill",
"anchor": "windowfetch-polyfill",
"htmlText": "window.fetch polyfill"
},
{
"level": 2,
"text": "Table of Contents",
"anchor": "table-of-contents",
"htmlText": "Table of Contents"
},
{
"level": 2,
"text": "Read this first",
"anchor": "read-this-first",
"htmlText": "Read this first"
},
{
"level": 2,
"text": "Installation",
"anchor": "installation",
"htmlText": "Installation"
},
{
"level": 2,
"text": "Usage",
"anchor": "usage",
"htmlText": "Usage"
},
{
"level": 3,
"text": "Importing",
"anchor": "importing",
"htmlText": "Importing"
},
{
"level": 3,
"text": "HTML",
"anchor": "html",
"htmlText": "HTML"
},
{
"level": 3,
"text": "JSON",
"anchor": "json",
"htmlText": "JSON"
},
{
"level": 3,
"text": "Response metadata",
"anchor": "response-metadata",
"htmlText": "Response metadata"
},
{
"level": 3,
"text": "Post form",
"anchor": "post-form",
"htmlText": "Post form"
},
{
"level": 3,
"text": "Post JSON",
"anchor": "post-json",
"htmlText": "Post JSON"
},
{
"level": 3,
"text": "File upload",
"anchor": "file-upload",
"htmlText": "File upload"
},
{
"level": 3,
"text": "Caveats",
"anchor": "caveats",
"htmlText": "Caveats"
},
{
"level": 4,
"text": "Handling HTTP error statuses",
"anchor": "handling-http-error-statuses",
"htmlText": "Handling HTTP error statuses"
},
{
"level": 4,
"text": "Sending cookies",
"anchor": "sending-cookies",
"htmlText": "Sending cookies"
},
{
"level": 4,
"text": "Receiving cookies",
"anchor": "receiving-cookies",
"htmlText": "Receiving cookies"
},
{
"level": 4,
"text": "Redirect modes",
"anchor": "redirect-modes",
"htmlText": "Redirect modes"
},
{
"level": 4,
"text": "Obtaining the Response URL",
"anchor": "obtaining-the-response-url",
"htmlText": "Obtaining the Response URL"
},
{
"level": 4,
"text": "Aborting requests",
"anchor": "aborting-requests",
"htmlText": "Aborting requests"
},
{
"level": 2,
"text": "Browser Support",
"anchor": "browser-support",
"htmlText": "Browser Support"
}
],
"siteNavLoginPath": "/login?return_to=https%3A%2F%2Fgithub.com%2FJakeChampion%2Ffetch"
}
},
{
"displayName": "CODE_OF_CONDUCT.md",
"repoName": "fetch",
"refName": "main",
"path": "CODE_OF_CONDUCT.md",
"preferredFileType": "code_of_conduct",
"tabName": "Code of conduct",
"richText": null,
"loaded": false,
"timedOut": false,
"errorMessage": null,
"headerInfo": {
"toc": null,
"siteNavLoginPath": "/login?return_to=https%3A%2F%2Fgithub.com%2FJakeChampion%2Ffetch"
}
},
{
"displayName": "LICENSE",
"repoName": "fetch",
"refName": "main",
"path": "LICENSE",
"preferredFileType": "license",
"tabName": "MIT",
"richText": null,
"loaded": false,
"timedOut": false,
"errorMessage": null,
"headerInfo": {
"toc": null,
"siteNavLoginPath": "/login?return_to=https%3A%2F%2Fgithub.com%2FJakeChampion%2Ffetch"
}
},
{
"displayName": "SECURITY.md",
"repoName": "fetch",
"refName": "main",
"path": "SECURITY.md",
"preferredFileType": "security",
"tabName": "Security",
"richText": null,
"loaded": false,
"timedOut": false,
"errorMessage": null,
"headerInfo": {
"toc": null,
"siteNavLoginPath": "/login?return_to=https%3A%2F%2Fgithub.com%2FJakeChampion%2Ffetch"
}
}
],
"overviewFilesProcessingTime": 27.871122000000003
}
},
"appPayload": {
"helpUrl": "https://docs.github.com",
"findFileWorkerPath": "/assets-cdn/worker/find-file-worker-32bb159cc57c.js",
"findInFileWorkerPath": "/assets-cdn/worker/find-in-file-worker-c6704d501c10.js",
"githubDevUrl": null,
"enabled_features": {
"code_nav_ui_events": false,
"copilot_conversational_ux": false,
"copilot_conversational_ux_embedding_update": false,
"copilot_popover_file_editor_header": false,
"copilot_smell_icebreaker_ux": true,
"copilot_workspace": false,
"codeview_firefox_inert": true
}
}
}
}
{
"accept-ranges": "bytes",
"cache-control": "max-age=0, private, must-revalidate",
"content-encoding": "gzip",
"content-security-policy": "default-src 'none'; base-uri 'self'; child-src github.com/assets-cdn/worker/ gist.github.com/assets-cdn/worker/; connect-src 'self' uploads.github.com www.githubstatus.com collector.github.com raw.githubusercontent.com api.github.com github-cloud.s3.amazonaws.com github-production-repository-file-5c1aeb.s3.amazonaws.com github-production-upload-manifest-file-7fdce7.s3.amazonaws.com github-production-user-asset-6210df.s3.amazonaws.com api.githubcopilot.com objects-origin.githubusercontent.com *.actions.githubusercontent.com wss://*.actions.githubusercontent.com productionresultssa0.blob.core.windows.net/ productionresultssa1.blob.core.windows.net/ productionresultssa2.blob.core.windows.net/ productionresultssa3.blob.core.windows.net/ productionresultssa4.blob.core.windows.net/ productionresultssa5.blob.core.windows.net/ productionresultssa6.blob.core.windows.net/ productionresultssa7.blob.core.windows.net/ productionresultssa8.blob.core.windows.net/ productionresultssa9.blob.core.windows.net/ productionresultssa10.blob.core.windows.net/ productionresultssa11.blob.core.windows.net/ productionresultssa12.blob.core.windows.net/ productionresultssa13.blob.core.windows.net/ productionresultssa14.blob.core.windows.net/ productionresultssa15.blob.core.windows.net/ productionresultssa16.blob.core.windows.net/ productionresultssa17.blob.core.windows.net/ productionresultssa18.blob.core.windows.net/ productionresultssa19.blob.core.windows.net/ github-production-repository-image-32fea6.s3.amazonaws.com github-production-release-asset-2e65be.s3.amazonaws.com insights.github.com wss://alive.github.com; font-src github.githubassets.com; form-action 'self' github.com gist.github.com objects-origin.githubusercontent.com; frame-ancestors 'none'; frame-src viewscreen.githubusercontent.com notebooks.githubusercontent.com; img-src 'self' data: github.githubassets.com media.githubusercontent.com camo.githubusercontent.com identicons.github.com avatars.githubusercontent.com github-cloud.s3.amazonaws.com objects.githubusercontent.com secured-user-images.githubusercontent.com/ user-images.githubusercontent.com/ private-user-images.githubusercontent.com opengraph.githubassets.com github-production-user-asset-6210df.s3.amazonaws.com customer-stories-feed.github.com spotlights-feed.github.com objects-origin.githubusercontent.com *.githubusercontent.com; manifest-src 'self'; media-src github.com user-images.githubusercontent.com/ secured-user-images.githubusercontent.com/ private-user-images.githubusercontent.com github-production-user-asset-6210df.s3.amazonaws.com gist.github.com; script-src github.githubassets.com; style-src 'unsafe-inline' github.githubassets.com; upgrade-insecure-requests; worker-src github.com/assets-cdn/worker/ gist.github.com/assets-cdn/worker/",
"content-type": "text/html; charset=utf-8",
"date": "Mon, 26 Feb 2024 11:14:57 GMT",
"etag": "f2bf2f264ad3df7320d233518fb92331",
"referrer-policy": "no-referrer-when-downgrade",
"server": "GitHub.com",
"set-cookie": "logged_in=no; Path=/; Domain=github.com; Expires=Wed, 26 Feb 2025 11:14:56 GMT; HttpOnly; Secure; SameSite=Lax",
"strict-transport-security": "max-age=31536000; includeSubdomains; preload",
"transfer-encoding": "chunked",
"vary": "X-PJAX, X-PJAX-Container, Turbo-Visit, Turbo-Frame, Accept-Encoding, Accept, X-Requested-With",
"x-content-type-options": "nosniff",
"x-frame-options": "deny",
"x-github-request-id": "8926:9F97:1BC79BB:277D16F:65DC72B0",
"x-xss-protection": "0"
}