axios 0.31.1 → 0.33.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
@@ -235,9 +373,10 @@ module.exports = function httpAdapter(config) {
235
373
 
236
374
  // HTTP basic authentication
237
375
  var auth = undefined;
238
- if (config.auth) {
239
- var username = config.auth.username || '';
240
- var password = config.auth.password || '';
376
+ var configAuth = utils.hasOwnProperty(config, 'auth') ? config.auth : undefined;
377
+ if (configAuth) {
378
+ var username = utils.hasOwnProperty(configAuth, 'username') ? configAuth.username || '' : '';
379
+ var password = utils.hasOwnProperty(configAuth, 'password') ? configAuth.password || '' : '';
241
380
  auth = username + ':' + password;
242
381
  }
243
382
 
@@ -252,8 +391,13 @@ module.exports = function httpAdapter(config) {
252
391
  delete headers[headerNames.authorization];
253
392
  }
254
393
 
394
+ var paramsSerializer = utils.hasOwnProperty(config, 'paramsSerializer') ? config.paramsSerializer : undefined;
395
+
255
396
  try {
256
- buildURL(parsed.path, config.params, config.paramsSerializer).replace(/^\?/, '');
397
+ buildURL(parsed.path, config.params, paramsSerializer).replace(
398
+ /^\?/,
399
+ ''
400
+ );
257
401
  } catch (err) {
258
402
  var customErr = new Error(err.message);
259
403
  customErr.config = config;
@@ -263,7 +407,11 @@ module.exports = function httpAdapter(config) {
263
407
  }
264
408
 
265
409
  var options = {
266
- path: buildURL(parsed.path, config.params, config.paramsSerializer).replace(/^\?/, ''),
410
+ path: buildURL(
411
+ parsed.path,
412
+ config.params,
413
+ paramsSerializer
414
+ ).replace(/^\?/, ''),
267
415
  method: method,
268
416
  headers: headers,
269
417
  agents: { http: config.httpAgent, https: config.httpsAgent },
@@ -273,12 +421,22 @@ module.exports = function httpAdapter(config) {
273
421
  beforeRedirects: {}
274
422
  };
275
423
 
424
+ var socketPathError = checkSocketPath(config);
425
+ if (socketPathError) {
426
+ return reject(socketPathError);
427
+ }
428
+
276
429
  if (config.socketPath) {
277
430
  options.socketPath = config.socketPath;
278
431
  } else {
279
432
  options.hostname = parsed.hostname;
280
433
  options.port = parsed.port;
281
- setProxy(options, config.proxy, protocol + '//' + parsed.host + options.path);
434
+ var configProxy = utils.hasOwnProperty(config, 'proxy') ? config.proxy : undefined;
435
+ setProxy(
436
+ options,
437
+ configProxy,
438
+ protocol + '//' + parsed.host + options.path
439
+ );
282
440
  }
283
441
 
284
442
  var transport;
@@ -350,7 +508,7 @@ module.exports = function httpAdapter(config) {
350
508
  };
351
509
 
352
510
  if (responseType === 'stream') {
353
- // Enforce maxContentLength on streamed responses too (GHSA-vf2m-468p-8v99).
511
+ // Enforce maxContentLength on streamed responses too.
354
512
  // Previously the stream path bypassed the size guard because the check only
355
513
  // ran on the buffering branch.
356
514
  if (config.maxContentLength > -1) {
@@ -360,12 +518,16 @@ module.exports = function httpAdapter(config) {
360
518
  transform: function transformChunk(chunk, encoding, callback) {
361
519
  streamedBytes += chunk.length;
362
520
  if (streamedBytes > maxContentLength) {
363
- callback(new AxiosError(
364
- 'maxContentLength size of ' + maxContentLength + ' exceeded',
365
- AxiosError.ERR_BAD_RESPONSE,
366
- config,
367
- lastRequest
368
- ));
521
+ callback(
522
+ new AxiosError(
523
+ 'maxContentLength size of ' +
524
+ maxContentLength +
525
+ ' exceeded',
526
+ AxiosError.ERR_BAD_RESPONSE,
527
+ config,
528
+ lastRequest
529
+ )
530
+ );
369
531
  return;
370
532
  }
371
533
  callback(null, chunk);
@@ -399,12 +561,23 @@ module.exports = function httpAdapter(config) {
399
561
  totalResponseBytes += chunk.length;
400
562
 
401
563
  // make sure the content length is not over the maxContentLength if specified
402
- if (config.maxContentLength > -1 && totalResponseBytes > config.maxContentLength) {
564
+ if (
565
+ config.maxContentLength > -1 &&
566
+ totalResponseBytes > config.maxContentLength
567
+ ) {
403
568
  // stream.destroy() emit aborted event before calling reject() on Node.js v16
404
569
  rejected = true;
405
570
  responseStream.destroy();
406
- reject(new AxiosError('maxContentLength size of ' + config.maxContentLength + ' exceeded',
407
- AxiosError.ERR_BAD_RESPONSE, config, lastRequest));
571
+ reject(
572
+ new AxiosError(
573
+ 'maxContentLength size of ' +
574
+ config.maxContentLength +
575
+ ' exceeded',
576
+ AxiosError.ERR_BAD_RESPONSE,
577
+ config,
578
+ lastRequest
579
+ )
580
+ );
408
581
  }
409
582
  });
410
583
 
@@ -413,12 +586,14 @@ module.exports = function httpAdapter(config) {
413
586
  return;
414
587
  }
415
588
  responseStream.destroy();
416
- reject(new AxiosError(
417
- 'response stream aborted',
418
- AxiosError.ECONNABORTED,
419
- config,
420
- lastRequest
421
- ));
589
+ reject(
590
+ new AxiosError(
591
+ 'response stream aborted',
592
+ AxiosError.ECONNABORTED,
593
+ config,
594
+ lastRequest
595
+ )
596
+ );
422
597
  });
423
598
 
424
599
  responseStream.on('error', function handleStreamError(err) {
@@ -428,7 +603,10 @@ module.exports = function httpAdapter(config) {
428
603
 
429
604
  responseStream.on('end', function handleStreamEnd() {
430
605
  try {
431
- var responseData = responseBuffer.length === 1 ? responseBuffer[0] : Buffer.concat(responseBuffer);
606
+ var responseData =
607
+ responseBuffer.length === 1
608
+ ? responseBuffer[0]
609
+ : Buffer.concat(responseBuffer);
432
610
  if (responseType !== 'arraybuffer') {
433
611
  responseData = responseData.toString(responseEncoding);
434
612
  if (!responseEncoding || responseEncoding === 'utf8') {
@@ -437,7 +615,9 @@ module.exports = function httpAdapter(config) {
437
615
  }
438
616
  response.data = responseData;
439
617
  } catch (err) {
440
- reject(AxiosError.from(err, null, config, response.request, response));
618
+ reject(
619
+ AxiosError.from(err, null, config, response.request, response)
620
+ );
441
621
  }
442
622
  settle(resolve, reject, response);
443
623
  });
@@ -459,16 +639,28 @@ module.exports = function httpAdapter(config) {
459
639
 
460
640
  // Handle request timeout
461
641
  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);
642
+ // Force an int timeout so the `req` interface gets a clean number.
643
+ // The try/catch is required: merged config values have a null prototype,
644
+ // and parseInt on a null-prototype object throws "Cannot convert object
645
+ // to primitive value" because there is no inherited toString. Treating
646
+ // that as NaN routes to the same ERR_BAD_OPTION_VALUE rejection as any
647
+ // other unparsable value.
648
+ var timeout;
649
+ try {
650
+ timeout = parseInt(config.timeout, 10);
651
+ } catch (err) {
652
+ timeout = NaN;
653
+ }
464
654
 
465
655
  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
- ));
656
+ reject(
657
+ new AxiosError(
658
+ 'error trying to parse `config.timeout` to int',
659
+ AxiosError.ERR_BAD_OPTION_VALUE,
660
+ config,
661
+ req
662
+ )
663
+ );
472
664
 
473
665
  return;
474
666
  }
@@ -480,17 +672,23 @@ module.exports = function httpAdapter(config) {
480
672
  // ClientRequest.setTimeout will be fired on the specify milliseconds, and can make sure that abort() will be fired after connect.
481
673
  req.setTimeout(timeout, function handleRequestTimeout() {
482
674
  req.abort();
483
- var timeoutErrorMessage = config.timeout ? 'timeout of ' + config.timeout + 'ms exceeded' : 'timeout exceeded';
675
+ var timeoutErrorMessage = config.timeout
676
+ ? 'timeout of ' + config.timeout + 'ms exceeded'
677
+ : 'timeout exceeded';
484
678
  var transitional = config.transitional || transitionalDefaults;
485
679
  if (config.timeoutErrorMessage) {
486
680
  timeoutErrorMessage = config.timeoutErrorMessage;
487
681
  }
488
- reject(new AxiosError(
489
- timeoutErrorMessage,
490
- transitional.clarifyTimeoutError ? AxiosError.ETIMEDOUT : AxiosError.ECONNABORTED,
491
- config,
492
- req
493
- ));
682
+ reject(
683
+ new AxiosError(
684
+ timeoutErrorMessage,
685
+ transitional.clarifyTimeoutError
686
+ ? AxiosError.ETIMEDOUT
687
+ : AxiosError.ECONNABORTED,
688
+ config,
689
+ req
690
+ )
691
+ );
494
692
  });
495
693
  }
496
694
 
@@ -501,16 +699,21 @@ module.exports = function httpAdapter(config) {
501
699
  if (req.aborted) return;
502
700
 
503
701
  req.abort();
504
- reject(!cancel || cancel.type ? new CanceledError(null, config, req) : cancel);
702
+ reject(
703
+ !cancel || cancel.type
704
+ ? new CanceledError(null, config, req)
705
+ : cancel
706
+ );
505
707
  };
506
708
 
507
709
  config.cancelToken && config.cancelToken.subscribe(onCanceled);
508
710
  if (config.signal) {
509
- config.signal.aborted ? onCanceled() : config.signal.addEventListener('abort', onCanceled);
711
+ config.signal.aborted
712
+ ? onCanceled()
713
+ : config.signal.addEventListener('abort', onCanceled);
510
714
  }
511
715
  }
512
716
 
513
-
514
717
  // Send the request
515
718
  if (utils.isStream(data)) {
516
719
  data.on('error', function handleStreamError(err) {
@@ -519,7 +722,7 @@ module.exports = function httpAdapter(config) {
519
722
 
520
723
  // follow-redirects enforces options.maxBodyLength for stream uploads, but the
521
724
  // native http/https transport (used when maxRedirects === 0) does not.
522
- // Count bytes ourselves so the limit is always honored (GHSA-5c9x-8gcm-mpgx).
725
+ // Count bytes ourselves so the limit is always honored.
523
726
  var nativeTransport = transport === http || transport === https;
524
727
  if (nativeTransport && config.maxBodyLength > -1) {
525
728
  var maxBodyLength = config.maxBodyLength;
@@ -528,12 +731,14 @@ module.exports = function httpAdapter(config) {
528
731
  transform: function transformChunk(chunk, encoding, callback) {
529
732
  uploadedBytes += chunk.length;
530
733
  if (uploadedBytes > maxBodyLength) {
531
- callback(new AxiosError(
532
- 'Request body larger than maxBodyLength limit',
533
- AxiosError.ERR_BAD_REQUEST,
534
- config,
535
- req
536
- ));
734
+ callback(
735
+ new AxiosError(
736
+ 'Request body larger than maxBodyLength limit',
737
+ AxiosError.ERR_BAD_REQUEST,
738
+ config,
739
+ req
740
+ )
741
+ );
537
742
  return;
538
743
  }
539
744
  callback(null, chunk);
@@ -542,8 +747,16 @@ module.exports = function httpAdapter(config) {
542
747
  bodyLimiter.on('error', function handleLimiterError(err) {
543
748
  if (rejected) return;
544
749
  rejected = true;
545
- try { data.unpipe(bodyLimiter); } catch (e) { /* noop */ }
546
- try { bodyLimiter.unpipe(req); } catch (e) { /* noop */ }
750
+ try {
751
+ data.unpipe(bodyLimiter);
752
+ } catch (e) {
753
+ /* noop */
754
+ }
755
+ try {
756
+ bodyLimiter.unpipe(req);
757
+ } catch (e) {
758
+ /* noop */
759
+ }
547
760
  req.destroy();
548
761
  reject(err);
549
762
  });