axios 0.31.1 → 0.32.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.
package/index.d.ts CHANGED
@@ -154,11 +154,14 @@ export interface AxiosRequestConfig<D = any> {
154
154
  onUploadProgress?: (progressEvent: ProgressEvent) => void;
155
155
  onDownloadProgress?: (progressEvent: ProgressEvent) => void;
156
156
  maxContentLength?: number;
157
+ formDataHeaderPolicy?: 'legacy' | 'content-only';
158
+ redact?: string[];
157
159
  validateStatus?: ((status: number) => boolean) | null;
158
160
  maxBodyLength?: number;
159
161
  maxRedirects?: number;
160
162
  beforeRedirect?: (options: Record<string, any>, responseDetails: {headers: Record<string, string>}) => void;
161
163
  socketPath?: string | null;
164
+ allowedSocketPaths?: string | string[] | null;
162
165
  httpAgent?: any;
163
166
  httpsAgent?: any;
164
167
  proxy?: AxiosProxyConfig | false;
@@ -10,6 +10,7 @@ var https = require('https');
10
10
  var httpFollow = require('follow-redirects/http');
11
11
  var httpsFollow = require('follow-redirects/https');
12
12
  var url = require('url');
13
+ var path = require('path');
13
14
  var zlib = require('zlib');
14
15
  var VERSION = require('./../env/data').version;
15
16
  var transitionalDefaults = require('../defaults/transitional');
@@ -36,6 +37,94 @@ function dispatchBeforeRedirect(options) {
36
37
  }
37
38
  }
38
39
 
