axios 1.1.3 → 1.3.4

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.

Potentially problematic release.


This version of axios might be problematic. Click here for more details.

Files changed (48) hide show
  1. package/CHANGELOG.md +312 -75
  2. package/{UPGRADE_GUIDE.md → MIGRATION_GUIDE.md} +1 -1
  3. package/README.md +64 -25
  4. package/dist/axios.js +888 -582
  5. package/dist/axios.js.map +1 -1
  6. package/dist/axios.min.js +1 -1
  7. package/dist/axios.min.js.map +1 -1
  8. package/dist/browser/axios.cjs +3191 -0
  9. package/dist/browser/axios.cjs.map +1 -0
  10. package/dist/esm/axios.js +889 -626
  11. package/dist/esm/axios.js.map +1 -1
  12. package/dist/esm/axios.min.js +1 -1
  13. package/dist/esm/axios.min.js.map +1 -1
  14. package/dist/node/axios.cjs +1001 -575
  15. package/dist/node/axios.cjs.map +1 -1
  16. package/index.d.cts +528 -0
  17. package/index.d.ts +116 -56
  18. package/index.js +12 -3
  19. package/lib/adapters/adapters.js +59 -0
  20. package/lib/adapters/http.js +118 -57
  21. package/lib/adapters/xhr.js +7 -4
  22. package/lib/axios.js +13 -3
  23. package/lib/core/Axios.js +10 -8
  24. package/lib/core/AxiosError.js +1 -1
  25. package/lib/core/AxiosHeaders.js +102 -80
  26. package/lib/core/dispatchRequest.js +7 -2
  27. package/lib/core/mergeConfig.js +50 -46
  28. package/lib/defaults/index.js +2 -21
  29. package/lib/env/classes/FormData.js +2 -2
  30. package/lib/env/data.js +1 -1
  31. package/lib/helpers/HttpStatusCode.js +71 -0
  32. package/lib/helpers/ZlibHeaderTransformStream.js +28 -0
  33. package/lib/helpers/formDataToStream.js +111 -0
  34. package/lib/helpers/readBlob.js +15 -0
  35. package/lib/helpers/speedometer.js +1 -1
  36. package/lib/helpers/toFormData.js +5 -15
  37. package/lib/platform/browser/classes/Blob.js +3 -0
  38. package/lib/platform/browser/classes/FormData.js +1 -1
  39. package/lib/platform/browser/index.js +21 -0
  40. package/lib/utils.js +107 -9
  41. package/package.json +86 -14
  42. package/bin/ssl_hotfix.js +0 -22
  43. package/gulpfile.js +0 -88
  44. package/karma.conf.cjs +0 -250
  45. package/lib/adapters/index.js +0 -33
  46. package/rollup.config.js +0 -90
  47. package/tsconfig.json +0 -14
  48. package/tslint.json +0 -6
@@ -7,6 +7,7 @@ import buildURL from './../helpers/buildURL.js';
7
7
  import {getProxyForUrl} from 'proxy-from-env';
8
8
  import http from 'http';
9
9
  import https from 'https';
10
+ import util from 'util';
10
11
  import followRedirects from 'follow-redirects';
11
12
  import zlib from 'zlib';
12
13
  import {VERSION} from '../env/data.js';
@@ -19,6 +20,19 @@ import stream from 'stream';
19
20
  import AxiosHeaders from '../core/AxiosHeaders.js';
20
21
  import AxiosTransformStream from '../helpers/AxiosTransformStream.js';
21
22
  import EventEmitter from 'events';
23
+ import formDataToStream from "../helpers/formDataToStream.js";
24
+ import readBlob from "../helpers/readBlob.js";
25
+ import ZlibHeaderTransformStream from '../helpers/ZlibHeaderTransformStream.js';
26
+
27
+ const zlibOptions = {
28
+ flush: zlib.constants.Z_SYNC_FLUSH,
29
+ finishFlush: zlib.constants.Z_SYNC_FLUSH
30
+ };
31
+
32
+ const brotliOptions = {
33
+ flush: zlib.constants.BROTLI_OPERATION_FLUSH,
34
+ finishFlush: zlib.constants.BROTLI_OPERATION_FLUSH
35
+ }
22
36
 
