{"id":13393667,"url":"https://github.com/umijs/umi-request","last_synced_at":"2025-05-14T05:11:28.126Z","repository":{"id":37733937,"uuid":"160780204","full_name":"umijs/umi-request","owner":"umijs","description":"A request tool based on fetch.","archived":false,"fork":false,"pushed_at":"2023-05-08T06:35:49.000Z","size":261,"stargazers_count":2221,"open_issues_count":136,"forks_count":335,"subscribers_count":49,"default_branch":"master","last_synced_at":"2025-05-12T11:07:09.571Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/umijs.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.MD","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2018-12-07T06:19:17.000Z","updated_at":"2025-04-27T08:06:38.000Z","dependencies_parsed_at":"2022-07-12T15:18:07.700Z","dependency_job_id":"a5de2ddb-3f34-4760-89d8-198cd91e8582","html_url":"https://github.com/umijs/umi-request","commit_stats":{"total_commits":114,"total_committers":30,"mean_commits":3.8,"dds":0.6052631578947368,"last_synced_commit":"50197be3c854f7480713d407f16209adc1134aa9"},"previous_names":[],"tags_count":31,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/umijs%2Fumi-request","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/umijs%2Fumi-request/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/umijs%2Fumi-request/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/umijs%2Fumi-request/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/umijs","download_url":"https://codeload.github.com/umijs/umi-request/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254076850,"owners_count":22010611,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-07-30T17:00:58.374Z","updated_at":"2025-05-14T05:11:23.106Z","avatar_url":"https://github.com/umijs.png","language":"JavaScript","funding_links":[],"categories":["JavaScript","目录"],"sub_categories":["\u003ca id=\"other\"\u003e其他\u003c/a\u003e"],"readme":"English | [简体中文](./README_zh-CN.md)\n\n# umi-request\n\nThe network request library, based on fetch encapsulation, combines the features of fetch and axios to provide developers with a unified api call method, simplifying usage, and providing common functions such as caching, timeout, character encoding processing, and error handling.\n\n[![NPM version](https://img.shields.io/npm/v/umi-request.svg?style=flat)](https://npmjs.org/package/umi-request)\n[![Build Status](https://img.shields.io/travis/umijs/umi-request.svg?style=flat)](https://travis-ci.org/umijs/umi-request)\n[![NPM downloads](http://img.shields.io/npm/dm/umi-request.svg?style=flat)](https://npmjs.org/package/umi-request)\n\n---\n\n## Supported features\n\n- url parameter is automatically serialized\n- post data submission method is simplified\n- response return processing simplification\n- api timeout support\n- api request cache support\n- support for processing gbk\n- request and response interceptor support like axios\n- unified error handling\n- middleware support\n- cancel request support like axios\n- make http request from node.js\n\n## umi-request vs fetch vs axios\n\n| Features             | umi-request            | fetch                  | axios          |\n| :------------------- | :--------------------- | :--------------------- | :------------- |\n| implementation       | Browser native support | Browser native support | XMLHttpRequest |\n| size                 | 9k                     | 4k (polyfill)          | 14k            |\n| query simplification | ✅                      | ❌                      | ✅              |\n| post simplification  | ✅                      | ❌                      | ❌              |\n| timeout              | ✅                      | ❌                      | ✅              |\n| cache                | ✅                      | ❌                      | ❌              |\n| error Check          | ✅                      | ❌                      | ❌              |\n| error Handling       | ✅                      | ❌                      | ✅              |\n| interceptor          | ✅                      | ❌                      | ✅              |\n| prefix               | ✅                      | ❌                      | ❌              |\n| suffix               | ✅                      | ❌                      | ❌              |\n| processing gbk       | ✅                      | ❌                      | ❌              |\n| middleware           | ✅                      | ❌                      | ❌              |\n| cancel request       | ✅                      | ❌                      | ✅              |\n\nFor more discussion, refer to [Traditional Ajax is dead, Fetch eternal life](https://github.com/camsong/blog/issues/2) If you have good suggestions and needs, please mention [issue](https://github.com/umijs/umi/issues)\n\n## TODO Welcome pr\n\n- [x] Test case coverage 85%+\n- [x] write a document\n- [x] CI integration\n- [x] release configuration\n- [x] typescript\n\n## Installation\n\n```\nnpm install --save umi-request\n```\n\n## Example\n\nPerforming a `GET` request\n\n```javascript\nimport request from 'umi-request';\n\nrequest\n  .get('/api/v1/xxx?id=1')\n  .then(function(response) {\n    console.log(response);\n  })\n  .catch(function(error) {\n    console.log(error);\n  });\n\n// use options.params\nrequest\n  .get('/api/v1/xxx', {\n    params: {\n      id: 1,\n    },\n  })\n  .then(function(response) {\n    console.log(response);\n  })\n  .catch(function(error) {\n    console.log(error);\n  });\n```\n\nPerforming a `POST` request\n\n```javascript\nrequest\n  .post('/api/v1/user', {\n    data: {\n      name: 'Mike',\n    },\n  })\n  .then(function(response) {\n    console.log(response);\n  })\n  .catch(function(error) {\n    console.log(error);\n  });\n```\n\n## umi-request API\n\nRequests can be made by passing relevant options to `umi-request`\n\n**umi-request(url[, options])**\n\n```javascript\nimport request from 'umi-request';\n\nrequest('/api/v1/xxx', {\n  method: 'get',\n  params: { id: 1 },\n})\n  .then(function(response) {\n    console.log(response);\n  })\n  .catch(function(error) {\n    console.log(error);\n  });\n\nrequest('/api/v1/user', {\n  method: 'post',\n  data: {\n    name: 'Mike',\n  },\n})\n  .then(function(response) {\n    console.log(response);\n  })\n  .catch(function(error) {\n    console.log(error);\n  });\n```\n\n## Request method aliases\n\nFor convenience umi-request have been provided for all supported methods.\n\n**request.get(url[, options])**\n\n**request.post(url[, options])**\n\n**request.delete(url[, options])**\n\n**request.put(url[, options])**\n\n**request.patch(url[, options])**\n\n**request.head(url[, options])**\n\n**request.options(url[, options])**\n\n## Creating an instance\n\nYou can use `extend({[options]})` to create a new instance of umi-request.\n\n**extend([options])**\n\n```javascript\nimport { extend } from 'umi-request';\n\nconst request = extend({\n  prefix: '/api/v1',\n  timeout: 1000,\n  headers: {\n    'Content-Type': 'multipart/form-data',\n  },\n});\n\nrequest\n  .get('/user')\n  .then(function(response) {\n    console.log(response);\n  })\n  .catch(function(error) {\n    console.log(error);\n  });\n```\n\nCreate an instance of umi-request in NodeJS enviroment\n\n```javascript\nconst umi = require('umi-request');\nconst extendRequest = umi.extend({ timeout: 10000 });\n\nextendRequest('/api/user')\n  .then(res =\u003e {\n    console.log(res);\n  })\n  .catch(err =\u003e {\n    console.log(err);\n  });\n```\n\nThe available instance methods are list below. The specified options will be merge with the instance options.\n\n**request.get(url[, options])**\n\n**request.post(url[, options])**\n\n**request.delete(url[, options])**\n\n**request.put(url[, options])**\n\n**request.patch(url[, options])**\n\n**request.head(url[, options])**\n\n**request.options(url[, options])**\n\nMore umi-request cases can see [antd-pro](https://github.com/umijs/ant-design-pro/blob/master/src/utils/request.js)\n\n## request options\n\n| Parameter           | Description                                                      | Type                      | Optional Value                    | Default                    |\n| :------------------ | :--------------------------------------------------------------- | :------------------------ | :-------------------------------- | :------------------------- |\n| method              | request method                                                   | string                    | get , post , put ...              | get                        |\n| params              | url request parameters                                           | object or URLSearchParams | --                                | --                         |\n| data                | Submitted data                                                   | any                       | --                                | --                         |\n| headers             | fetch original parameters                                        | object                    | --                                | {}                         |\n| timeout             | timeout, default millisecond, write with caution                 | number                    | --                                |\n| timeoutMessage      | customize timeout error message, please config `timeout` first   | string                    | --                                | --                         |\n| prefix              | prefix, generally used to override the uniform settings prefix   | string                    | --                                | --                         |\n| suffix              | suffix, such as some scenes api need to be unified .json         | string                    | --                                |\n| credentials         | fetch request with cookies                                       | string                    | --                                | credentials: 'same-origin' |\n| useCache            | Whether to use caching (only support browser environment)        | boolean                   | --                                | false                      |\n| validateCache       | cache strategy function                                          | (url, options) =\u003e boolean | --                                | only get request to cache  |\n| ttl                 | Cache duration, 0 is not expired                                 | number                    | --                                | 60000                      |\n| maxCache            | Maximum number of caches                                         | number                    | --                                | 0(Infinity)                |\n| requestType         | post request data type                                           | string                    | json , form                       | json                       |\n| parseResponse       | response processing simplification                               | boolean                   | --                                | true                       |\n| charset             | character set                                                    | string                    | utf8 , gbk                        | utf8                       |\n| responseType        | How to parse the returned data                                   | string                    | json , text , blob , formData ... | json , text                |\n| throwErrIfParseFail | throw error when JSON parse fail and responseType is 'json'      | boolean                   | --                                | false                      |\n| getResponse         | Whether to get the source response, the result will wrap a layer | boolean                   | --                                | fasle                      |\n| errorHandler        | exception handling, or override unified exception handling       | function(error)           | --                                |\n| cancelToken         | Token to cancel request                                          | CancelToken.token         | --                                | --                         |\n\nThe other parameters of fetch are valid. See [fetch documentation](https://github.github.io/fetch/)\n\n## extend options Initialize default parameters, support all of the above\n\n| Parameter | Description            | Type   | Optional Value       | Default |\n| :-------- | :--------------------- | :----- | :------------------- | :------ |\n| method    | request method         | string | get , post , put ... | get     |\n| params    | url request parameters | object | --                   | --      |\n| data      | Submitted data         | any    | --                   | --      |\n| ...       |\n\n```javascript\n{\n  // 'method' is the request method to be used when making the request\n  method: 'get', // default\n\n  // 'params' are the URL parameters to be sent with request\n  // Must be a plain object or a URLSearchParams object\n  params: { id: 1 },\n\n  // 'paramSerializer' is a function in charge of serializing 'params'. ( be aware of 'params' was merged by extends's 'params' and request's 'params' and URLSearchParams will be transform to plain object. )\n  paramsSerializer: function (params) {\n    return Qs.stringify(params, { arrayFormat: 'brackets' })\n  },\n\n  // 'data' 作为请求主体被发送的数据\n  // 适用于这些请求方法 'PUT', 'POST', 和 'PATCH'\n  // 必须是以下类型之一：\n  // - string, plain object, ArrayBuffer, ArrayBufferView, URLSearchParams\n  // - 浏览器专属：FormData, File, Blob\n  // - Node 专属： Stream\n\n  // 'data' is the data to be sent as the request body\n  // Only applicable for request methods 'PUT', 'POST', and 'PATCH'\n  // Must be of one of the following types:\n  // 1. string, plain object, ArrayBuffer, ArrayBufferView, URLSearchParams\n  // 2. Browser only: FormData, File, Blob\n  // 3. Node only: Stream\n  data: { name: 'Mike' },\n\n  // 'headers' are custom headers to be sent\n  headers: { 'Content-Type': 'multipart/form-data' },\n\n  // 'timeout' specifies the number of milliseconds before the request times out.\n  // If the request takes longer than 'timeout', request will be aborted and throw RequestError.\n  timeout: 1000,\n\n  // ’prefix‘ used to set URL's prefix\n  // ( e.g. request('/user/save', { prefix: '/api/v1' }) =\u003e request('/api/v1/user/save') )\n  prefix: '',\n\n  // ’suffix‘ used to set URL's suffix\n  // ( e.g. request('/api/v1/user/save', { suffix: '.json'}) =\u003e request('/api/v1/user/save.json') )\n  suffix: '',\n\n  // 'credentials' indicates whether the user agent should send cookies from the other domain in the case of cross-origin requests.\n  // omit: Never send or receive cookies.\n  // same-origin: Send user credentials (cookies, basic http auth, etc..) if the URL is on the same origin as the calling script. This is the default value.\n  // include: Always send user credentials (cookies, basic http auth, etc..), even for cross-origin calls.\n  credentials: 'same-origin', // default\n\n  // ’useCache‘ The GET request would be cache in ttl milliseconds when 'useCache' is true.\n  // The cache key would be 'url + params + method'.\n  useCache: false, // default\n\n  // 'ttl' cache duration（milliseconds），0 is infinity\n  ttl: 60000,\n\n  // 'maxCache' are the max number of requests to be cached, 0 means infinity.\n  maxCache: 0,\n\n  // According to http protocal, request of GET used to get data from server, it's necessary to cache response data when server data update not frequently. We provide 'validateCache'\n  // for some cases that need to cache data with other method reqeust.\n  validateCache: (url, options) =\u003e { return options.method.toLowerCase() === 'get' },\n\n\n  // 'requestType' umi-request will add headers and body according to the 'requestType' when the type of data is object or array.\n  // 1. requestType === 'json' :(default )\n  // options.headers = {\n  //   Accept: 'application/json',\n  //   'Content-Type': 'application/json;charset=UTF-8',\n  //   ...options.headers,\n  // }\n  // options.body = JSON.stringify(data)\n  //\n  // 2. requestType === 'form':\n  // options.headers = {\n  //   Accept: 'application/json',\n  //   'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',\n  //   ...options.headers,\n  // };\n  // options.body = query-string.stringify(data);\n  //\n  // 3. other requestType\n  // options.headers = {\n  //   Accept: 'application/json',\n  //   ...options.headers,\n  // };\n  // options.body = data;\n  requestType: 'json', // default\n\n  // 'parseResponse' whether processing response\n  parseResponse: true, // default\n\n  // 'charset' This parameter can be used when the server returns gbk to avoid garbled characters.(parseResponse should set to true)\n  charset: 'gbk',\n\n  // 'responseType': how to processing response.(parseResponse should be true)\n  // The default value is 'json', would processing response by Response.text().then( d =\u003e JSON.parse(d) )\n  // Other responseType (text, blob, arrayBuffer, formData), would processing response by Response[responseType]()\n  responseType: 'json', // default\n\n  // 'throwErrIfParseFail': whether throw error or not when JSON parse data fail and responseType is 'json'.\n  throwErrIfParseFail: false, // default\n\n  // 'getResponse': if you need the origin Response, set true and will return { data, response }.\n  getResponse: false,// default\n\n  // 'errorHandler' error handle entry.\n  errorHandler: function(error) { /* 异常处理 */ },\n\n  // 'cancelToken' the token of cancel request.\n  cancelToken: null,\n}\n```\n\n### Extend Options\n\nSometimes we need to update options after **extend** a request instance, umi-request provide **extendOptions** for users to update options:\n\n```javascript\nconst request = extend({ timeout: 1000, params: { a: '1' } });\n// default options is: { timeout: 1000, params: { a: '1' }}\n\nrequest.extendOptions({ timeout: 3000, params: { b: '2' } });\n// after extendOptions: { timeout: 3000, params: { a: '1', b: '2' }}\n```\n\n## Response Schema\n\nThe response for a request contains the following information.\n\n```javascript\n{\n  // 'data' is the response that was provided by the server\n  data: {},\n\n  // 'status' is the HTTP status code from the server response\n  status: 200,\n\n  // 'statusText' is the HTTP status message from the server response\n  statusText: 'OK',\n\n  // 'headers' the headers that the server responded with\n  // All header names are lower cased\n  headers: {},\n}\n```\n\nWhen options.getResponse === false, the response schema would be 'data'\n\n```javascript\nrequest.get('/api/v1/xxx', { getResponse: false }).then(function(data) {\n  console.log(data);\n});\n```\n\nWhen options.getResponse === true ，the response schema would be { data, response }\n\n```javascript\nrequest.get('/api/v1/xxx', { getResponse: true }).then(function({ data, response }) {\n  console.log(data);\n  console.log(response.status);\n  console.log(response.statusText);\n  console.log(response.headers);\n});\n```\n\nYou can get Response from `error` object in errorHandler or request.catch.\n\n## Error handling\n\n```javascript\nimport request, { extend } from 'umi-request';\n\nconst errorHandler = function(error) {\n  const codeMap = {\n    '021': 'An error has occurred',\n    '022': 'It’s a big mistake,',\n    // ....\n  };\n  if (error.response) {\n    // The request was made and the server responded with a status code\n    // that falls out of the range of 2xx\n    console.log(error.response.status);\n    console.log(error.response.headers);\n    console.log(error.data);\n    console.log(error.request);\n    console.log(codeMap[error.data.status]);\n  } else {\n    // The request was made but no response was received or error occurs when setting up the request.\n    console.log(error.message);\n  }\n\n  throw error; // If throw. The error will continue to be thrown.\n\n  // return {some: 'data'}; If return, return the value as a return. If you don't write it is equivalent to return undefined, you can judge whether the response has a value when processing the result.\n  // return {some: 'data'};\n};\n\n// 1. Unified processing\nconst extendRequest = extend({ errorHandler });\n\n// 2. Separate special treatment\n// If unified processing is configured, but an api needs special handling. When requested, the errorHandler is passed as a parameter.\nrequest('/api/v1/xxx', { errorHandler });\n\n// 3. not configure errorHandler, the response will be directly treated as promise, and it will be caught.\nrequest('/api/v1/xxx')\n  .then(function(response) {\n    console.log(response);\n  })\n  .catch(function(error) {\n    return errorHandler(error);\n  });\n```\n\n## Middleware\n\nExpressive HTTP middleware framework for node.js. For development to enhance before and after request. Support create instance, global, core middlewares.\n\n**Instance Middleware (default)** request.use(fn) Different instances's instance middleware are independence.\n**Global Middleware** request.use(fn, { global: true }) Different instances share global middlewares.\n**Core Middleware** request.use(fn, { core: true }) Used to expand request core.\n\nrequest.use(fn[, options])\n\n### params\n\nfn params\n\n- ctx(Object)：context, content request and response\n- next(Function)：function to call the next middleware\n\noptions params\n\n- global(boolean): whether global， higher priority than core\n- core(boolean): whether core\n\n### example\n\n1. same type of middlewares\n\n```javascript\nimport request, { extend } from 'umi-request';\nrequest.use(async (ctx, next) =\u003e {\n  console.log('a1');\n  await next();\n  console.log('a2');\n});\nrequest.use(async (ctx, next) =\u003e {\n  console.log('b1');\n  await next();\n  console.log('b2');\n});\n\nconst data = await request('/api/v1/a');\n```\n\norder of middlewares be called:\n\n```shell\na1 -\u003e b1 -\u003e response -\u003e b2 -\u003e a2\n```\n\n2. Different type of middlewares\n\n```javascript\nrequest.use(async (ctx, next) =\u003e {\n  console.log('instanceA1');\n  await next();\n  console.log('instanceA2');\n});\nrequest.use(async (ctx, next) =\u003e {\n  console.log('instanceB1');\n  await next();\n  console.log('instanceB2');\n});\nrequest.use(\n  async (ctx, next) =\u003e {\n    console.log('globalA1');\n    await next();\n    console.log('globalA2');\n  },\n  { global: true }\n);\nrequest.use(\n  async (ctx, next) =\u003e {\n    console.log('coreA1');\n    await next();\n    console.log('coreA2');\n  },\n  { core: true }\n);\n```\n\norder of middlewares be called:\n\n```shell\ninstanceA1 -\u003e instanceB1 -\u003e globalA1 -\u003e coreA1 -\u003e coreA2 -\u003e globalA2 -\u003e instanceB2 -\u003e instanceA2\n```\n\n3. Enhance request\n\n```javascript\nrequest.use(async (ctx, next) =\u003e {\n  const { req } = ctx;\n  const { url, options } = req;\n\n  if (url.indexOf('/api') !== 0) {\n    ctx.req.url = `/api/v1/${url}`;\n  }\n  ctx.req.options = {\n    ...options,\n    foo: 'foo',\n  };\n\n  await next();\n\n  const { res } = ctx;\n  const { success = false } = res;\n  if (!success) {\n    // ...\n  }\n});\n```\n\n4. Use core middleware to expand request core.\n\n```javascript\nrequest.use(\n  async (ctx, next) =\u003e {\n    const { req } = ctx;\n    const { url, options } = req;\n    const { __umiRequestCoreType__ = 'normal' } = options;\n\n    // __umiRequestCoreType__ use to identificat request core\n    // when value is 'normal' , use umi-request 's fetch request core\n    if (__umiRequestCoreType__ === 'normal') {\n      await next();\n      return;\n    }\n\n    // when value is not normal, use your request func.\n    const response = getResponseByOtherWay();\n\n    ctx.res = response;\n\n    await next();\n    return;\n  },\n  { core: true }\n);\n\nrequest('/api/v1/rpc', {\n  __umiRequestCoreType__: 'rpc',\n  parseResponse: false,\n})\n  .then(function(response) {\n    console.log(response);\n  })\n  .catch(function(error) {\n    console.log(error);\n  });\n```\n\n## Interceptor\n\nYou can intercept requests or responses before they are handled by then or catch.\n\n1. global Interceptor\n\n```javascript\n// request interceptor, change url or options.\nrequest.interceptors.request.use((url, options) =\u003e {\n  return {\n    url: `${url}\u0026interceptors=yes`,\n    options: { ...options, interceptors: true },\n  };\n});\n\n// Same as the last one\nrequest.interceptors.request.use(\n  (url, options) =\u003e {\n    return {\n      url: `${url}\u0026interceptors=yes`,\n      options: { ...options, interceptors: true },\n    };\n  },\n  { global: true }\n);\n\n// response interceptor, chagne response\nrequest.interceptors.response.use((response, options) =\u003e {\n  response.headers.append('interceptors', 'yes yo');\n  return response;\n});\n\n// handling error in response interceptor\nrequest.interceptors.response.use(response =\u003e {\n  const codeMaps = {\n    502: '网关错误。',\n    503: '服务不可用，服务器暂时过载或维护。',\n    504: '网关超时。',\n  };\n  message.error(codeMaps[response.status]);\n  return response;\n});\n\n// clone response in response interceptor\nrequest.interceptors.response.use(async response =\u003e {\n  const data = await response.clone().json();\n  if (data \u0026\u0026 data.NOT_LOGIN) {\n    location.href = '登录url';\n  }\n  return response;\n});\n```\n\n1. instance Interceptor\n\n```javascript\n// Global interceptors are used `request` instance method directly\nrequest.interceptors.request.use(\n  (url, options) =\u003e {\n    return {\n      url: `${url}\u0026interceptors=yes`,\n      options: { ...options, interceptors: true },\n    };\n  },\n  { global: false }\n); // second paramet defaults { global: true }\n\nfunction createClient(baseUrl) {\n  const request = extend({\n    prefix: baseUrl,\n  });\n  return request;\n}\n\nconst clientA = createClient('/api');\nconst clientB = createClient('/api');\n// Independent instance Interceptor\nclientA.interceptors.request.use(\n  (url, options) =\u003e {\n    return {\n      url: `${url}\u0026interceptors=clientA`,\n      options,\n    };\n  },\n  { global: false }\n);\n\nclientB.interceptors.request.use(\n  (url, options) =\u003e {\n    return {\n      url: `${url}\u0026interceptors=clientB`,\n      options,\n    };\n  },\n  { global: false }\n);\n```\n\n## Cancel request\n\n### Use AbortController\n\nBase on [AbortController](https://developer.mozilla.org/en-US/docs/Web/API/AbortController) that allows you to abort one or more Web requests as and when desired.\n\n```javascript\n// polyfill abort controller if needed\nimport 'yet-another-abortcontroller-polyfill'\nimport Request from 'umi-request';\n\nconst controller = new AbortController(); // create a controller\nconst { signal } = controller; // grab a reference to its associated AbortSignal object using the AbortController.signal property\n\nsignal.addEventListener('abort', () =\u003e {\n  console.log('aborted!');\n});\n\nRequest('/api/response_after_1_sec', {\n  signal, // pass in the AbortSignal as an option inside the request's options object (see {signal}, below). This associates the signal and controller with the fetch request and allows us to abort it by calling AbortController.abort(),\n});\n\n// 取消请求\nsetTimeout(() =\u003e {\n  controller.abort(); // Aborts a DOM request before it has completed. This is able to abort fetch requests, consumption of any response Body, and streams.\n}, 100);\n```\n\n### Use Cancel Token\n\n\u003e Cancel Token still work, but we don’t recommend using them in the new code.\n\n1. You can cancel a request using a cancel token.\n\n```javascript\nimport Request from 'umi-request';\n\nconst CancelToken = Request.CancelToken;\nconst { token, cancel } = CancelToken.source();\n\nRequest.get('/api/cancel', {\n  cancelToken: token,\n}).catch(function(thrown) {\n  if (Request.isCancel(thrown)) {\n    console.log('Request canceled', thrown.message);\n  } else {\n    // handle error\n  }\n});\n\nRequest.post(\n  '/api/cancel',\n  {\n    name: 'hello world',\n  },\n  {\n    cancelToken: token,\n  }\n);\n\n// cancel request (the message parameter is optional)\ncancel('Operation canceled by the user.');\n```\n\n2. You can also create a cancel token by passing an executor function to the CancelToken constructor:\n\n```javascript\nimport Request from 'umi-request';\n\nconst CancelToken = Request.CancelToken;\nlet cancel;\n\nRequest.get('/api/cancel', {\n  cancelToken: new CancelToken(function executor(c) {\n    cancel = c;\n  }),\n});\n\n// cancel request\ncancel();\n```\n\n## Cases\n\n### How to get Response Headers\n\nUse **Headers.get()** (more detail see [MDN 文档](https://developer.mozilla.org/zh-CN/docs/Web/API/Headers/get))\n\n```javascript\nrequest('/api/v1/some/api', { getResponse: true }).then(({ data, response }) =\u003e {\n  response.headers.get('Content-Type');\n});\n```\n\nIf want to get a custem header, you need to set [Access-Control-Expose-Headers](https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Access-Control-Expose-Headers) on server.\n\n### File upload\n\nUse FormData() contructor，the browser will add request header `\"Content-Type: multipart/form-data\"` automatically, developer don't need to add request header **Content-Type**\n\n```javascript\nconst formData = new FormData();\nformData.append('file', file);\nrequest('/api/v1/some/api', { method: 'post', data: formData, requestType: 'form',});\n```\n\nThe Access-Control-Expose-Headers response header indicates which headers can be exposed as part of the response by listing their names.[Access-Control-Expose-Headers](https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Access-Control-Expose-Headers)\n\n## Development and debugging\n\n- npm install\n- npm run dev\n- npm link\n- Then go to the project you are testing to execute npm link umi-request\n- Introduced and used\n\n## Questions \u0026 Suggestions\n\nPlease open an issue [here](https://github.com/umijs/umi/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc).\n\n## Code Contributors\n\n- @clock157\n- @yesmeck\n- @yutingzhao1991\n\n## LICENSE\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fumijs%2Fumi-request","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fumijs%2Fumi-request","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fumijs%2Fumi-request/lists"}