40
+ function removeProxyAuthorization(headers) {
41
+ Object.keys(headers).forEach(function removeHeader(header) {
42
+ if (header.toLowerCase() === 'proxy-authorization') {
43
+ delete headers[header];
44
+ }
45
+ });
46
+ }
47
+
48
+ function normalizeSocketPath(socketPath) {
49
+ if (/^\\\\[.?]\\pipe\\/i.test(socketPath)) {
50
+ return socketPath;
51
+ }
52
+
53
+ return path.resolve(socketPath);
54
+ }
55
+
56
+ function getAllowedSocketPaths(config) {
57
+ var allowedSocketPaths = config.allowedSocketPaths;
58
+
59
+ if (
60
+ allowedSocketPaths === null ||
61
+ typeof allowedSocketPaths === 'undefined'
62
+ ) {
63
+ return null;
64
+ }
65
+
66
+ if (utils.isString(allowedSocketPaths)) {
67
+ return [allowedSocketPaths];
68
+ }
69
+
70
+ if (utils.isArray(allowedSocketPaths)) {
71
+ for (var i = 0; i < allowedSocketPaths.length; i++) {
72
+ if (!utils.isString(allowedSocketPaths[i])) {
73
+ return false;
74
+ }
75
+ }
76
+
77
+ return allowedSocketPaths;
78
+ }
79
+
80
+ return false;
81
+ }
82
+
83
+ function checkSocketPath(config) {
84
+ var socketPath = config.socketPath;
85
+
86
+ if (!socketPath) {
87
+ return null;
88
+ }
89
+
90
+ if (!utils.isString(socketPath)) {
91
+ return new AxiosError(
92
+ 'config.socketPath must be a string',
93
+ AxiosError.ERR_BAD_OPTION_VALUE,
94
+ config
95
+ );
96
+ }
97
+
98
+ var allowedSocketPaths = getAllowedSocketPaths(config);
99
+
100
+ if (allowedSocketPaths === false) {
101
+ return new AxiosError(
102
+ 'config.allowedSocketPaths must be a string, an array of strings, or null',
103
+ AxiosError.ERR_BAD_OPTION_VALUE,
104
+ config
105
+ );
106
+ }
107
+
108
+ if (allowedSocketPaths) {
109
+ var normalizedSocketPath = normalizeSocketPath(socketPath);
110
+ var allowed = allowedSocketPaths.some(
111
+ function isAllowed(allowedSocketPath) {
112
+ return normalizeSocketPath(allowedSocketPath) === normalizedSocketPath;
113
+ }
114
+ );
115
+
116
+ if (!allowed) {
117
+ return new AxiosError(
118
+ 'config.socketPath is not allowed by config.allowedSocketPaths',
119
+ AxiosError.ERR_BAD_OPTION_VALUE,
120
+ config
121
+ );
122
+ }
123
+ }
124
+
125
+ return null;
126
+ }
127
+
39
128
  /**
40
129
  *
41
130
  * @param {http.ClientRequestArgs} options
@@ -54,20 +143,37 @@ function setProxy(options, configProxy, location) {
54
143
  }
55
144
  }
56
145
  }
146
+ if (!proxy) {
147
+ removeProxyAuthorization(options.headers);
148
+ }
57
149
  if (proxy) {
58
150
  // Basic proxy authorization
59
- if (proxy.auth) {
151
+ var proxyAuth = utils.hasOwnProperty(proxy, 'auth')
152
+ ? proxy.auth
153
+ : undefined;
154
+ if (proxyAuth) {
60
155
  // Support proxy auth object form
61
- if (proxy.auth.username || proxy.auth.password) {
62
- proxy.auth = (proxy.auth.username || '') + ':' + (proxy.auth.password || '');
156
+ if (utils.isObject(proxyAuth)) {
157
+ var proxyUsername = utils.hasOwnProperty(proxyAuth, 'username')
158
+ ? proxyAuth.username
159
+ : '';
160
+ var proxyPassword = utils.hasOwnProperty(proxyAuth, 'password')
161
+ ? proxyAuth.password
162
+ : '';
163
+ proxyAuth =
164
+ proxyUsername || proxyPassword
165
+ ? proxyUsername + ':' + proxyPassword
166
+ : undefined;
167
+ }
168
+ if (proxyAuth) {
169
+ var base64 = Buffer.from(proxyAuth, 'utf8').toString('base64');
170
+ removeProxyAuthorization(options.headers);
171
+ options.headers['Proxy-Authorization'] = 'Basic ' + base64;
63
172
  }
64
- var base64 = Buffer
65
- .from(proxy.auth, 'utf8')
66
- .toString('base64');
67
- options.headers['Proxy-Authorization'] = 'Basic ' + base64;
68
173
  }
69
174
 
70
- options.headers.host = options.hostname + (options.port ? ':' + options.port : '');
175
+ options.headers.host =
176
+ options.hostname + (options.port ? ':' + options.port : '');
71
177
  options.hostname = proxy.host;
72
178
  options.host = proxy.host;
73
179
  options.port = proxy.port;
@@ -86,7 +192,10 @@ function setProxy(options, configProxy, location) {
86
192
 
87
193
  /*eslint consistent-return:0*/