23
37
  const isBrotliSupported = utils.isFunction(zlib.createBrotliDecompress);
24
38
 
@@ -100,14 +114,41 @@ function setProxy(options, configProxy, location) {
100
114
  };
101
115
  }
102
116
 
117
+ const isHttpAdapterSupported = typeof process !== 'undefined' && utils.kindOf(process) === 'process';
118
+
119
+ // temporary hotfix
120
+
121
+ const wrapAsync = (asyncExecutor) => {
122
+ return new Promise((resolve, reject) => {
123
+ let onDone;
124
+ let isDone;
125
+
126
+ const done = (value, isRejected) => {
127
+ if (isDone) return;
128
+ isDone = true;
129
+ onDone && onDone(value, isRejected);
130
+ }
131
+
132
+ const _resolve = (value) => {
133
+ done(value);
134
+ resolve(value);
135
+ };
136
+
137
+ const _reject = (reason) => {
138
+ done(reason, true);
139
+ reject(reason);
140
+ }
141
+
142
+ asyncExecutor(_resolve, _reject, (onDoneHandler) => (onDone = onDoneHandler)).catch(_reject);
143
+ })
144
+ };
145
+
103
146
  /*eslint consistent-return:0*/
104
- export default function httpAdapter(config) {
105
- return new Promise(function dispatchHttpRequest(resolvePromise, rejectPromise) {
106
- let data = config.data;
107
- const responseType = config.responseType;
108
- const responseEncoding = config.responseEncoding;
147
+ export default isHttpAdapterSupported && function httpAdapter(config) {
148
+ return wrapAsync(async function dispatchHttpRequest(resolve, reject, onDone) {
149
+ let {data} = config;
150
+ const {responseType, responseEncoding} = config;
109
151
  const method = config.method.toUpperCase();
110
- let isFinished;
111
152
  let isDone;
112
153
  let rejected = false;
113
154
  let req;
@@ -115,10 +156,7 @@ export default function httpAdapter(config) {
115
156
  // temporary internal emitter until the AxiosRequest class will be implemented
116
157
  const emitter = new EventEmitter();
117
158
 
118
- function onFinished() {
119
- if (isFinished) return;
120
- isFinished = true;
121
-
159
+ const onFinished = () => {
122
160
  if (config.cancelToken) {
123
161
  config.cancelToken.unsubscribe(abort);
124
162
  }
@@ -130,26 +168,13 @@ export default function httpAdapter(config) {
130
168
  emitter.removeAllListeners();
131
169
  }
132
170
 
133
- function done(value, isRejected) {
134
- if (isDone) return;
135
-
171
+ onDone((value, isRejected) => {
136
172
  isDone = true;
137
-
138
173
  if (isRejected) {
139
174
  rejected = true;
140
175
  onFinished();
141
176
  }
142
-
143
- isRejected ? rejectPromise(value) : resolvePromise(value);
144
- }
145
-
146
- const resolve = function resolve(value) {
147
- done(value);
148
- };
149
-
150
- const reject = function reject(value) {
151
- done(value, true);
152
- };
177
+ });
153
178
 
154
179
  function abort(reason) {
155
180
  emitter.emit('abort', !reason || reason.type ? new CanceledError(null, config, req) : reason);
@@ -166,7 +191,7 @@ export default function httpAdapter(config) {
166
191
 
167
192
  // Parse url
168
193
  const fullPath = buildFullPath(config.baseURL, config.url);
169
- const parsed = new URL(fullPath);
194
+ const parsed = new URL(fullPath, 'http://localhost');
170
195
  const protocol = parsed.protocol || supportedProtocols[0];
171
196
 
172
197
  if (protocol === 'data:') {
@@ -193,7 +218,7 @@ export default function httpAdapter(config) {
193
218
  convertedData = convertedData.toString(responseEncoding);
194
219
 
195
220
  if (!responseEncoding || responseEncoding === 'utf8') {
196
- data = utils.stripBOM(convertedData);
221
+ convertedData = utils.stripBOM(convertedData);
197
222
  }
198
223
  } else if (responseType === 'stream') {
199
224
  convertedData = stream.Readable.from(convertedData);
@@ -203,7 +228,7 @@ export default function httpAdapter(config) {
203
228
  data: convertedData,
204
229
  status: 200,
205
230
  statusText: 'OK',
206
- headers: {},
231
+ headers: new AxiosHeaders(),
207
232
  config
208
233
  });
209
234
  }
@@ -230,9 +255,32 @@ export default function httpAdapter(config) {
230
255
  let maxUploadRate = undefined;
231
256
  let maxDownloadRate = undefined;
232
257
 
233
- // support for https://www.npmjs.com/package/form-data api
234
- if (utils.isFormData(data) && utils.isFunction(data.getHeaders)) {
258
+ // support for spec compliant FormData objects
259
+ if (utils.isSpecCompliantForm(data)) {
260
+ const userBoundary = headers.getContentType(/boundary=([-_\w\d]{10,70})/i);
261
+
262
+ data = formDataToStream(data, (formHeaders) => {
263
+ headers.set(formHeaders);
264
+ }, {
265
+ tag: `axios-${VERSION}-boundary`,
266
+ boundary: userBoundary && userBoundary[1] || undefined
267
+ });
268
+ // support for https://www.npmjs.com/package/form-data api
269
+ } else if (utils.isFormData(data) && utils.isFunction(data.getHeaders)) {
235
270
  headers.set(data.getHeaders());
271
+
272
+ if (!headers.hasContentLength()) {
273
+ try {
274
+ const knownLength = await util.promisify(data.getLength).call(data);
275
+ Number.isFinite(knownLength) && knownLength >= 0 && headers.setContentLength(knownLength);
276
+ /*eslint no-empty:0*/
277
+ } catch (e) {
278
+ }
279
+ }
280
+ } else if (utils.isBlob(data)) {
281
+ data.size && headers.setContentType(data.type || 'application/octet-stream');
282
+ headers.setContentLength(data.size || 0);
283
+ data = stream.Readable.from(readBlob(data));
236
284
  } else if (data && !utils.isStream(data)) {
237
285
  if (Buffer.isBuffer(data)) {
238
286
  // Nothing to do...
@@ -249,7 +297,7 @@ export default function httpAdapter(config) {
249
297
  }
250
298
 
251
299
  // Add Content-Length header if data exists
252
- headers.set('Content-Length', data.length, false);
300
+ headers.setContentLength(data.length, false);
253
301
 
254
302
  if (config.maxBodyLength > -1 && data.length > config.maxBodyLength) {
255
303
  return reject(new AxiosError(
@@ -260,7 +308,7 @@ export default function httpAdapter(config) {
260
308
  }
261
309
  }
262
310
 
263
- const contentLength = +headers.getContentLength();
311
+ const contentLength = utils.toFiniteNumber(headers.getContentLength());
264
312
 
265
313
  if (utils.isArray(maxRate)) {
266
314
  maxUploadRate = maxRate[0];
@@ -275,7 +323,7 @@ export default function httpAdapter(config) {
275
323
  }
276
324
 
277
325
  data = stream.pipeline([data, new AxiosTransformStream({
278
- length: utils.toFiniteNumber(contentLength),
326
+ length: contentLength,
279
327
  maxRate: utils.toFiniteNumber(maxUploadRate)
280
328
  })], utils.noop);
281
329
 
@@ -318,7 +366,10 @@ export default function httpAdapter(config) {
318
366
  return reject(customErr);
319
367
  }
320
368
 
321
- headers.set('Accept-Encoding', 'gzip, deflate, br', false);
369
+ headers.set(
370
+ 'Accept-Encoding',
371
+ 'gzip, compress, deflate' + (isBrotliSupported ? ', br' : ''), false
372
+ );
322
373
 
323
374
  const options = {
324
375
  path,
@@ -373,56 +424,66 @@ export default function httpAdapter(config) {
373
424
 
374
425
  const streams = [res];
375
426
 
376
- // uncompress the response body transparently if required
427
+ const responseLength = +res.headers['content-length'];
428
+
429
+ if (onDownloadProgress) {
430
+ const transformStream = new AxiosTransformStream({
431
+ length: utils.toFiniteNumber(responseLength),
432
+ maxRate: utils.toFiniteNumber(maxDownloadRate)
433
+ });
434
+
435
+ onDownloadProgress && transformStream.on('progress', progress => {
436
+ onDownloadProgress(Object.assign(progress, {
437
+ download: true
438
+ }));
439
+ });
440
+
441
+ streams.push(transformStream);
442
+ }
443
+
444
+ // decompress the response body transparently if required
377
445
  let responseStream = res;
378
446
 
379
447
  // return the last request in case of redirects
380
448
  const lastRequest = res.req || req;
381
449
 
382
450
  // if decompress disabled we should not decompress
383
- if (config.decompress !== false) {
451
+ if (config.decompress !== false && res.headers['content-encoding']) {
384
452
  // if no content, but headers still say that it is encoded,
385
453
  // remove the header not confuse downstream operations
386
- if (data && data.length === 0 && res.headers['content-encoding']) {
454
+ if (method === 'HEAD' || res.statusCode === 204) {
387
455
  delete res.headers['content-encoding'];
388
456
  }
389
457
 
390
458
  switch (res.headers['content-encoding']) {
391
459
  /*eslint default-case:0*/
392
460
  case 'gzip':
461
+ case 'x-gzip':
393
462
  case 'compress':
463
+ case 'x-compress':
464
+ // add the unzipper to the body stream processing pipeline
465
+ streams.push(zlib.createUnzip(zlibOptions));
466
+
467
+ // remove the content-encoding in order to not confuse downstream operations
468
+ delete res.headers['content-encoding'];
469
+ break;
394
470
  case 'deflate':
471
+ streams.push(new ZlibHeaderTransformStream());
472
+
395
473
  // add the unzipper to the body stream processing pipeline
396
- streams.push(zlib.createUnzip());
474
+ streams.push(zlib.createUnzip(zlibOptions));
397
475
 
398
476
  // remove the content-encoding in order to not confuse downstream operations
399
477
  delete res.headers['content-encoding'];
400
478
  break;
401
479
  case 'br':
402
480
  if (isBrotliSupported) {
403
- streams.push(zlib.createBrotliDecompress());
481
+ streams.push(zlib.createBrotliDecompress(brotliOptions));
404
482
  delete res.headers['content-encoding'];
405
483
  }
406
484
  }
407
485
  }
408
486
 
409
- if (onDownloadProgress) {
410
- const responseLength = +res.headers['content-length'];
411
-
412
- const transformStream = new AxiosTransformStream({
413
- length: utils.toFiniteNumber(responseLength),
414
- maxRate: utils.toFiniteNumber(maxDownloadRate)
415
- });
416
-
417
- onDownloadProgress && transformStream.on('progress', progress => {
418
- onDownloadProgress(Object.assign(progress, {
419
- download: true
420
- }));
421
- });
422
-
423
- streams.push(transformStream);
424
- }
425
-
426
487
  responseStream = streams.length > 1 ? stream.pipeline(streams, utils.noop) : streams[0];
427
488
 
428
489
  const offListeners = stream.finished(responseStream, () => {
@@ -588,4 +649,4 @@ export default function httpAdapter(config) {
588
649
  });
589
650
  }
590
651
 
591
- export const __setProxy = setProxy;
652
+ export const __setProxy = setProxy;
@@ -33,7 +33,8 @@ function progressEventReducer(listener, isDownloadStream) {
33
33
  progress: total ? (loaded / total) : undefined,
34
34
  bytes: progressBytes,
35
35
  rate: rate ? rate : undefined,
36
- estimated: rate && total && inRange ? (total - loaded) / rate : undefined
36
+ estimated: rate && total && inRange ? (total - loaded) / rate : undefined,
37
+ event: e
37
38
  };
38
39
 
39
40
  data[isDownloadStream ? 'download' : 'upload'] = true;
@@ -42,7 +43,9 @@ function progressEventReducer(listener, isDownloadStream) {
42
43
  };
43
44
  }
44
45
 
45
- export default function xhrAdapter(config) {
46
+ const isXHRAdapterSupported = typeof XMLHttpRequest !== 'undefined';
47
+
48
+ export default isXHRAdapterSupported && function (config) {
46
49
  return new Promise(function dispatchXhrRequest(resolve, reject) {
47
50
  let requestData = config.data;
48
51
  const requestHeaders = AxiosHeaders.from(config.headers).normalize();
@@ -58,7 +61,7 @@ export default function xhrAdapter(config) {
58
61
  }
59
62
  }
60
63
 
61
- if (utils.isFormData(requestData) && platform.isStandardBrowserEnv) {
64
+ if (utils.isFormData(requestData) && (platform.isStandardBrowserEnv || platform.isStandardBrowserWebWorkerEnv)) {
62
65
  requestHeaders.setContentType(false); // Let the browser set it
63
66
  }
64
67
 
@@ -86,7 +89,7 @@ export default function xhrAdapter(config) {
86
89
  const responseHeaders = AxiosHeaders.from(
87
90
  'getAllResponseHeaders' in request && request.getAllResponseHeaders()
88
91
  );
89
- const responseData = !responseType || responseType === 'text' || responseType === 'json' ?
92
+ const responseData = !responseType || responseType === 'text' || responseType === 'json' ?
90
93
  request.responseText : request.response;
91
94
  const response = {
92
95
  data: responseData,
package/lib/axios.js CHANGED
@@ -14,6 +14,8 @@ import toFormData from './helpers/toFormData.js';
14
14
  import AxiosError from './core/AxiosError.js';
15
15
  import spread from './helpers/spread.js';
16
16
  import isAxiosError from './helpers/isAxiosError.js';
17
+ import AxiosHeaders from "./core/AxiosHeaders.js";
18
+ import HttpStatusCode from './helpers/HttpStatusCode.js';
17
19
 
18
20
  /**
19
21
  * Create an instance of Axios
@@ -69,8 +71,16 @@ axios.spread = spread;
69
71
  // Expose isAxiosError
70
72
  axios.isAxiosError = isAxiosError;
71
73
 
72
- axios.formToJSON = thing => {
73
- return formDataToJSON(utils.isHTMLForm(thing) ? new FormData(thing) : thing);
74
- };
74
+ // Expose mergeConfig
75
+ axios.mergeConfig = mergeConfig;
76
+
77
+ axios.AxiosHeaders = AxiosHeaders;
78
+
79
+ axios.formToJSON = thing => formDataToJSON(utils.isHTMLForm(thing) ? new FormData(thing) : thing);
80
+
81
+ axios.HttpStatusCode = HttpStatusCode;
82
+
83
+ axios.default = axios;
75
84
 
85
+ // this module should only have a default export
76
86
  export default axios
package/lib/core/Axios.js CHANGED
@@ -47,7 +47,7 @@ class Axios {
47
47
 
48
48
  config = mergeConfig(this.defaults, config);
49
49
 
50
- const {transitional, paramsSerializer} = config;
50
+ const {transitional, paramsSerializer, headers} = config;
51
51
 
52
52
  if (transitional !== undefined) {
53
53
  validator.assertOptions(transitional, {
@@ -67,20 +67,22 @@ class Axios {
67
67
  // Set config.method
68
68
  config.method = (config.method || this.defaults.method || 'get').toLowerCase();
69
69
 
70
+ let contextHeaders;
71
+
70
72
  // Flatten headers
71
- const defaultHeaders = config.headers && utils.merge(
72
- config.headers.common,
73
- config.headers[config.method]
73
+ contextHeaders = headers && utils.merge(
74
+ headers.common,
75
+ headers[config.method]
74
76
  );
75
77
 
76
- defaultHeaders && utils.forEach(
78
+ contextHeaders && utils.forEach(
77
79
  ['delete', 'get', 'head', 'post', 'put', 'patch', 'common'],
78
- function cleanHeaderConfig(method) {
79
- delete config.headers[method];
80
+ (method) => {
81
+ delete headers[method];
80
82
  }
81
83
  );
82
84
 
83
- config.headers = new AxiosHeaders(config.headers, defaultHeaders);
85
+ config.headers = AxiosHeaders.concat(contextHeaders, headers);
84
86
 
85
87
  // filter out skipped interceptors
86
88
  const requestInterceptorChain = [];
@@ -45,7 +45,7 @@ utils.inherits(AxiosError, Error, {
45
45
  columnNumber: this.columnNumber,
46
46
  stack: this.stack,
47
47
  // Axios
48
- config: this.config,
48
+ config: utils.toJSONObject(this.config),
49
49
  code: this.code,
50
50
  status: this.response && this.response.status ? this.response.status : null
51
51
  };