axios 0.21.4 → 0.30.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/CHANGELOG.md +318 -54
  2. package/README.md +378 -64
  3. package/SECURITY.md +3 -3
  4. package/UPGRADE_GUIDE.md +41 -13
  5. package/bin/check-build-version.js +19 -0
  6. package/bin/ssl_hotfix.js +22 -0
  7. package/dist/axios.js +2072 -1878
  8. package/dist/axios.js.map +1 -0
  9. package/dist/axios.min.js +2 -3
  10. package/dist/axios.min.js.map +1 -0
  11. package/dist/esm/axios.js +2379 -0
  12. package/dist/esm/axios.js.map +1 -0
  13. package/dist/esm/axios.min.js +2 -0
  14. package/dist/esm/axios.min.js.map +1 -0
  15. package/index.d.ts +219 -46
  16. package/lib/adapters/http.js +262 -130
  17. package/lib/adapters/xhr.js +59 -22
  18. package/lib/axios.js +19 -7
  19. package/lib/cancel/CancelToken.js +65 -4
  20. package/lib/cancel/CanceledError.js +24 -0
  21. package/lib/core/Axios.js +45 -17
  22. package/lib/core/AxiosError.js +97 -0
  23. package/lib/core/InterceptorManager.js +9 -0
  24. package/lib/core/buildFullPath.js +5 -2
  25. package/lib/core/dispatchRequest.js +13 -1
  26. package/lib/core/mergeConfig.js +54 -38
  27. package/lib/core/settle.js +3 -3
  28. package/lib/core/transformData.js +4 -3
  29. package/lib/{defaults.js → defaults/index.js} +64 -23
  30. package/lib/defaults/transitional.js +7 -0
  31. package/lib/env/README.md +3 -0
  32. package/lib/env/classes/FormData.js +2 -0
  33. package/lib/env/data.js +3 -0
  34. package/lib/helpers/AxiosURLSearchParams.js +42 -0
  35. package/lib/helpers/bind.js +1 -5
  36. package/lib/helpers/buildURL.js +18 -33
  37. package/lib/helpers/combineURLs.js +1 -1
  38. package/lib/helpers/formDataToJSON.js +74 -0
  39. package/lib/helpers/fromDataURI.js +51 -0
  40. package/lib/helpers/isAbsoluteURL.js +1 -1
  41. package/lib/helpers/isAxiosError.js +3 -1
  42. package/lib/helpers/isURLSameOrigin.js +12 -12
  43. package/lib/helpers/null.js +2 -0
  44. package/lib/helpers/parseHeaders.js +2 -2
  45. package/lib/helpers/parseProtocol.js +6 -0
  46. package/lib/helpers/toFormData.js +179 -0
  47. package/lib/helpers/toURLEncodedForm.js +18 -0
  48. package/lib/helpers/validator.js +14 -33
  49. package/lib/platform/browser/classes/FormData.js +3 -0
  50. package/lib/platform/browser/classes/URLSearchParams.js +5 -0
  51. package/lib/platform/browser/index.js +11 -0
  52. package/lib/platform/index.js +3 -0
  53. package/lib/platform/node/classes/FormData.js +3 -0
  54. package/lib/platform/node/classes/URLSearchParams.js +5 -0
  55. package/lib/platform/node/index.js +11 -0
  56. package/lib/utils.js +210 -37
  57. package/package.json +42 -26
  58. package/rollup.config.js +60 -0
  59. package/tsconfig.json +14 -0
  60. package/tslint.json +6 -0
  61. package/dist/axios.map +0 -1
  62. package/dist/axios.min.map +0 -1
  63. package/lib/cancel/Cancel.js +0 -19
  64. package/lib/core/createError.js +0 -18
  65. package/lib/core/enhanceError.js +0 -42
@@ -4,70 +4,186 @@ var utils = require('./../utils');
4
4
  var settle = require('./../core/settle');
5
5
  var buildFullPath = require('../core/buildFullPath');
6
6
  var buildURL = require('./../helpers/buildURL');
7
+ var getProxyForUrl = require('proxy-from-env').getProxyForUrl;
7
8
  var http = require('http');