88
194
  module.exports = function httpAdapter(config) {
89
- return new Promise(function dispatchHttpRequest(resolvePromise, rejectPromise) {
195
+ return new Promise(function dispatchHttpRequest(
196
+ resolvePromise,
197
+ rejectPromise
198
+ ) {
90
199
  var onCanceled;
91
200
  function done() {
92
201
  if (config.cancelToken) {
@@ -113,7 +222,11 @@ module.exports = function httpAdapter(config) {
113
222
  var method = config.method.toUpperCase();
114
223
 
115
224
  // Parse url
116
- var fullPath = buildFullPath(config.baseURL, config.url, config.allowAbsoluteUrls);
225
+ var fullPath = buildFullPath(
226
+ config.baseURL,
227
+ config.url,
228
+ config.allowAbsoluteUrls
229
+ );
117
230
  var parsed = url.parse(fullPath);
118
231
  var protocol = parsed.protocol || supportedProtocols[0];
119
232
 
@@ -125,11 +238,15 @@ module.exports = function httpAdapter(config) {
125
238
  var estimated = estimateDataURLDecodedBytes(dataUrl);
126
239
 
127
240
  if (estimated > config.maxContentLength) {
128
- return reject(new AxiosError(
129
- 'maxContentLength size of ' + config.maxContentLength + ' exceeded',
130
- AxiosError.ERR_BAD_RESPONSE,
131
- config
132
- ));
241
+ return reject(
242
+ new AxiosError(
243
+ 'maxContentLength size of ' +
244
+ config.maxContentLength +
245
+ ' exceeded',
246
+ AxiosError.ERR_BAD_RESPONSE,
247
+ config
248
+ )
249
+ );
133
250
  }
134
251
  }
135
252
 
@@ -145,7 +262,9 @@ module.exports = function httpAdapter(config) {
145
262
  }
146
263
 
147
264
  try {
148
- var envOption = utils.hasOwnProperty(config, 'env') ? config.env : undefined;
265
+ var envOption = utils.hasOwnProperty(config, 'env')
266
+ ? config.env
267
+ : undefined;
149
268
  convertedData = fromDataURI(config.url, responseType === 'blob', {
150
269
  Blob: envOption && envOption.Blob
151
270
  });
@@ -173,11 +292,13 @@ module.exports = function httpAdapter(config) {
173
292
  }
174
293
 
175
294
  if (supportedProtocols.indexOf(protocol) === -1) {
176
- return reject(new AxiosError(
177
- 'Unsupported protocol ' + protocol,
178
- AxiosError.ERR_BAD_REQUEST,
179
- config
180
- ));
295
+ return reject(
296
+ new AxiosError(
297
+ 'Unsupported protocol ' + protocol,
298
+ AxiosError.ERR_BAD_REQUEST,
299
+ config
300
+ )
301
+ );
181
302
  }
182
303
 
183
304
  var headers = config.headers;
@@ -201,9 +322,22 @@ module.exports = function httpAdapter(config) {
201
322
  }
202
323
 
203
324
  // support for https://www.npmjs.com/package/form-data api
204
- if (utils.isFormData(data) && utils.isFunction(data.getHeaders) &&
205
- data.getHeaders !== Object.prototype.getHeaders) {
206
- Object.assign(headers, data.getHeaders());
325
+ if (
326
+ utils.isFormData(data) &&
327
+ utils.isFunction(data.getHeaders) &&
328
+ data.getHeaders !== Object.prototype.getHeaders
329
+ ) {
330
+ var formHeaders = data.getHeaders();
331
+ if (config.formDataHeaderPolicy === 'content-only') {
332
+ Object.keys(formHeaders).forEach(function copyContentHeader(name) {
333
+ var lowerName = name.toLowerCase();
334
+ if (lowerName === 'content-type' || lowerName === 'content-length') {
335
+ headers[name] = formHeaders[name];
336
+ }
337
+ });
338
+ } else {
339
+ Object.assign(headers, formHeaders);
340
+ }
207
341
  } else if (data && !utils.isStream(data)) {
208
342
  if (Buffer.isBuffer(data)) {
209
343
  // Nothing to do...
@@ -212,19 +346,23 @@ module.exports = function httpAdapter(config) {
212
346
  } else if (utils.isString(data)) {
213
347
  data = Buffer.from(data, 'utf-8');
214
348
  } else {
215
- return reject(new AxiosError(
216
- 'Data after transformation must be a string, an ArrayBuffer, a Buffer, or a Stream',
217
- AxiosError.ERR_BAD_REQUEST,
218
- config
219
- ));
349
+ return reject(
350
+ new AxiosError(
351
+ 'Data after transformation must be a string, an ArrayBuffer, a Buffer, or a Stream',
352
+ AxiosError.ERR_BAD_REQUEST,
353
+ config
354
+ )
355
+ );
220
356
  }
221
357
 
222
358
  if (config.maxBodyLength > -1 && data.length > config.maxBodyLength) {
223
- return reject(new AxiosError(
224
- 'Request body larger than maxBodyLength limit',
225
- AxiosError.ERR_BAD_REQUEST,
226
- config
227
- ));
359
+ return reject(
360
+ new AxiosError(
361
+ 'Request body larger than maxBodyLength limit',
362
+ AxiosError.ERR_BAD_REQUEST,
363
+ config
364
+ )
365
+ );
228
366
  }
229
367
 
230
368
  // Add Content-Length header if data exists
@@ -253,7 +391,10 @@ module.exports = function httpAdapter(config) {
253
391
  }
254
392
 
255
393
  try {
256
- buildURL(parsed.path, config.params, config.paramsSerializer).replace(/^\?/, '');
394
+ buildURL(parsed.path, config.params, config.paramsSerializer).replace(
395
+ /^\?/,
396
+ ''
397
+ );
257
398
  } catch (err) {
258
399
  var customErr = new Error(err.message);
259
400
  customErr.config = config;
@@ -263,7 +404,11 @@ module.exports = function httpAdapter(config) {
263
404
  }
264
405
 
265
406
  var options = {
266
- path: buildURL(parsed.path, config.params, config.paramsSerializer).replace(/^\?/, ''),
407
+ path: buildURL(
408
+ parsed.path,
409
+ config.params,
410
+ config.paramsSerializer
411
+ ).replace(/^\?/, ''),
267
412
  method: method,
268
413
  headers: headers,
269
414
  agents: { http: config.httpAgent, https: config.httpsAgent },
@@ -273,12 +418,21 @@ module.exports = function httpAdapter(config) {
273
418
  beforeRedirects: {}
274
419
  };
275
420
 
421
+ var socketPathError = checkSocketPath(config);
422
+ if (socketPathError) {
423
+ return reject(socketPathError);
424
+ }
425
+
276
426
  if (config.socketPath) {
277
427
  options.socketPath = config.socketPath;
278
428
  } else {
279
429
  options.hostname = parsed.hostname;
280
430
  options.port = parsed.port;
281
- setProxy(options, config.proxy, protocol + '//' + parsed.host + options.path);
431
+ setProxy(
432
+ options,
433
+ config.proxy,
434
+ protocol + '//' + parsed.host + options.path
435
+ );
282
436
  }
283
437
 
284
438
  var transport;
@@ -350,7 +504,7 @@ module.exports = function httpAdapter(config) {
350
504
  };
351
505
 
352
506
  if (responseType === 'stream') {
353
- // Enforce maxContentLength on streamed responses too (GHSA-vf2m-468p-8v99).
507
+ // Enforce maxContentLength on streamed responses too.
354
508
  // Previously the stream path bypassed the size guard because the check only
355
509
  // ran on the buffering branch.
356
510
  if (config.maxContentLength > -1) {
@@ -360,12 +514,16 @@ module.exports = function httpAdapter(config) {
360
514
  transform: function transformChunk(chunk, encoding, callback) {
361
515
  streamedBytes += chunk.length;
362
516
  if (streamedBytes > maxContentLength) {
363
- callback(new AxiosError(
364
- 'maxContentLength size of ' + maxContentLength + ' exceeded',
365
- AxiosError.ERR_BAD_RESPONSE,
366
- config,
367
- lastRequest
368
- ));
517
+ callback(
518
+ new AxiosError(
519
+ 'maxContentLength size of ' +
520
+ maxContentLength +
521
+ ' exceeded',
522
+ AxiosError.ERR_BAD_RESPONSE,
523
+ config,
524
+ lastRequest
525
+ )
526
+ );
369
527
  return;
370
528
  }
371
529
  callback(null, chunk);
@@ -399,12 +557,23 @@ module.exports = function httpAdapter(config) {
399
557
  totalResponseBytes += chunk.length;
400
558
 
401
559
  // make sure the content length is not over the maxContentLength if specified
402
- if (config.maxContentLength > -1 && totalResponseBytes > config.maxContentLength) {
560
+ if (
561
+ config.maxContentLength > -1 &&
562
+ totalResponseBytes > config.maxContentLength
563
+ ) {
403
564
  // stream.destroy() emit aborted event before calling reject() on Node.js v16
404
565
  rejected = true;
405
566
  responseStream.destroy();
406
- reject(new AxiosError('maxContentLength size of ' + config.maxContentLength + ' exceeded',
407
- AxiosError.ERR_BAD_RESPONSE, config, lastRequest));
567
+ reject(
568
+ new AxiosError(
569
+ 'maxContentLength size of ' +
570
+ config.maxContentLength +
571
+ ' exceeded',
572
+ AxiosError.ERR_BAD_RESPONSE,
573
+ config,
574
+ lastRequest
575
+ )
576
+ );
408
577
  }
409
578
  });
410
579
 
@@ -413,12 +582,14 @@ module.exports = function httpAdapter(config) {
413
582
  return;
414
583
  }
415
584
  responseStream.destroy();
416
- reject(new AxiosError(
417
- 'response stream aborted',
418
- AxiosError.ECONNABORTED,
419
- config,
420
- lastRequest
421
- ));
585
+ reject(
586
+ new AxiosError(
587
+ 'response stream aborted',
588
+ AxiosError.ECONNABORTED,
589
+ config,
590
+ lastRequest
591
+ )
592
+ );
422
593
  });
423
594
 
424
595
  responseStream.on('error', function handleStreamError(err) {
@@ -428,7 +599,10 @@ module.exports = function httpAdapter(config) {
428
599
 
429
600
  responseStream.on('end', function handleStreamEnd() {
430
601
  try {
431
- var responseData = responseBuffer.length === 1 ? responseBuffer[0] : Buffer.concat(responseBuffer);
602
+ var responseData =
603
+ responseBuffer.length === 1
604
+ ? responseBuffer[0]
605
+ : Buffer.concat(responseBuffer);
432
606
  if (responseType !== 'arraybuffer') {
433
607
  responseData = responseData.toString(responseEncoding);
434
608
  if (!responseEncoding || responseEncoding === 'utf8') {
@@ -437,7 +611,9 @@ module.exports = function httpAdapter(config) {
437
611
  }
438
612
  response.data = responseData;
439
613
  } catch (err) {
440
- reject(AxiosError.from(err, null, config, response.request, response));
614
+ reject(
615
+ AxiosError.from(err, null, config, response.request, response)
616
+ );
441
617
  }
442
618
  settle(resolve, reject, response);
443
619
  });
@@ -459,16 +635,28 @@ module.exports = function httpAdapter(config) {
459
635
 
460
636
  // Handle request timeout
461
637
  if (config.timeout) {
462
- // This is forcing a int timeout to avoid problems if the `req` interface doesn't handle other types.
463
- var timeout = parseInt(config.timeout, 10);
638
+ // Force an int timeout so the `req` interface gets a clean number.
639
+ // The try/catch is required: merged config values have a null prototype,
640
+ // and parseInt on a null-prototype object throws "Cannot convert object
641
+ // to primitive value" because there is no inherited toString. Treating
642
+ // that as NaN routes to the same ERR_BAD_OPTION_VALUE rejection as any
643
+ // other unparsable value.
644
+ var timeout;
645
+ try {
646
+ timeout = parseInt(config.timeout, 10);
647
+ } catch (err) {
648
+ timeout = NaN;
649
+ }
464
650
 
465
651
  if (isNaN(timeout)) {
466
- reject(new AxiosError(
467
- 'error trying to parse `config.timeout` to int',
468
- AxiosError.ERR_BAD_OPTION_VALUE,
469
- config,
470
- req
471
- ));
652
+ reject(
653
+ new AxiosError(
654
+ 'error trying to parse `config.timeout` to int',
655
+ AxiosError.ERR_BAD_OPTION_VALUE,
656
+ config,
657
+ req
658
+ )
659
+ );
472
660
 
473
661
  return;
474
662
  }
@@ -480,17 +668,23 @@ module.exports = function httpAdapter(config) {
480
668
  // ClientRequest.setTimeout will be fired on the specify milliseconds, and can make sure that abort() will be fired after connect.
481
669
  req.setTimeout(timeout, function handleRequestTimeout() {
482
670
  req.abort();
483
- var timeoutErrorMessage = config.timeout ? 'timeout of ' + config.timeout + 'ms exceeded' : 'timeout exceeded';
671
+ var timeoutErrorMessage = config.timeout
672
+ ? 'timeout of ' + config.timeout + 'ms exceeded'
673
+ : 'timeout exceeded';
484
674
  var transitional = config.transitional || transitionalDefaults;
485
675
  if (config.timeoutErrorMessage) {
486
676
  timeoutErrorMessage = config.timeoutErrorMessage;
487
677
  }
488
- reject(new AxiosError(
489
- timeoutErrorMessage,
490
- transitional.clarifyTimeoutError ? AxiosError.ETIMEDOUT : AxiosError.ECONNABORTED,
491
- config,
492
- req
493
- ));
678
+ reject(
679
+ new AxiosError(
680
+ timeoutErrorMessage,
681
+ transitional.clarifyTimeoutError
682
+ ? AxiosError.ETIMEDOUT
683
+ : AxiosError.ECONNABORTED,
684
+ config,
685
+ req
686
+ )
687
+ );
494
688
  });
495
689
  }
496
690
 
@@ -501,16 +695,21 @@ module.exports = function httpAdapter(config) {
501
695
  if (req.aborted) return;
502
696
 
503
697
  req.abort();
504
- reject(!cancel || cancel.type ? new CanceledError(null, config, req) : cancel);
698
+ reject(
699
+ !cancel || cancel.type
700
+ ? new CanceledError(null, config, req)
701
+ : cancel
702
+ );
505
703
  };
506
704
 
507
705
  config.cancelToken && config.cancelToken.subscribe(onCanceled);
508
706
  if (config.signal) {
509
- config.signal.aborted ? onCanceled() : config.signal.addEventListener('abort', onCanceled);
707
+ config.signal.aborted
708
+ ? onCanceled()
709
+ : config.signal.addEventListener('abort', onCanceled);
510
710
  }
511
711
  }
512
712
 
513
-
514
713
  // Send the request
515
714
  if (utils.isStream(data)) {
516
715
  data.on('error', function handleStreamError(err) {
@@ -519,7 +718,7 @@ module.exports = function httpAdapter(config) {
519
718
 
520
719
  // follow-redirects enforces options.maxBodyLength for stream uploads, but the
521
720
  // native http/https transport (used when maxRedirects === 0) does not.
522
- // Count bytes ourselves so the limit is always honored (GHSA-5c9x-8gcm-mpgx).
721
+ // Count bytes ourselves so the limit is always honored.
523
722
  var nativeTransport = transport === http || transport === https;
524
723
  if (nativeTransport && config.maxBodyLength > -1) {
525
724
  var maxBodyLength = config.maxBodyLength;
@@ -528,12 +727,14 @@ module.exports = function httpAdapter(config) {
528
727
  transform: function transformChunk(chunk, encoding, callback) {
529
728
  uploadedBytes += chunk.length;
530
729
  if (uploadedBytes > maxBodyLength) {
531
- callback(new AxiosError(
532
- 'Request body larger than maxBodyLength limit',
533
- AxiosError.ERR_BAD_REQUEST,
534
- config,
535
- req
536
- ));
730
+ callback(
731
+ new AxiosError(
732
+ 'Request body larger than maxBodyLength limit',
733
+ AxiosError.ERR_BAD_REQUEST,
734
+ config,
735
+ req
736
+ )
737
+ );
537
738
  return;
538
739
  }
539
740
  callback(null, chunk);
@@ -542,8 +743,16 @@ module.exports = function httpAdapter(config) {
542
743
  bodyLimiter.on('error', function handleLimiterError(err) {
543
744
  if (rejected) return;
544
745
  rejected = true;
545
- try { data.unpipe(bodyLimiter); } catch (e) { /* noop */ }
546
- try { bodyLimiter.unpipe(req); } catch (e) { /* noop */ }
746
+ try {
747
+ data.unpipe(bodyLimiter);
748
+ } catch (e) {
749
+ /* noop */
750
+ }
751
+ try {
752
+ bodyLimiter.unpipe(req);
753
+ } catch (e) {
754
+ /* noop */
755
+ }
547
756
  req.destroy();
548
757
  reject(err);
549
758
  });