8
9
  var https = require('https');
9
- var httpFollow = require('follow-redirects').http;
10
- var httpsFollow = require('follow-redirects').https;
10
+ var httpFollow = require('follow-redirects/http');
11
+ var httpsFollow = require('follow-redirects/https');
11
12
  var url = require('url');
12
13
  var zlib = require('zlib');
13
- var pkg = require('./../../package.json');
14
- var createError = require('../core/createError');
15
- var enhanceError = require('../core/enhanceError');
14
+ var VERSION = require('./../env/data').version;
15
+ var transitionalDefaults = require('../defaults/transitional');
16
+ var AxiosError = require('../core/AxiosError');
17
+ var CanceledError = require('../cancel/CanceledError');
18
+ var platform = require('../platform');
19
+ var fromDataURI = require('../helpers/fromDataURI');
20
+ var stream = require('stream');
16
21
 
17
22
  var isHttps = /https:?/;
18
23
 
24
+ var supportedProtocols = platform.protocols.map(function(protocol) {
25
+ return protocol + ':';
26
+ });
27
+
28
+ function dispatchBeforeRedirect(options) {
29
+ if (options.beforeRedirects.proxy) {
30
+ options.beforeRedirects.proxy(options);
31
+ }
32
+ if (options.beforeRedirects.config) {
33
+ options.beforeRedirects.config(options);
34
+ }
35
+ }
36
+
19
37
  /**
20
38
  *
21
39
  * @param {http.ClientRequestArgs} options
22
- * @param {AxiosProxyConfig} proxy
40
+ * @param {AxiosProxyConfig} configProxy
23
41
  * @param {string} location
24
42
  */
25
- function setProxy(options, proxy, location) {
26
- options.hostname = proxy.host;
27
- options.host = proxy.host;
28
- options.port = proxy.port;
29
- options.path = location;
30
-
31
- // Basic proxy authorization
32
- if (proxy.auth) {
33
- var base64 = Buffer.from(proxy.auth.username + ':' + proxy.auth.password, 'utf8').toString('base64');
34
- options.headers['Proxy-Authorization'] = 'Basic ' + base64;
43
+ function setProxy(options, configProxy, location) {
44
+ var proxy = configProxy;
45
+ if (!proxy && proxy !== false) {
46
+ var proxyUrl = getProxyForUrl(location);
47
+ if (proxyUrl) {
48
+ proxy = url.parse(proxyUrl);
49
+ // replace 'host' since the proxy object is not a URL object
50
+ proxy.host = proxy.hostname;
51
+ }
52
+ }
53
+ if (proxy) {
54
+ // Basic proxy authorization
55
+ if (proxy.auth) {
56
+ // Support proxy auth object form
57
+ if (proxy.auth.username || proxy.auth.password) {
58
+ proxy.auth = (proxy.auth.username || '') + ':' + (proxy.auth.password || '');
59
+ }
60
+ var base64 = Buffer
61
+ .from(proxy.auth, 'utf8')
62
+ .toString('base64');
63
+ options.headers['Proxy-Authorization'] = 'Basic ' + base64;
64
+ }
65
+
66
+ options.headers.host = options.hostname + (options.port ? ':' + options.port : '');
67
+ options.hostname = proxy.host;
68
+ options.host = proxy.host;
69
+ options.port = proxy.port;
70
+ options.path = location;
71
+ if (proxy.protocol) {
72
+ options.protocol = proxy.protocol;
73
+ }
35
74
  }
36
75
 
37
- // If a proxy is used, any redirects must also pass through the proxy
38
- options.beforeRedirect = function beforeRedirect(redirection) {
39
- redirection.headers.host = redirection.host;
40
- setProxy(redirection, proxy, redirection.href);
76
+ options.beforeRedirects.proxy = function beforeRedirect(redirectOptions) {
77
+ // Configure proxy for redirected request, passing the original config proxy to apply
78
+ // the exact same logic as if the redirected request was performed by axios directly.
79
+ setProxy(redirectOptions, configProxy, redirectOptions.href);
41
80
  };
42
81
  }
43
82
 
44
83
  /*eslint consistent-return:0*/
45
84
  module.exports = function httpAdapter(config) {
46
85
  return new Promise(function dispatchHttpRequest(resolvePromise, rejectPromise) {
86
+ var onCanceled;
87
+ function done() {
88
+ if (config.cancelToken) {
89
+ config.cancelToken.unsubscribe(onCanceled);
90
+ }
91
+
92
+ if (config.signal) {
93
+ config.signal.removeEventListener('abort', onCanceled);
94
+ }
95
+ }
47
96
  var resolve = function resolve(value) {
97
+ done();
48
98
  resolvePromise(value);
49
99
  };
100
+ var rejected = false;
50
101
  var reject = function reject(value) {
102
+ done();
103
+ rejected = true;
51
104
  rejectPromise(value);
52
105
  };
53
106
  var data = config.data;
107
+ var responseType = config.responseType;
108
+ var responseEncoding = config.responseEncoding;
109
+ var method = config.method.toUpperCase();
110
+
111
+ // Parse url
112
+ var fullPath = buildFullPath(config.baseURL, config.url, config.allowAbsoluteUrls);
113
+ var parsed = url.parse(fullPath);
114
+ var protocol = parsed.protocol || supportedProtocols[0];
115
+
116
+ if (protocol === 'data:') {
117
+ var convertedData;
118
+
119
+ if (method !== 'GET') {
120
+ return settle(resolve, reject, {
121
+ status: 405,
122
+ statusText: 'method not allowed',
123
+ headers: {},
124
+ config: config
125
+ });
126
+ }
127
+
128
+ try {
129
+ convertedData = fromDataURI(config.url, responseType === 'blob', {
130
+ Blob: config.env && config.env.Blob
131
+ });
132
+ } catch (err) {
133
+ throw AxiosError.from(err, AxiosError.ERR_BAD_REQUEST, config);
134
+ }
135
+
136
+ if (responseType === 'text') {
137
+ convertedData = convertedData.toString(responseEncoding);
138
+
139
+ if (!responseEncoding || responseEncoding === 'utf8') {
140
+ data = utils.stripBOM(convertedData);
141
+ }
142
+ } else if (responseType === 'stream') {
143
+ convertedData = stream.Readable.from(convertedData);
144
+ }
145
+
146
+ return settle(resolve, reject, {
147
+ data: convertedData,
148
+ status: 200,
149
+ statusText: 'OK',
150
+ headers: {},
151
+ config: config
152
+ });
153
+ }
154
+
155
+ if (supportedProtocols.indexOf(protocol) === -1) {
156
+ return reject(new AxiosError(
157
+ 'Unsupported protocol ' + protocol,
158
+ AxiosError.ERR_BAD_REQUEST,
159
+ config
160
+ ));
161
+ }
162
+
54
163
  var headers = config.headers;
164
+ var headerNames = {};
165
+
166
+ Object.keys(headers).forEach(function storeLowerName(name) {
167
+ headerNames[name.toLowerCase()] = name;
168
+ });
55
169
 
56
170
  // Set User-Agent (required by some servers)
57
171
  // See https://github.com/axios/axios/issues/69
58
- if ('User-Agent' in headers || 'user-agent' in headers) {
172
+ if ('user-agent' in headerNames) {
59
173
  // User-Agent is specified; handle case where no UA header is desired
60
- if (!headers['User-Agent'] && !headers['user-agent']) {
61
- delete headers['User-Agent'];
62
- delete headers['user-agent'];
174
+ if (!headers[headerNames['user-agent']]) {
175
+ delete headers[headerNames['user-agent']];
63
176
  }
64
177
  // Otherwise, use specified value
65
178
  } else {
66
179
  // Only set header if it hasn't been set in config
67
- headers['User-Agent'] = 'axios/' + pkg.version;
180
+ headers['User-Agent'] = 'axios/' + VERSION;
68
181
  }
69
182
 
70
- if (data && !utils.isStream(data)) {
183
+ // support for https://www.npmjs.com/package/form-data api
184
+ if (utils.isFormData(data) && utils.isFunction(data.getHeaders)) {
185
+ Object.assign(headers, data.getHeaders());
186
+ } else if (data && !utils.isStream(data)) {
71
187
  if (Buffer.isBuffer(data)) {
72
188
  // Nothing to do...
73
189
  } else if (utils.isArrayBuffer(data)) {
@@ -75,14 +191,25 @@ module.exports = function httpAdapter(config) {
75
191
  } else if (utils.isString(data)) {
76
192
  data = Buffer.from(data, 'utf-8');
77
193
  } else {
78
- return reject(createError(
194
+ return reject(new AxiosError(
79
195
  'Data after transformation must be a string, an ArrayBuffer, a Buffer, or a Stream',
196
+ AxiosError.ERR_BAD_REQUEST,
197
+ config
198
+ ));
199
+ }
200
+
201
+ if (config.maxBodyLength > -1 && data.length > config.maxBodyLength) {
202
+ return reject(new AxiosError(
203
+ 'Request body larger than maxBodyLength limit',
204
+ AxiosError.ERR_BAD_REQUEST,
80
205
  config
81
206
  ));
82
207
  }
83
208
 
84
209
  // Add Content-Length header if data exists
85
- headers['Content-Length'] = data.length;
210
+ if (!headerNames['content-length']) {
211
+ headers['Content-Length'] = data.length;
212
+ }
86
213
  }
87
214
 
88
215
  // HTTP basic authentication
@@ -93,11 +220,6 @@ module.exports = function httpAdapter(config) {
93
220
  auth = username + ':' + password;
94
221
  }
95
222
 
96
- // Parse url
97
- var fullPath = buildFullPath(config.baseURL, config.url);
98
- var parsed = url.parse(fullPath);
99
- var protocol = parsed.protocol || 'http:';
100
-
101
223
  if (!auth && parsed.auth) {
102
224
  var urlAuth = parsed.auth.split(':');
103
225
  var urlUsername = urlAuth[0] || '';
@@ -105,20 +227,29 @@ module.exports = function httpAdapter(config) {
105
227
  auth = urlUsername + ':' + urlPassword;
106
228
  }
107
229
 
108
- if (auth) {
109
- delete headers.Authorization;
230
+ if (auth && headerNames.authorization) {
231
+ delete headers[headerNames.authorization];
110
232
  }
111
233
 
112
- var isHttpsRequest = isHttps.test(protocol);
113
- var agent = isHttpsRequest ? config.httpsAgent : config.httpAgent;
234
+ try {
235
+ buildURL(parsed.path, config.params, config.paramsSerializer).replace(/^\?/, '');
236
+ } catch (err) {
237
+ var customErr = new Error(err.message);
238
+ customErr.config = config;
239
+ customErr.url = config.url;
240
+ customErr.exists = true;
241
+ reject(customErr);
242
+ }
114
243
 
115
244
  var options = {
116
245
  path: buildURL(parsed.path, config.params, config.paramsSerializer).replace(/^\?/, ''),
117
- method: config.method.toUpperCase(),
246
+ method: method,
118
247
  headers: headers,
119
- agent: agent,
120
248
  agents: { http: config.httpAgent, https: config.httpsAgent },
121
- auth: auth
249
+ auth: auth,
250
+ protocol: protocol,
251
+ beforeRedirect: dispatchBeforeRedirect,
252
+ beforeRedirects: {}
122
253
  };
123
254
 
124
255
  if (config.socketPath) {
@@ -126,76 +257,35 @@ module.exports = function httpAdapter(config) {
126
257
  } else {
127
258
  options.hostname = parsed.hostname;
128
259
  options.port = parsed.port;
129
- }
130
-
131
- var proxy = config.proxy;
132
- if (!proxy && proxy !== false) {
133
- var proxyEnv = protocol.slice(0, -1) + '_proxy';
134
- var proxyUrl = process.env[proxyEnv] || process.env[proxyEnv.toUpperCase()];
135
- if (proxyUrl) {
136
- var parsedProxyUrl = url.parse(proxyUrl);
137
- var noProxyEnv = process.env.no_proxy || process.env.NO_PROXY;
138
- var shouldProxy = true;
139
-
140
- if (noProxyEnv) {
141
- var noProxy = noProxyEnv.split(',').map(function trim(s) {
142
- return s.trim();
143
- });
144
-
145
- shouldProxy = !noProxy.some(function proxyMatch(proxyElement) {
146
- if (!proxyElement) {
147
- return false;
148
- }
149
- if (proxyElement === '*') {
150
- return true;
151
- }
152
- if (proxyElement[0] === '.' &&
153
- parsed.hostname.substr(parsed.hostname.length - proxyElement.length) === proxyElement) {
154
- return true;
155
- }
156
-
157
- return parsed.hostname === proxyElement;
158
- });
159
- }
160
-
161
- if (shouldProxy) {
162
- proxy = {
163
- host: parsedProxyUrl.hostname,
164
- port: parsedProxyUrl.port,
165
- protocol: parsedProxyUrl.protocol
166
- };
167
-
168
- if (parsedProxyUrl.auth) {
169
- var proxyUrlAuth = parsedProxyUrl.auth.split(':');
170
- proxy.auth = {
171
- username: proxyUrlAuth[0],
172
- password: proxyUrlAuth[1]
173
- };
174
- }
175
- }
176
- }
177
- }
178
-
179
- if (proxy) {
180
- options.headers.host = parsed.hostname + (parsed.port ? ':' + parsed.port : '');
181
- setProxy(options, proxy, protocol + '//' + parsed.hostname + (parsed.port ? ':' + parsed.port : '') + options.path);
260
+ setProxy(options, config.proxy, protocol + '//' + parsed.hostname + (parsed.port ? ':' + parsed.port : '') + options.path);
182
261
  }
183
262
 
184
263
  var transport;
185
- var isHttpsProxy = isHttpsRequest && (proxy ? isHttps.test(proxy.protocol) : true);
264
+ var isHttpsRequest = isHttps.test(options.protocol);
265
+ options.agent = isHttpsRequest ? config.httpsAgent : config.httpAgent;
186
266
  if (config.transport) {
187
267
  transport = config.transport;
188
268
  } else if (config.maxRedirects === 0) {
189
- transport = isHttpsProxy ? https : http;
269
+ transport = isHttpsRequest ? https : http;
190
270
  } else {
191
271
  if (config.maxRedirects) {
192
272
  options.maxRedirects = config.maxRedirects;
193
273
  }
194
- transport = isHttpsProxy ? httpsFollow : httpFollow;
274
+ if (config.beforeRedirect) {
275
+ options.beforeRedirects.config = config.beforeRedirect;
276
+ }
277
+ transport = isHttpsRequest ? httpsFollow : httpFollow;
195
278
  }
196
279
 
197
280
  if (config.maxBodyLength > -1) {
198
281
  options.maxBodyLength = config.maxBodyLength;
282
+ } else {
283
+ // follow-redirects does not skip comparison, so it should always succeed for axios -1 unlimited
284
+ options.maxBodyLength = Infinity;
285
+ }
286
+
287
+ if (config.insecureHTTPParser) {
288
+ options.insecureHTTPParser = config.insecureHTTPParser;
199
289
  }
200
290
 
201
291
  // Create the request
@@ -203,21 +293,26 @@ module.exports = function httpAdapter(config) {
203
293
  if (req.aborted) return;
204
294
 
205
295
  // uncompress the response body transparently if required
206
- var stream = res;
296
+ var responseStream = res;
207
297
 
208
298
  // return the last request in case of redirects
209
299
  var lastRequest = res.req || req;
210
300
 
301
+ // if decompress disabled we should not decompress
302
+ if (config.decompress !== false) {
303
+ // if no content, but headers still say that it is encoded,
304
+ // remove the header not confuse downstream operations
305
+ if (data && data.length === 0 && res.headers['content-encoding']) {
306
+ delete res.headers['content-encoding'];
307
+ }
211
308
 
212
- // if no content, is HEAD request or decompress disabled we should not decompress
213
- if (res.statusCode !== 204 && lastRequest.method !== 'HEAD' && config.decompress !== false) {
214
309
  switch (res.headers['content-encoding']) {
215
310
  /*eslint default-case:0*/
216
311
  case 'gzip':
217
312
  case 'compress':
218
313
  case 'deflate':
219
- // add the unzipper to the body stream processing pipeline
220
- stream = stream.pipe(zlib.createUnzip());
314
+ // add the unzipper to the body stream processing pipeline
315
+ responseStream = responseStream.pipe(zlib.createUnzip());
221
316
 
222
317
  // remove the content-encoding in order to not confuse downstream operations
223
318
  delete res.headers['content-encoding'];
@@ -233,39 +328,57 @@ module.exports = function httpAdapter(config) {
233
328
  request: lastRequest
234
329
  };
235
330
 
236
- if (config.responseType === 'stream') {
237
- response.data = stream;
331
+ if (responseType === 'stream') {
332
+ response.data = responseStream;
238
333
  settle(resolve, reject, response);
239
334
  } else {
240
335
  var responseBuffer = [];
241
336
  var totalResponseBytes = 0;
242
- stream.on('data', function handleStreamData(chunk) {
337
+ responseStream.on('data', function handleStreamData(chunk) {
243
338
  responseBuffer.push(chunk);
244
339
  totalResponseBytes += chunk.length;
245
340
 
246
341
  // make sure the content length is not over the maxContentLength if specified
247
342
  if (config.maxContentLength > -1 && totalResponseBytes > config.maxContentLength) {
248
- stream.destroy();
249
- reject(createError('maxContentLength size of ' + config.maxContentLength + ' exceeded',
250
- config, null, lastRequest));
343
+ // stream.destroy() emit aborted event before calling reject() on Node.js v16
344
+ rejected = true;
345
+ responseStream.destroy();
346
+ reject(new AxiosError('maxContentLength size of ' + config.maxContentLength + ' exceeded',
347
+ AxiosError.ERR_BAD_RESPONSE, config, lastRequest));
348
+ }
349
+ });
350
+
351
+ responseStream.on('aborted', function handlerStreamAborted() {
352
+ if (rejected) {
353
+ return;
251
354
  }
355
+ responseStream.destroy();
356
+ reject(new AxiosError(
357
+ 'response stream aborted',
358
+ AxiosError.ECONNABORTED,
359
+ config,
360
+ lastRequest
361
+ ));
252
362
  });
253
363
 
254
- stream.on('error', function handleStreamError(err) {
364
+ responseStream.on('error', function handleStreamError(err) {
255
365
  if (req.aborted) return;
256
- reject(enhanceError(err, config, null, lastRequest));
366
+ reject(AxiosError.from(err, null, config, lastRequest));
257
367
  });
258
368
 
259
- stream.on('end', function handleStreamEnd() {
260
- var responseData = Buffer.concat(responseBuffer);
261
- if (config.responseType !== 'arraybuffer') {
262
- responseData = responseData.toString(config.responseEncoding);
263
- if (!config.responseEncoding || config.responseEncoding === 'utf8') {
264
- responseData = utils.stripBOM(responseData);
369
+ responseStream.on('end', function handleStreamEnd() {
370
+ try {
371
+ var responseData = responseBuffer.length === 1 ? responseBuffer[0] : Buffer.concat(responseBuffer);
372
+ if (responseType !== 'arraybuffer') {
373
+ responseData = responseData.toString(responseEncoding);
374
+ if (!responseEncoding || responseEncoding === 'utf8') {
375
+ responseData = utils.stripBOM(responseData);
376
+ }
265
377
  }
378
+ response.data = responseData;
379
+ } catch (err) {
380
+ reject(AxiosError.from(err, null, config, response.request, response));
266
381
  }
267
-
268
- response.data = responseData;
269
382
  settle(resolve, reject, response);
270
383
  });
271
384
  }
@@ -273,8 +386,15 @@ module.exports = function httpAdapter(config) {
273
386
 
274
387
  // Handle errors
275
388
  req.on('error', function handleRequestError(err) {
276
- if (req.aborted && err.code !== 'ERR_FR_TOO_MANY_REDIRECTS') return;
277
- reject(enhanceError(err, config, null, req));
389
+ // @todo remove
390
+ // if (req.aborted && err.code !== AxiosError.ERR_FR_TOO_MANY_REDIRECTS) return;
391
+ reject(AxiosError.from(err, null, config, req));
392
+ });
393
+
394
+ // set tcp keep alive to prevent drop connection by peer
395
+ req.on('socket', function handleRequestSocket(socket) {
396
+ // default interval of sending ack packet is 1 minute
397
+ socket.setKeepAlive(true, 1000 * 60);
278
398
  });
279
399
 
280
400
  // Handle request timeout
@@ -283,10 +403,10 @@ module.exports = function httpAdapter(config) {
283
403
  var timeout = parseInt(config.timeout, 10);
284
404
 
285
405
  if (isNaN(timeout)) {
286
- reject(createError(
406
+ reject(new AxiosError(
287
407
  'error trying to parse `config.timeout` to int',
408
+ AxiosError.ERR_BAD_OPTION_VALUE,
288
409
  config,
289
- 'ERR_PARSE_TIMEOUT',
290
410
  req
291
411
  ));
292
412
 
@@ -296,33 +416,45 @@ module.exports = function httpAdapter(config) {
296
416
  // Sometime, the response will be very slow, and does not respond, the connect event will be block by event loop system.
297
417
  // And timer callback will be fired, and abort() will be invoked before connection, then get "socket hang up" and code ECONNRESET.
298
418
  // At this time, if we have a large number of request, nodejs will hang up some socket on background. and the number will up and up.
299
- // And then these socket which be hang up will devoring CPU little by little.
419
+ // And then these socket which be hang up will devouring CPU little by little.
300
420
  // ClientRequest.setTimeout will be fired on the specify milliseconds, and can make sure that abort() will be fired after connect.
301
421
  req.setTimeout(timeout, function handleRequestTimeout() {
302
422
  req.abort();
303
- reject(createError(
304
- 'timeout of ' + timeout + 'ms exceeded',
423
+ var timeoutErrorMessage = config.timeout ? 'timeout of ' + config.timeout + 'ms exceeded' : 'timeout exceeded';
424
+ var transitional = config.transitional || transitionalDefaults;
425
+ if (config.timeoutErrorMessage) {
426
+ timeoutErrorMessage = config.timeoutErrorMessage;
427
+ }
428
+ reject(new AxiosError(
429
+ timeoutErrorMessage,
430
+ transitional.clarifyTimeoutError ? AxiosError.ETIMEDOUT : AxiosError.ECONNABORTED,
305
431
  config,
306
- config.transitional && config.transitional.clarifyTimeoutError ? 'ETIMEDOUT' : 'ECONNABORTED',
307
432
  req
308
433
  ));
309
434
  });
310
435
  }
311
436
 
312
- if (config.cancelToken) {
437
+ if (config.cancelToken || config.signal) {
313
438
  // Handle cancellation
314
- config.cancelToken.promise.then(function onCanceled(cancel) {
439
+ // eslint-disable-next-line func-names
440
+ onCanceled = function(cancel) {
315
441
  if (req.aborted) return;
316
442
 
317
443
  req.abort();
318
- reject(cancel);
319
- });
444
+ reject(!cancel || cancel.type ? new CanceledError(null, config, req) : cancel);
445
+ };
446
+
447
+ config.cancelToken && config.cancelToken.subscribe(onCanceled);
448
+ if (config.signal) {
449
+ config.signal.aborted ? onCanceled() : config.signal.addEventListener('abort', onCanceled);
450
+ }
320
451
  }
321
452
 
453
+
322
454
  // Send the request
323
455
  if (utils.isStream(data)) {
324
456
  data.on('error', function handleStreamError(err) {
325
- reject(enhanceError(err, config, null, req));
457
+ reject(AxiosError.from(err, config, null, req));
326
458
  }).pipe(req);
327
459
  } else {
328
460
  req.end(data);