axios 1.17.0 → 1.18.1
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/CHANGELOG.md +84 -1
- package/README.md +155 -22
- package/dist/axios.js +407 -142
- package/dist/axios.min.js +3 -3
- package/dist/axios.min.js.map +1 -1
- package/dist/browser/axios.cjs +422 -115
- package/dist/esm/axios.js +422 -115
- package/dist/esm/axios.min.js +2 -2
- package/dist/esm/axios.min.js.map +1 -1
- package/dist/node/axios.cjs +515 -130
- package/index.d.cts +19 -1
- package/index.d.ts +19 -1
- package/lib/adapters/adapters.js +1 -1
- package/lib/adapters/fetch.js +140 -49
- package/lib/adapters/http.js +215 -54
- package/lib/adapters/xhr.js +1 -0
- package/lib/core/Axios.js +3 -2
- package/lib/core/AxiosError.js +13 -1
- package/lib/core/AxiosHeaders.js +10 -7
- package/lib/core/buildFullPath.js +29 -1
- package/lib/core/mergeConfig.js +35 -0
- package/lib/defaults/transitional.js +1 -0
- package/lib/env/data.js +1 -1
- package/lib/helpers/AxiosURLSearchParams.js +1 -3
- package/lib/helpers/buildURL.js +6 -3
- package/lib/helpers/composeSignals.js +1 -1
- package/lib/helpers/cookies.js +5 -1
- package/lib/helpers/estimateDataURLDecodedBytes.js +16 -11
- package/lib/helpers/formDataToJSON.js +25 -3
- package/lib/helpers/fromDataURI.js +4 -2
- package/lib/helpers/resolveConfig.js +14 -7
- package/lib/helpers/shouldBypassProxy.js +33 -1
- package/lib/helpers/toFormData.js +47 -11
- package/lib/helpers/validator.js +1 -1
- package/lib/utils.js +75 -11
- package/package.json +2 -2
package/dist/node/axios.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! Axios v1.
|
|
1
|
+
/*! Axios v1.18.1 Copyright (c) 2026 Matt Zabriskie and contributors */
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
4
|
var FormData$1 = require('form-data');
|
|
@@ -40,6 +40,52 @@ const {
|
|
|
40
40
|
iterator,
|
|
41
41
|
toStringTag
|
|
42
42
|
} = Symbol;
|
|
43
|
+
|
|
44
|
+
/* Creating a function that will check if an object has a property. */
|
|
45
|
+
const hasOwnProperty = (({
|
|
46
|
+
hasOwnProperty
|
|
47
|
+
}) => (obj, prop) => hasOwnProperty.call(obj, prop))(Object.prototype);
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Walk the prototype chain (excluding the shared Object.prototype) looking for
|
|
51
|
+
* an own `prop`. This distinguishes genuine own/inherited members — including
|
|
52
|
+
* class accessors and template prototypes — from members injected via
|
|
53
|
+
* Object.prototype pollution (e.g. `Object.prototype.username = '...'`), which
|
|
54
|
+
* live on Object.prototype itself and are therefore never matched.
|
|
55
|
+
*
|
|
56
|
+
* @param {*} thing The value whose chain to inspect
|
|
57
|
+
* @param {string|symbol} prop The property key to look for
|
|
58
|
+
*
|
|
59
|
+
* @returns {boolean} True when `prop` is owned below Object.prototype
|
|
60
|
+
*/
|
|
61
|
+
const hasOwnInPrototypeChain = (thing, prop) => {
|
|
62
|
+
let obj = thing;
|
|
63
|
+
const seen = [];
|
|
64
|
+
while (obj != null && obj !== Object.prototype) {
|
|
65
|
+
if (seen.indexOf(obj) !== -1) {
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
seen.push(obj);
|
|
69
|
+
if (hasOwnProperty(obj, prop)) {
|
|
70
|
+
return true;
|
|
71
|
+
}
|
|
72
|
+
obj = getPrototypeOf(obj);
|
|
73
|
+
}
|
|
74
|
+
return false;
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Read `obj[prop]` only when it is safe from Object.prototype pollution. Own
|
|
79
|
+
* properties and members inherited from a non-Object.prototype source (a class
|
|
80
|
+
* instance or template object) are honored; a value reachable only through a
|
|
81
|
+
* polluted Object.prototype is ignored and `undefined` is returned.
|
|
82
|
+
*
|
|
83
|
+
* @param {*} obj The source object
|
|
84
|
+
* @param {string|symbol} prop The property key to read
|
|
85
|
+
*
|
|
86
|
+
* @returns {*} The resolved value, or undefined when unsafe/absent
|
|
87
|
+
*/
|
|
88
|
+
const getSafeProp = (obj, prop) => obj != null && hasOwnInPrototypeChain(obj, prop) ? obj[prop] : undefined;
|
|
43
89
|
const kindOf = (cache => thing => {
|
|
44
90
|
const str = toString.call(thing);
|
|
45
91
|
return cache[str] || (cache[str] = str.slice(8, -1).toLowerCase());
|
|
@@ -158,11 +204,15 @@ const isBoolean = thing => thing === true || thing === false;
|
|
|
158
204
|
* @returns {boolean} True if value is a plain Object, otherwise false
|
|
159
205
|
*/
|
|
160
206
|
const isPlainObject = val => {
|
|
161
|
-
if (
|
|
207
|
+
if (!isObject(val)) {
|
|
162
208
|
return false;
|
|
163
209
|
}
|
|
164
210
|
const prototype = getPrototypeOf(val);
|
|
165
|
-
return (prototype === null || prototype === Object.prototype ||
|
|
211
|
+
return (prototype === null || prototype === Object.prototype || getPrototypeOf(prototype) === null) &&
|
|
212
|
+
// Treat any genuine (non-Object.prototype-polluted) Symbol.toStringTag or
|
|
213
|
+
// Symbol.iterator as evidence the value is a tagged/iterable type rather
|
|
214
|
+
// than a plain object, while ignoring keys injected onto Object.prototype.
|
|
215
|
+
!hasOwnInPrototypeChain(val, toStringTag) && !hasOwnInPrototypeChain(val, iterator);
|
|
166
216
|
};
|
|
167
217
|
|
|
168
218
|
/**
|
|
@@ -662,11 +712,6 @@ const toCamelCase = str => {
|
|
|
662
712
|
return p1.toUpperCase() + p2;
|
|
663
713
|
});
|
|
664
714
|
};
|
|
665
|
-
|
|
666
|
-
/* Creating a function that will check if an object has a property. */
|
|
667
|
-
const hasOwnProperty = (({
|
|
668
|
-
hasOwnProperty
|
|
669
|
-
}) => (obj, prop) => hasOwnProperty.call(obj, prop))(Object.prototype);
|
|
670
715
|
const {
|
|
671
716
|
propertyIsEnumerable
|
|
672
717
|
} = Object.prototype;
|
|
@@ -844,6 +889,19 @@ const asap = typeof queueMicrotask !== 'undefined' ? queueMicrotask.bind(_global
|
|
|
844
889
|
// *********************
|
|
845
890
|
|
|
846
891
|
const isIterable = thing => thing != null && isFunction$1(thing[iterator]);
|
|
892
|
+
|
|
893
|
+
/**
|
|
894
|
+
* Determine if a value is iterable via an iterator that is NOT sourced solely
|
|
895
|
+
* from a polluted Object.prototype. Use this instead of `isIterable` whenever
|
|
896
|
+
* the iterable comes from untrusted input (e.g. user-supplied header sources),
|
|
897
|
+
* so `Object.prototype[Symbol.iterator] = ...` cannot turn an ordinary object
|
|
898
|
+
* into an attacker-controlled entries iterator.
|
|
899
|
+
*
|
|
900
|
+
* @param {*} thing The value to test
|
|
901
|
+
*
|
|
902
|
+
* @returns {boolean} True if value has a non-polluted iterator
|
|
903
|
+
*/
|
|
904
|
+
const isSafeIterable = thing => thing != null && hasOwnInPrototypeChain(thing, iterator) && isIterable(thing);
|
|
847
905
|
var utils$1 = {
|
|
848
906
|
isArray,
|
|
849
907
|
isArrayBuffer,
|
|
@@ -889,6 +947,8 @@ var utils$1 = {
|
|
|
889
947
|
hasOwnProperty,
|
|
890
948
|
hasOwnProp: hasOwnProperty,
|
|
891
949
|
// an alias to avoid ESLint no-prototype-builtins detection
|
|
950
|
+
hasOwnInPrototypeChain,
|
|
951
|
+
getSafeProp,
|
|
892
952
|
reduceDescriptors,
|
|
893
953
|
freezeMethods,
|
|
894
954
|
toObjectSet,
|
|
@@ -904,7 +964,8 @@ var utils$1 = {
|
|
|
904
964
|
isThenable,
|
|
905
965
|
setImmediate: _setImmediate,
|
|
906
966
|
asap,
|
|
907
|
-
isIterable
|
|
967
|
+
isIterable,
|
|
968
|
+
isSafeIterable
|
|
908
969
|
};
|
|
909
970
|
|
|
910
971
|
// RawAxiosHeaders whose duplicates are ignored by node
|
|
@@ -1066,15 +1127,21 @@ class AxiosHeaders {
|
|
|
1066
1127
|
setHeaders(header, valueOrRewrite);
|
|
1067
1128
|
} else if (utils$1.isString(header) && (header = header.trim()) && !isValidHeaderName(header)) {
|
|
1068
1129
|
setHeaders(parseHeaders(header), valueOrRewrite);
|
|
1069
|
-
} else if (utils$1.isObject(header) && utils$1.
|
|
1070
|
-
let obj =
|
|
1130
|
+
} else if (utils$1.isObject(header) && utils$1.isSafeIterable(header)) {
|
|
1131
|
+
let obj = Object.create(null),
|
|
1071
1132
|
dest,
|
|
1072
1133
|
key;
|
|
1073
1134
|
for (const entry of header) {
|
|
1074
1135
|
if (!utils$1.isArray(entry)) {
|
|
1075
1136
|
throw new TypeError('Object iterator must return a key-value pair');
|
|
1076
1137
|
}
|
|
1077
|
-
|
|
1138
|
+
key = entry[0];
|
|
1139
|
+
if (utils$1.hasOwnProp(obj, key)) {
|
|
1140
|
+
dest = obj[key];
|
|
1141
|
+
obj[key] = utils$1.isArray(dest) ? [...dest, entry[1]] : [dest, entry[1]];
|
|
1142
|
+
} else {
|
|
1143
|
+
obj[key] = entry[1];
|
|
1144
|
+
}
|
|
1078
1145
|
}
|
|
1079
1146
|
setHeaders(obj, valueOrRewrite);
|
|
1080
1147
|
} else {
|
|
@@ -1286,7 +1353,19 @@ function redactConfig(config, redactKeys) {
|
|
|
1286
1353
|
class AxiosError extends Error {
|
|
1287
1354
|
static from(error, code, config, request, response, customProps) {
|
|
1288
1355
|
const axiosError = new AxiosError(error.message, code || error.code, config, request, response);
|
|
1289
|
-
|
|
1356
|
+
// Match native `Error` `cause` semantics: non-enumerable. The wrapped
|
|
1357
|
+
// error often carries circular internals (sockets, requests, agents), so
|
|
1358
|
+
// an enumerable `cause` makes structured loggers (pino/winston) and any
|
|
1359
|
+
// own-property walk throw "Converting circular structure to JSON".
|
|
1360
|
+
// Regression from #6982; see #7205. `__proto__: null` mirrors the
|
|
1361
|
+
// `message` descriptor below (prototype-pollution-safe descriptor).
|
|
1362
|
+
Object.defineProperty(axiosError, 'cause', {
|
|
1363
|
+
__proto__: null,
|
|
1364
|
+
value: error,
|
|
1365
|
+
writable: true,
|
|
1366
|
+
enumerable: false,
|
|
1367
|
+
configurable: true
|
|
1368
|
+
});
|
|
1290
1369
|
axiosError.name = error.name;
|
|
1291
1370
|
|
|
1292
1371
|
// Preserve status from the original error if not already set from response
|
|
@@ -1377,6 +1456,10 @@ AxiosError.ERR_NOT_SUPPORT = 'ERR_NOT_SUPPORT';
|
|
|
1377
1456
|
AxiosError.ERR_INVALID_URL = 'ERR_INVALID_URL';
|
|
1378
1457
|
AxiosError.ERR_FORM_DATA_DEPTH_EXCEEDED = 'ERR_FORM_DATA_DEPTH_EXCEEDED';
|
|
1379
1458
|
|
|
1459
|
+
// Default nesting limit shared with the inverse transform (formDataToJSON) so
|
|
1460
|
+
// the FormData <-> JSON round-trip stays symmetric.
|
|
1461
|
+
const DEFAULT_FORM_DATA_MAX_DEPTH = 100;
|
|
1462
|
+
|
|
1380
1463
|
/**
|
|
1381
1464
|
* Determines if the given thing is a array or js object.
|
|
1382
1465
|
*
|
|
@@ -1477,8 +1560,9 @@ function toFormData(obj, formData, options) {
|
|
|
1477
1560
|
const dots = options.dots;
|
|
1478
1561
|
const indexes = options.indexes;
|
|
1479
1562
|
const _Blob = options.Blob || typeof Blob !== 'undefined' && Blob;
|
|
1480
|
-
const maxDepth = options.maxDepth === undefined ?
|
|
1563
|
+
const maxDepth = options.maxDepth === undefined ? DEFAULT_FORM_DATA_MAX_DEPTH : options.maxDepth;
|
|
1481
1564
|
const useBlob = _Blob && utils$1.isSpecCompliantForm(formData);
|
|
1565
|
+
const stack = [];
|
|
1482
1566
|
if (!utils$1.isFunction(visitor)) {
|
|
1483
1567
|
throw new TypeError('visitor must be a function');
|
|
1484
1568
|
}
|
|
@@ -1494,10 +1578,38 @@ function toFormData(obj, formData, options) {
|
|
|
1494
1578
|
throw new AxiosError('Blob is not supported. Use a Buffer instead.');
|
|
1495
1579
|
}
|
|
1496
1580
|
if (utils$1.isArrayBuffer(value) || utils$1.isTypedArray(value)) {
|
|
1497
|
-
|
|
1581
|
+
if (useBlob && typeof _Blob === 'function') {
|
|
1582
|
+
return new _Blob([value]);
|
|
1583
|
+
}
|
|
1584
|
+
if (typeof Buffer !== 'undefined') {
|
|
1585
|
+
return Buffer.from(value);
|
|
1586
|
+
}
|
|
1587
|
+
throw new AxiosError('Blob is not supported. Use a Buffer instead.', AxiosError.ERR_NOT_SUPPORT);
|
|
1498
1588
|
}
|
|
1499
1589
|
return value;
|
|
1500
1590
|
}
|
|
1591
|
+
function throwIfMaxDepthExceeded(depth) {
|
|
1592
|
+
if (depth > maxDepth) {
|
|
1593
|
+
throw new AxiosError('Object is too deeply nested (' + depth + ' levels). Max depth: ' + maxDepth, AxiosError.ERR_FORM_DATA_DEPTH_EXCEEDED);
|
|
1594
|
+
}
|
|
1595
|
+
}
|
|
1596
|
+
function stringifyWithDepthLimit(value, depth) {
|
|
1597
|
+
if (maxDepth === Infinity) {
|
|
1598
|
+
return JSON.stringify(value);
|
|
1599
|
+
}
|
|
1600
|
+
const ancestors = [];
|
|
1601
|
+
return JSON.stringify(value, function limitDepth(_key, currentValue) {
|
|
1602
|
+
if (!utils$1.isObject(currentValue)) {
|
|
1603
|
+
return currentValue;
|
|
1604
|
+
}
|
|
1605
|
+
while (ancestors.length && ancestors[ancestors.length - 1] !== this) {
|
|
1606
|
+
ancestors.pop();
|
|
1607
|
+
}
|
|
1608
|
+
ancestors.push(currentValue);
|
|
1609
|
+
throwIfMaxDepthExceeded(depth + ancestors.length - 1);
|
|
1610
|
+
return currentValue;
|
|
1611
|
+
});
|
|
1612
|
+
}
|
|
1501
1613
|
|
|
1502
1614
|
/**
|
|
1503
1615
|
* Default visitor.
|
|
@@ -1520,7 +1632,7 @@ function toFormData(obj, formData, options) {
|
|
|
1520
1632
|
// eslint-disable-next-line no-param-reassign
|
|
1521
1633
|
key = metaTokens ? key : key.slice(0, -2);
|
|
1522
1634
|
// eslint-disable-next-line no-param-reassign
|
|
1523
|
-
value =
|
|
1635
|
+
value = stringifyWithDepthLimit(value, 1);
|
|
1524
1636
|
} else if (utils$1.isArray(value) && isFlatArray(value) || (utils$1.isFileList(value) || utils$1.endsWith(key, '[]')) && (arr = utils$1.toArray(value))) {
|
|
1525
1637
|
// eslint-disable-next-line no-param-reassign
|
|
1526
1638
|
key = removeBrackets(key);
|
|
@@ -1538,7 +1650,6 @@ function toFormData(obj, formData, options) {
|
|
|
1538
1650
|
formData.append(renderKey(path, key, dots), convertValue(value));
|
|
1539
1651
|
return false;
|
|
1540
1652
|
}
|
|
1541
|
-
const stack = [];
|
|
1542
1653
|
const exposedHelpers = Object.assign(predicates, {
|
|
1543
1654
|
defaultVisitor,
|
|
1544
1655
|
convertValue,
|
|
@@ -1546,9 +1657,7 @@ function toFormData(obj, formData, options) {
|
|
|
1546
1657
|
});
|
|
1547
1658
|
function build(value, path, depth = 0) {
|
|
1548
1659
|
if (utils$1.isUndefined(value)) return;
|
|
1549
|
-
|
|
1550
|
-
throw new AxiosError('Object is too deeply nested (' + depth + ' levels). Max depth: ' + maxDepth, AxiosError.ERR_FORM_DATA_DEPTH_EXCEEDED);
|
|
1551
|
-
}
|
|
1660
|
+
throwIfMaxDepthExceeded(depth);
|
|
1552
1661
|
if (stack.indexOf(value) !== -1) {
|
|
1553
1662
|
throw new Error('Circular reference detected in ' + path.join('.'));
|
|
1554
1663
|
}
|
|
@@ -1607,9 +1716,7 @@ prototype.append = function append(name, value) {
|
|
|
1607
1716
|
this._pairs.push([name, value]);
|
|
1608
1717
|
};
|
|
1609
1718
|
prototype.toString = function toString(encoder) {
|
|
1610
|
-
const _encode = encoder ?
|
|
1611
|
-
return encoder.call(this, value, encode$1);
|
|
1612
|
-
} : encode$1;
|
|
1719
|
+
const _encode = encoder ? value => encoder.call(this, value, encode$1) : encode$1;
|
|
1613
1720
|
return this._pairs.map(function each(pair) {
|
|
1614
1721
|
return _encode(pair[0]) + '=' + _encode(pair[1]);
|
|
1615
1722
|
}, '').join('&');
|
|
@@ -1640,11 +1747,16 @@ function buildURL(url, params, options) {
|
|
|
1640
1747
|
if (!params) {
|
|
1641
1748
|
return url;
|
|
1642
1749
|
}
|
|
1643
|
-
|
|
1750
|
+
url = url || '';
|
|
1644
1751
|
const _options = utils$1.isFunction(options) ? {
|
|
1645
1752
|
serialize: options
|
|
1646
1753
|
} : options;
|
|
1647
|
-
|
|
1754
|
+
|
|
1755
|
+
// Read serializer options pollution-safely: own properties and methods on a
|
|
1756
|
+
// class/template prototype are honored, but values injected onto a polluted
|
|
1757
|
+
// Object.prototype are ignored.
|
|
1758
|
+
const _encode = utils$1.getSafeProp(_options, 'encode') || encode;
|
|
1759
|
+
const serializeFn = utils$1.getSafeProp(_options, 'serialize');
|
|
1648
1760
|
let serializedParams;
|
|
1649
1761
|
if (serializeFn) {
|
|
1650
1762
|
serializedParams = serializeFn(params, _options);
|
|
@@ -1733,7 +1845,8 @@ var transitionalDefaults = {
|
|
|
1733
1845
|
forcedJSONParsing: true,
|
|
1734
1846
|
clarifyTimeoutError: false,
|
|
1735
1847
|
legacyInterceptorReqResOrdering: true,
|
|
1736
|
-
advertiseZstdAcceptEncoding: false
|
|
1848
|
+
advertiseZstdAcceptEncoding: false,
|
|
1849
|
+
validateStatusUndefinedResolves: true
|
|
1737
1850
|
};
|
|
1738
1851
|
|
|
1739
1852
|
var URLSearchParams = url.URLSearchParams;
|
|
@@ -1834,6 +1947,13 @@ function toURLEncodedForm(data, options) {
|
|
|
1834
1947
|
});
|
|
1835
1948
|
}
|
|
1836
1949
|
|
|
1950
|
+
const MAX_DEPTH = DEFAULT_FORM_DATA_MAX_DEPTH;
|
|
1951
|
+
function throwIfDepthExceeded(index) {
|
|
1952
|
+
if (index > MAX_DEPTH) {
|
|
1953
|
+
throw new AxiosError('FormData field is too deeply nested (' + index + ' levels). Max depth: ' + MAX_DEPTH, AxiosError.ERR_FORM_DATA_DEPTH_EXCEEDED);
|
|
1954
|
+
}
|
|
1955
|
+
}
|
|
1956
|
+
|
|
1837
1957
|
/**
|
|
1838
1958
|
* It takes a string like `foo[x][y][z]` and returns an array like `['foo', 'x', 'y', 'z']
|
|
1839
1959
|
*
|
|
@@ -1846,9 +1966,14 @@ function parsePropPath(name) {
|
|
|
1846
1966
|
// foo.x.y.z
|
|
1847
1967
|
// foo-x-y-z
|
|
1848
1968
|
// foo x y z
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1969
|
+
const path = [];
|
|
1970
|
+
const pattern = /\w+|\[(\w*)]/g;
|
|
1971
|
+
let match;
|
|
1972
|
+
while ((match = pattern.exec(name)) !== null) {
|
|
1973
|
+
throwIfDepthExceeded(path.length);
|
|
1974
|
+
path.push(match[0] === '[]' ? '' : match[1] || match[0]);
|
|
1975
|
+
}
|
|
1976
|
+
return path;
|
|
1852
1977
|
}
|
|
1853
1978
|
|
|
1854
1979
|
/**
|
|
@@ -1880,6 +2005,7 @@ function arrayToObject(arr) {
|
|
|
1880
2005
|
*/
|
|
1881
2006
|
function formDataToJSON(formData) {
|
|
1882
2007
|
function buildPath(path, value, target, index) {
|
|
2008
|
+
throwIfDepthExceeded(index);
|
|
1883
2009
|
let name = path[index++];
|
|
1884
2010
|
if (name === '__proto__') return true;
|
|
1885
2011
|
const isNumericKey = Number.isFinite(+name);
|
|
@@ -2120,6 +2246,24 @@ function combineURLs(baseURL, relativeURL) {
|
|
|
2120
2246
|
return relativeURL ? baseURL.replace(/\/?\/$/, '') + '/' + relativeURL.replace(/^\/+/, '') : baseURL;
|
|
2121
2247
|
}
|
|
2122
2248
|
|
|
2249
|
+
const malformedHttpProtocol = /^https?:(?!\/\/)/i;
|
|
2250
|
+
const httpProtocolControlCharacters = /[\t\n\r]/g;
|
|
2251
|
+
function stripLeadingC0ControlOrSpace(url) {
|
|
2252
|
+
let i = 0;
|
|
2253
|
+
while (i < url.length && url.charCodeAt(i) <= 0x20) {
|
|
2254
|
+
i++;
|
|
2255
|
+
}
|
|
2256
|
+
return url.slice(i);
|
|
2257
|
+
}
|
|
2258
|
+
function normalizeURLForProtocolCheck(url) {
|
|
2259
|
+
return stripLeadingC0ControlOrSpace(url).replace(httpProtocolControlCharacters, '');
|
|
2260
|
+
}
|
|
2261
|
+
function assertValidHttpProtocolURL(url, config) {
|
|
2262
|
+
if (typeof url === 'string' && malformedHttpProtocol.test(normalizeURLForProtocolCheck(url))) {
|
|
2263
|
+
throw new AxiosError('Invalid URL: missing "//" after protocol', AxiosError.ERR_INVALID_URL, config);
|
|
2264
|
+
}
|
|
2265
|
+
}
|
|
2266
|
+
|
|
2123
2267
|
/**
|
|
2124
2268
|
* Creates a new URL by combining the baseURL with the requestedURL,
|
|
2125
2269
|
* only when the requestedURL is not already an absolute URL.
|
|
@@ -2130,9 +2274,11 @@ function combineURLs(baseURL, relativeURL) {
|
|
|
2130
2274
|
*
|
|
2131
2275
|
* @returns {string} The combined full path
|
|
2132
2276
|
*/
|
|
2133
|
-
function buildFullPath(baseURL, requestedURL, allowAbsoluteUrls) {
|
|
2277
|
+
function buildFullPath(baseURL, requestedURL, allowAbsoluteUrls, config) {
|
|
2278
|
+
assertValidHttpProtocolURL(requestedURL, config);
|
|
2134
2279
|
let isRelativeUrl = !isAbsoluteURL(requestedURL);
|
|
2135
2280
|
if (baseURL && (isRelativeUrl || allowAbsoluteUrls === false)) {
|
|
2281
|
+
assertValidHttpProtocolURL(baseURL, config);
|
|
2136
2282
|
return combineURLs(baseURL, requestedURL);
|
|
2137
2283
|
}
|
|
2138
2284
|
return requestedURL;
|
|
@@ -2234,7 +2380,7 @@ function getEnv(key) {
|
|
|
2234
2380
|
return process.env[key.toLowerCase()] || process.env[key.toUpperCase()] || '';
|
|
2235
2381
|
}
|
|
2236
2382
|
|
|
2237
|
-
const VERSION = "1.
|
|
2383
|
+
const VERSION = "1.18.1";
|
|
2238
2384
|
|
|
2239
2385
|
function parseProtocol(url) {
|
|
2240
2386
|
const match = /^([-+\w]{1,25}):(?:\/\/)?/.exec(url);
|
|
@@ -2274,13 +2420,13 @@ function fromDataURI(uri, asBlob, options) {
|
|
|
2274
2420
|
|
|
2275
2421
|
// RFC 2397 section 3: default mediatype is text/plain;charset=US-ASCII
|
|
2276
2422
|
// Bare `data:,` leaves mime undefined; Blob normalises that to "" per spec.
|
|
2277
|
-
let mime;
|
|
2423
|
+
let mime = '';
|
|
2278
2424
|
if (type) {
|
|
2279
2425
|
mime = params ? type + params : type;
|
|
2280
2426
|
} else if (params) {
|
|
2281
2427
|
mime = 'text/plain' + params;
|
|
2282
2428
|
}
|
|
2283
|
-
const buffer = Buffer.from(decodeURIComponent(body), encoding);
|
|
2429
|
+
const buffer = encoding === 'base64' ? Buffer.from(body, 'base64') : Buffer.from(decodeURIComponent(body), encoding);
|
|
2284
2430
|
if (asBlob) {
|
|
2285
2431
|
if (!_Blob) {
|
|
2286
2432
|
throw new AxiosError('Blob is not supported', AxiosError.ERR_NOT_SUPPORT);
|
|
@@ -2617,13 +2763,34 @@ const callbackify = (fn, reducer) => {
|
|
|
2617
2763
|
} : fn;
|
|
2618
2764
|
};
|
|
2619
2765
|
|
|
2620
|
-
const LOOPBACK_HOSTNAMES = new Set(['localhost']);
|
|
2766
|
+
const LOOPBACK_HOSTNAMES = new Set(['localhost', '0.0.0.0']);
|
|
2621
2767
|
const isIPv4Loopback = host => {
|
|
2622
2768
|
const parts = host.split('.');
|
|
2623
2769
|
if (parts.length !== 4) return false;
|
|
2624
2770
|
if (parts[0] !== '127') return false;
|
|
2625
2771
|
return parts.every(p => /^\d+$/.test(p) && Number(p) >= 0 && Number(p) <= 255);
|
|
2626
2772
|
};
|
|
2773
|
+
const isIPv6ZeroGroup = group => /^0{1,4}$/.test(group);
|
|
2774
|
+
|
|
2775
|
+
// The unspecified address (IPv4 0.0.0.0 / IPv6 ::) resolves to the local host
|
|
2776
|
+
// for outbound connections, so treat it as loopback-equivalent for NO_PROXY
|
|
2777
|
+
// matching. 0.0.0.0 is covered by LOOPBACK_HOSTNAMES; this handles compressed
|
|
2778
|
+
// and full IPv6 all-zero forms so both families bypass symmetrically.
|
|
2779
|
+
const isIPv6Unspecified = host => {
|
|
2780
|
+
if (host === '::') return true;
|
|
2781
|
+
const compressionIndex = host.indexOf('::');
|
|
2782
|
+
if (compressionIndex !== -1) {
|
|
2783
|
+
if (compressionIndex !== host.lastIndexOf('::')) return false;
|
|
2784
|
+
const left = host.slice(0, compressionIndex);
|
|
2785
|
+
const right = host.slice(compressionIndex + 2);
|
|
2786
|
+
const leftGroups = left ? left.split(':') : [];
|
|
2787
|
+
const rightGroups = right ? right.split(':') : [];
|
|
2788
|
+
const explicitGroups = leftGroups.length + rightGroups.length;
|
|
2789
|
+
return explicitGroups < 8 && leftGroups.every(isIPv6ZeroGroup) && rightGroups.every(isIPv6ZeroGroup);
|
|
2790
|
+
}
|
|
2791
|
+
const groups = host.split(':');
|
|
2792
|
+
return groups.length === 8 && groups.every(isIPv6ZeroGroup);
|
|
2793
|
+
};
|
|
2627
2794
|
const isIPv6Loopback = host => {
|
|
2628
2795
|
// Collapse all-zero groups: any form of ::1 / 0:0:...:0:1
|
|
2629
2796
|
// First, strip any leading "::" by normalising with Set lookup of common forms,
|
|
@@ -2656,6 +2823,7 @@ const isLoopback = host => {
|
|
|
2656
2823
|
if (!host) return false;
|
|
2657
2824
|
if (LOOPBACK_HOSTNAMES.has(host)) return true;
|
|
2658
2825
|
if (isIPv4Loopback(host)) return true;
|
|
2826
|
+
if (isIPv6Unspecified(host)) return true;
|
|
2659
2827
|
return isIPv6Loopback(host);
|
|
2660
2828
|
};
|
|
2661
2829
|
const DEFAULT_PORTS = {
|
|
@@ -2875,11 +3043,13 @@ const asyncDecorator = fn => (...args) => utils$1.asap(() => fn(...args));
|
|
|
2875
3043
|
* Estimate decoded byte length of a data:// URL *without* allocating large buffers.
|
|
2876
3044
|
* - For base64: compute exact decoded size using length and padding;
|
|
2877
3045
|
* handle %XX at the character-count level (no string allocation).
|
|
2878
|
-
* - For non-base64:
|
|
3046
|
+
* - For non-base64: compute the exact percent-decoded UTF-8 byte length.
|
|
2879
3047
|
*
|
|
2880
3048
|
* @param {string} url
|
|
2881
3049
|
* @returns {number}
|
|
2882
3050
|
*/
|
|
3051
|
+
const isHexDigit = charCode => charCode >= 48 && charCode <= 57 || charCode >= 65 && charCode <= 70 || charCode >= 97 && charCode <= 102;
|
|
3052
|
+
const isPercentEncodedByte = (str, i, len) => i + 2 < len && isHexDigit(str.charCodeAt(i + 1)) && isHexDigit(str.charCodeAt(i + 2));
|
|
2883
3053
|
function estimateDataURLDecodedBytes(url) {
|
|
2884
3054
|
if (!url || typeof url !== 'string') return 0;
|
|
2885
3055
|
if (!url.startsWith('data:')) return 0;
|
|
@@ -2896,7 +3066,7 @@ function estimateDataURLDecodedBytes(url) {
|
|
|
2896
3066
|
if (body.charCodeAt(i) === 37 /* '%' */ && i + 2 < len) {
|
|
2897
3067
|
const a = body.charCodeAt(i + 1);
|
|
2898
3068
|
const b = body.charCodeAt(i + 2);
|
|
2899
|
-
const isHex = (a
|
|
3069
|
+
const isHex = isHexDigit(a) && isHexDigit(b);
|
|
2900
3070
|
if (isHex) {
|
|
2901
3071
|
effectiveLen -= 2;
|
|
2902
3072
|
i += 2;
|
|
@@ -2931,18 +3101,18 @@ function estimateDataURLDecodedBytes(url) {
|
|
|
2931
3101
|
const bytes = groups * 3 - (pad || 0);
|
|
2932
3102
|
return bytes > 0 ? bytes : 0;
|
|
2933
3103
|
}
|
|
2934
|
-
if (typeof Buffer !== 'undefined' && typeof Buffer.byteLength === 'function') {
|
|
2935
|
-
return Buffer.byteLength(body, 'utf8');
|
|
2936
|
-
}
|
|
2937
3104
|
|
|
2938
3105
|
// Compute UTF-8 byte length directly from UTF-16 code units without allocating
|
|
2939
3106
|
// a byte buffer (TextEncoder.encode would defeat the DoS guard on large bodies).
|
|
2940
|
-
//
|
|
2941
|
-
//
|
|
3107
|
+
// Valid %XX triplets count as one decoded byte; this matches the bytes that
|
|
3108
|
+
// decodeURIComponent(body) would produce before Buffer re-encodes the string.
|
|
2942
3109
|
let bytes = 0;
|
|
2943
3110
|
for (let i = 0, len = body.length; i < len; i++) {
|
|
2944
3111
|
const c = body.charCodeAt(i);
|
|
2945
|
-
if (c
|
|
3112
|
+
if (c === 37 /* '%' */ && isPercentEncodedByte(body, i, len)) {
|
|
3113
|
+
bytes += 1;
|
|
3114
|
+
i += 2;
|
|
3115
|
+
} else if (c < 0x80) {
|
|
2946
3116
|
bytes += 1;
|
|
2947
3117
|
} else if (c < 0x800) {
|
|
2948
3118
|
bytes += 2;
|
|
@@ -3011,6 +3181,36 @@ const kAxiosInstalledTunnel = Symbol('axios.http.installedTunnel');
|
|
|
3011
3181
|
// so unbounded growth is not a concern in practice.
|
|
3012
3182
|
const tunnelingAgentCache = new Map();
|
|
3013
3183
|
const tunnelingAgentCacheUser = new WeakMap();
|
|
3184
|
+
// Minimum minor versions where Node's HTTP Agent supports native proxyEnv
|
|
3185
|
+
// handling. Checking the selected agent below also covers startup modes such
|
|
3186
|
+
// as NODE_OPTIONS=--use-env-proxy and --no-use-env-proxy precedence.
|
|
3187
|
+
const NODE_NATIVE_ENV_PROXY_SUPPORT = {
|
|
3188
|
+
22: 21,
|
|
3189
|
+
24: 5
|
|
3190
|
+
};
|
|
3191
|
+
function isNodeNativeEnvProxySupported(nodeVersion = process.versions && process.versions.node) {
|
|
3192
|
+
if (!nodeVersion) {
|
|
3193
|
+
return false;
|
|
3194
|
+
}
|
|
3195
|
+
const [major, minor] = nodeVersion.split('.').map(part => Number(part));
|
|
3196
|
+
if (!Number.isInteger(major) || !Number.isInteger(minor)) {
|
|
3197
|
+
return false;
|
|
3198
|
+
}
|
|
3199
|
+
if (major > 24) {
|
|
3200
|
+
return true;
|
|
3201
|
+
}
|
|
3202
|
+
return NODE_NATIVE_ENV_PROXY_SUPPORT[major] != null && minor >= NODE_NATIVE_ENV_PROXY_SUPPORT[major];
|
|
3203
|
+
}
|
|
3204
|
+
function isNodeEnvProxyEnabled(agent, nodeVersion = process.versions && process.versions.node) {
|
|
3205
|
+
if (!isNodeNativeEnvProxySupported(nodeVersion)) {
|
|
3206
|
+
return false;
|
|
3207
|
+
}
|
|
3208
|
+
const agentOptions = agent && agent.options;
|
|
3209
|
+
return Boolean(agentOptions && utils$1.hasOwnProp(agentOptions, 'proxyEnv') && agentOptions.proxyEnv != null);
|
|
3210
|
+
}
|
|
3211
|
+
function getProxyEnvAgent(options, configHttpAgent, configHttpsAgent) {
|
|
3212
|
+
return isHttps.test(options.protocol) ? configHttpsAgent || https.globalAgent : configHttpAgent || http.globalAgent;
|
|
3213
|
+
}
|
|
3014
3214
|
function getTunnelingAgent(agentOptions, userHttpsAgent) {
|
|
3015
3215
|
const key = agentOptions.protocol + '//' + agentOptions.hostname + ':' + (agentOptions.port || '') + '#' + (agentOptions.auth || '');
|
|
3016
3216
|
const cache = userHttpsAgent ? tunnelingAgentCacheUser.get(userHttpsAgent) || tunnelingAgentCacheUser.set(userHttpsAgent, new Map()).get(userHttpsAgent) : tunnelingAgentCache;
|
|
@@ -3066,8 +3266,8 @@ const flushOnFinish = (stream, [throttled, flush]) => {
|
|
|
3066
3266
|
const http2Sessions = new Http2Sessions();
|
|
3067
3267
|
|
|
3068
3268
|
/**
|
|
3069
|
-
* If the proxy, auth, or config beforeRedirects functions are defined,
|
|
3070
|
-
* with the options object.
|
|
3269
|
+
* If the proxy, auth, sensitive header, or config beforeRedirects functions are defined,
|
|
3270
|
+
* call them with the options object.
|
|
3071
3271
|
*
|
|
3072
3272
|
* @param {Object<string, any>} options - The options object that was passed to the request.
|
|
3073
3273
|
*
|
|
@@ -3080,10 +3280,34 @@ function dispatchBeforeRedirect(options, responseDetails, requestDetails) {
|
|
|
3080
3280
|
if (options.beforeRedirects.auth) {
|
|
3081
3281
|
options.beforeRedirects.auth(options);
|
|
3082
3282
|
}
|
|
3283
|
+
if (options.beforeRedirects.sensitiveHeaders) {
|
|
3284
|
+
options.beforeRedirects.sensitiveHeaders(options, requestDetails);
|
|
3285
|
+
}
|
|
3083
3286
|
if (options.beforeRedirects.config) {
|
|
3084
3287
|
options.beforeRedirects.config(options, responseDetails, requestDetails);
|
|
3085
3288
|
}
|
|
3086
3289
|
}
|
|
3290
|
+
function stripMatchingHeaders(headers, sensitiveSet) {
|
|
3291
|
+
if (!headers) {
|
|
3292
|
+
return;
|
|
3293
|
+
}
|
|
3294
|
+
Object.keys(headers).forEach(header => {
|
|
3295
|
+
if (sensitiveSet.has(header.toLowerCase())) {
|
|
3296
|
+
delete headers[header];
|
|
3297
|
+
}
|
|
3298
|
+
});
|
|
3299
|
+
}
|
|
3300
|
+
function isSameOriginRedirect(redirectOptions, requestDetails) {
|
|
3301
|
+
if (!requestDetails) {
|
|
3302
|
+
return false;
|
|
3303
|
+
}
|
|
3304
|
+
try {
|
|
3305
|
+
return new URL(requestDetails.url).origin === new URL(redirectOptions.href).origin;
|
|
3306
|
+
} catch (e) {
|
|
3307
|
+
// If origin comparison fails, treat the redirect as unsafe.
|
|
3308
|
+
return false;
|
|
3309
|
+
}
|
|
3310
|
+
}
|
|
3087
3311
|
|
|
3088
3312
|
/**
|
|
3089
3313
|
* If the proxy or config afterRedirects functions are defined, call them with the options
|
|
@@ -3094,9 +3318,10 @@ function dispatchBeforeRedirect(options, responseDetails, requestDetails) {
|
|
|
3094
3318
|
*
|
|
3095
3319
|
* @returns {http.ClientRequestArgs}
|
|
3096
3320
|
*/
|
|
3097
|
-
function setProxy(options, configProxy, location, isRedirect, configHttpsAgent) {
|
|
3321
|
+
function setProxy(options, configProxy, location, isRedirect, configHttpsAgent, configHttpAgent) {
|
|
3098
3322
|
let proxy = configProxy;
|
|
3099
|
-
|
|
3323
|
+
const proxyEnvAgent = getProxyEnvAgent(options, configHttpAgent, configHttpsAgent);
|
|
3324
|
+
if (!proxy && proxy !== false && !isNodeEnvProxyEnabled(proxyEnvAgent)) {
|
|
3100
3325
|
const proxyUrl = getProxyForUrl(location);
|
|
3101
3326
|
if (proxyUrl) {
|
|
3102
3327
|
if (!shouldBypassProxy(location)) {
|
|
@@ -3187,7 +3412,7 @@ function setProxy(options, configProxy, location, isRedirect, configHttpsAgent)
|
|
|
3187
3412
|
}
|
|
3188
3413
|
const tunnelingAgent = getTunnelingAgent(agentOptions, configHttpsAgent);
|
|
3189
3414
|
// Set both: `options.agent` is consumed by the native https.request path
|
|
3190
|
-
// (
|
|
3415
|
+
// (maxRedirects === 0); `options.agents.https` is consumed by
|
|
3191
3416
|
// follow-redirects, which ignores `options.agent` when `options.agents`
|
|
3192
3417
|
// is present.
|
|
3193
3418
|
options.agent = tunnelingAgent;
|
|
@@ -3231,7 +3456,7 @@ function setProxy(options, configProxy, location, isRedirect, configHttpsAgent)
|
|
|
3231
3456
|
options.beforeRedirects.proxy = function beforeRedirect(redirectOptions) {
|
|
3232
3457
|
// Configure proxy for redirected request, passing the original config proxy to apply
|
|
3233
3458
|
// the exact same logic as if the redirected request was performed by axios directly.
|
|
3234
|
-
setProxy(redirectOptions, configProxy, redirectOptions.href, true, configHttpsAgent);
|
|
3459
|
+
setProxy(redirectOptions, configProxy, redirectOptions.href, true, configHttpsAgent, configHttpAgent);
|
|
3235
3460
|
};
|
|
3236
3461
|
}
|
|
3237
3462
|
const isHttpAdapterSupported = typeof process !== 'undefined' && utils$1.kindOf(process) === 'process';
|
|
@@ -3314,7 +3539,12 @@ const http2Transport = {
|
|
|
3314
3539
|
/*eslint consistent-return:0*/
|
|
3315
3540
|
var httpAdapter = isHttpAdapterSupported && function httpAdapter(config) {
|
|
3316
3541
|
return wrapAsync(async function dispatchHttpRequest(resolve, reject, onDone) {
|
|
3317
|
-
|
|
3542
|
+
// Read config pollution-safely: own properties and members inherited from
|
|
3543
|
+
// a non-Object.prototype source (e.g. an Object.create(defaults) template)
|
|
3544
|
+
// are honored, but values injected onto a polluted Object.prototype are
|
|
3545
|
+
// ignored. All behavior-affecting reads in this adapter go through own()
|
|
3546
|
+
// so the protection boundary stays consistent.
|
|
3547
|
+
const own = key => utils$1.getSafeProp(config, key);
|
|
3318
3548
|
const transitional = own('transitional') || transitionalDefaults;
|
|
3319
3549
|
let data = own('data');
|
|
3320
3550
|
let lookup = own('lookup');
|
|
@@ -3322,9 +3552,17 @@ var httpAdapter = isHttpAdapterSupported && function httpAdapter(config) {
|
|
|
3322
3552
|
let httpVersion = own('httpVersion');
|
|
3323
3553
|
if (httpVersion === undefined) httpVersion = 1;
|
|
3324
3554
|
let http2Options = own('http2Options');
|
|
3555
|
+
const httpAgent = own('httpAgent');
|
|
3556
|
+
const httpsAgent = own('httpsAgent');
|
|
3557
|
+
const configProxy = own('proxy');
|
|
3325
3558
|
const responseType = own('responseType');
|
|
3326
3559
|
const responseEncoding = own('responseEncoding');
|
|
3327
|
-
const
|
|
3560
|
+
const socketPath = own('socketPath');
|
|
3561
|
+
const method = own('method').toUpperCase();
|
|
3562
|
+
const maxRedirects = own('maxRedirects');
|
|
3563
|
+
const maxBodyLength = own('maxBodyLength');
|
|
3564
|
+
const maxContentLength = own('maxContentLength');
|
|
3565
|
+
const decompress = own('decompress');
|
|
3328
3566
|
let isDone;
|
|
3329
3567
|
let rejected = false;
|
|
3330
3568
|
let req;
|
|
@@ -3365,9 +3603,11 @@ var httpAdapter = isHttpAdapterSupported && function httpAdapter(config) {
|
|
|
3365
3603
|
}
|
|
3366
3604
|
}
|
|
3367
3605
|
function createTimeoutError() {
|
|
3368
|
-
|
|
3369
|
-
|
|
3370
|
-
|
|
3606
|
+
const configTimeout = own('timeout');
|
|
3607
|
+
let timeoutErrorMessage = configTimeout ? 'timeout of ' + configTimeout + 'ms exceeded' : 'timeout exceeded';
|
|
3608
|
+
const configTimeoutErrorMessage = own('timeoutErrorMessage');
|
|
3609
|
+
if (configTimeoutErrorMessage) {
|
|
3610
|
+
timeoutErrorMessage = configTimeoutErrorMessage;
|
|
3371
3611
|
}
|
|
3372
3612
|
return new AxiosError(timeoutErrorMessage, transitional.clarifyTimeoutError ? AxiosError.ETIMEDOUT : AxiosError.ECONNABORTED, config, req);
|
|
3373
3613
|
}
|
|
@@ -3410,17 +3650,22 @@ var httpAdapter = isHttpAdapterSupported && function httpAdapter(config) {
|
|
|
3410
3650
|
});
|
|
3411
3651
|
|
|
3412
3652
|
// Parse url
|
|
3413
|
-
const fullPath = buildFullPath(
|
|
3414
|
-
|
|
3653
|
+
const fullPath = buildFullPath(own('baseURL'), own('url'), own('allowAbsoluteUrls'), config);
|
|
3654
|
+
// Unix-socket requests (own socketPath) commonly pass a path-only url
|
|
3655
|
+
// like '/foo'; supply a synthetic base so new URL() can still parse it.
|
|
3656
|
+
// Use the own-property value (not config.socketPath) so a polluted
|
|
3657
|
+
// prototype cannot influence URL base selection.
|
|
3658
|
+
const urlBase = socketPath ? 'http://localhost' : platform.hasBrowserEnv ? platform.origin : undefined;
|
|
3659
|
+
const parsed = new URL(fullPath, urlBase);
|
|
3415
3660
|
const protocol = parsed.protocol || supportedProtocols[0];
|
|
3416
3661
|
if (protocol === 'data:') {
|
|
3417
3662
|
// Apply the same semantics as HTTP: only enforce if a finite, non-negative cap is set.
|
|
3418
|
-
if (
|
|
3419
|
-
// Use the exact string passed to fromDataURI (
|
|
3420
|
-
const dataUrl = String(
|
|
3663
|
+
if (maxContentLength > -1) {
|
|
3664
|
+
// Use the exact string passed to fromDataURI (the configured url); fall back to fullPath if needed.
|
|
3665
|
+
const dataUrl = String(own('url') || fullPath || '');
|
|
3421
3666
|
const estimated = estimateDataURLDecodedBytes(dataUrl);
|
|
3422
|
-
if (estimated >
|
|
3423
|
-
return reject(new AxiosError('maxContentLength size of ' +
|
|
3667
|
+
if (estimated > maxContentLength) {
|
|
3668
|
+
return reject(new AxiosError('maxContentLength size of ' + maxContentLength + ' exceeded', AxiosError.ERR_BAD_RESPONSE, config));
|
|
3424
3669
|
}
|
|
3425
3670
|
}
|
|
3426
3671
|
let convertedData;
|
|
@@ -3433,7 +3678,7 @@ var httpAdapter = isHttpAdapterSupported && function httpAdapter(config) {
|
|
|
3433
3678
|
});
|
|
3434
3679
|
}
|
|
3435
3680
|
try {
|
|
3436
|
-
convertedData = fromDataURI(
|
|
3681
|
+
convertedData = fromDataURI(own('url'), responseType === 'blob', {
|
|
3437
3682
|
Blob: config.env && config.env.Blob
|
|
3438
3683
|
});
|
|
3439
3684
|
} catch (err) {
|
|
@@ -3507,7 +3752,7 @@ var httpAdapter = isHttpAdapterSupported && function httpAdapter(config) {
|
|
|
3507
3752
|
|
|
3508
3753
|
// Add Content-Length header if data exists
|
|
3509
3754
|
headers.setContentLength(data.length, false);
|
|
3510
|
-
if (
|
|
3755
|
+
if (maxBodyLength > -1 && data.length > maxBodyLength) {
|
|
3511
3756
|
return reject(new AxiosError('Request body larger than maxBodyLength limit', AxiosError.ERR_BAD_REQUEST, config));
|
|
3512
3757
|
}
|
|
3513
3758
|
}
|
|
@@ -3534,8 +3779,8 @@ var httpAdapter = isHttpAdapterSupported && function httpAdapter(config) {
|
|
|
3534
3779
|
let auth = undefined;
|
|
3535
3780
|
const configAuth = own('auth');
|
|
3536
3781
|
if (configAuth) {
|
|
3537
|
-
const username = configAuth
|
|
3538
|
-
const password = configAuth
|
|
3782
|
+
const username = utils$1.getSafeProp(configAuth, 'username') || '';
|
|
3783
|
+
const password = utils$1.getSafeProp(configAuth, 'password') || '';
|
|
3539
3784
|
auth = username + ':' + password;
|
|
3540
3785
|
}
|
|
3541
3786
|
if (!auth && (parsed.username || parsed.password)) {
|
|
@@ -3546,13 +3791,12 @@ var httpAdapter = isHttpAdapterSupported && function httpAdapter(config) {
|
|
|
3546
3791
|
auth && headers.delete('authorization');
|
|
3547
3792
|
let path$1;
|
|
3548
3793
|
try {
|
|
3549
|
-
path$1 = buildURL(parsed.pathname + parsed.search,
|
|
3794
|
+
path$1 = buildURL(parsed.pathname + parsed.search, own('params'), own('paramsSerializer')).replace(/^\?/, '');
|
|
3550
3795
|
} catch (err) {
|
|
3551
|
-
|
|
3552
|
-
|
|
3553
|
-
|
|
3554
|
-
|
|
3555
|
-
return reject(customErr);
|
|
3796
|
+
return reject(AxiosError.from(err, AxiosError.ERR_BAD_REQUEST, config, null, null, {
|
|
3797
|
+
url: own('url'),
|
|
3798
|
+
exists: true
|
|
3799
|
+
}));
|
|
3556
3800
|
}
|
|
3557
3801
|
headers.set('Accept-Encoding', utils$1.hasOwnProp(transitional, 'advertiseZstdAcceptEncoding') && transitional.advertiseZstdAcceptEncoding === true ? ACCEPT_ENCODING_WITH_ZSTD : ACCEPT_ENCODING, false);
|
|
3558
3802
|
|
|
@@ -3563,8 +3807,8 @@ var httpAdapter = isHttpAdapterSupported && function httpAdapter(config) {
|
|
|
3563
3807
|
method: method,
|
|
3564
3808
|
headers: toByteStringHeaderObject(headers),
|
|
3565
3809
|
agents: {
|
|
3566
|
-
http:
|
|
3567
|
-
https:
|
|
3810
|
+
http: httpAgent,
|
|
3811
|
+
https: httpsAgent
|
|
3568
3812
|
},
|
|
3569
3813
|
auth,
|
|
3570
3814
|
protocol,
|
|
@@ -3576,7 +3820,6 @@ var httpAdapter = isHttpAdapterSupported && function httpAdapter(config) {
|
|
|
3576
3820
|
|
|
3577
3821
|
// cacheable-lookup integration hotfix
|
|
3578
3822
|
!utils$1.isUndefined(lookup) && (options.lookup = lookup);
|
|
3579
|
-
const socketPath = own('socketPath');
|
|
3580
3823
|
if (socketPath) {
|
|
3581
3824
|
if (typeof socketPath !== 'string') {
|
|
3582
3825
|
return reject(new AxiosError('socketPath must be a string', AxiosError.ERR_BAD_OPTION_VALUE, config));
|
|
@@ -3594,15 +3837,20 @@ var httpAdapter = isHttpAdapterSupported && function httpAdapter(config) {
|
|
|
3594
3837
|
} else {
|
|
3595
3838
|
options.hostname = parsed.hostname.startsWith('[') ? parsed.hostname.slice(1, -1) : parsed.hostname;
|
|
3596
3839
|
options.port = parsed.port;
|
|
3597
|
-
setProxy(options,
|
|
3840
|
+
setProxy(options, configProxy, protocol + '//' + parsed.hostname + (parsed.port ? ':' + parsed.port : '') + options.path, false, httpsAgent, httpAgent);
|
|
3598
3841
|
}
|
|
3599
3842
|
let transport;
|
|
3600
3843
|
let isNativeTransport = false;
|
|
3844
|
+
// True only for the follow-redirects transport, which applies
|
|
3845
|
+
// options.maxBodyLength itself. Every other transport (http2, native
|
|
3846
|
+
// http/https, a user-supplied custom transport) needs the explicit
|
|
3847
|
+
// byte-counting pipeline below to enforce maxBodyLength on streamed uploads.
|
|
3848
|
+
let transportEnforcesMaxBodyLength = false;
|
|
3601
3849
|
const isHttpsRequest = isHttps.test(options.protocol);
|
|
3602
3850
|
// Don't clobber a CONNECT-tunneling agent installed by setProxy() for an
|
|
3603
3851
|
// HTTPS target.
|
|
3604
3852
|
if (options.agent == null) {
|
|
3605
|
-
options.agent = isHttpsRequest ?
|
|
3853
|
+
options.agent = isHttpsRequest ? httpsAgent : httpAgent;
|
|
3606
3854
|
}
|
|
3607
3855
|
if (isHttp2) {
|
|
3608
3856
|
transport = http2Transport;
|
|
@@ -3610,12 +3858,14 @@ var httpAdapter = isHttpAdapterSupported && function httpAdapter(config) {
|
|
|
3610
3858
|
const configTransport = own('transport');
|
|
3611
3859
|
if (configTransport) {
|
|
3612
3860
|
transport = configTransport;
|
|
3613
|
-
} else if (
|
|
3861
|
+
} else if (maxRedirects === 0) {
|
|
3614
3862
|
transport = isHttpsRequest ? https : http;
|
|
3615
3863
|
isNativeTransport = true;
|
|
3616
3864
|
} else {
|
|
3617
|
-
|
|
3618
|
-
|
|
3865
|
+
transportEnforcesMaxBodyLength = true;
|
|
3866
|
+
options.sensitiveHeaders = [];
|
|
3867
|
+
if (maxRedirects) {
|
|
3868
|
+
options.maxRedirects = maxRedirects;
|
|
3619
3869
|
}
|
|
3620
3870
|
const configBeforeRedirect = own('beforeRedirect');
|
|
3621
3871
|
if (configBeforeRedirect) {
|
|
@@ -3638,13 +3888,37 @@ var httpAdapter = isHttpAdapterSupported && function httpAdapter(config) {
|
|
|
3638
3888
|
}
|
|
3639
3889
|
};
|
|
3640
3890
|
}
|
|
3891
|
+
const sensitiveHeaders = own('sensitiveHeaders');
|
|
3892
|
+
if (sensitiveHeaders != null) {
|
|
3893
|
+
if (!utils$1.isArray(sensitiveHeaders)) {
|
|
3894
|
+
return reject(new AxiosError('sensitiveHeaders must be an array of strings', AxiosError.ERR_BAD_OPTION_VALUE, config));
|
|
3895
|
+
}
|
|
3896
|
+
const sensitiveSet = new Set();
|
|
3897
|
+
for (const header of sensitiveHeaders) {
|
|
3898
|
+
if (!utils$1.isString(header)) {
|
|
3899
|
+
return reject(new AxiosError('sensitiveHeaders must be an array of strings', AxiosError.ERR_BAD_OPTION_VALUE, config));
|
|
3900
|
+
}
|
|
3901
|
+
sensitiveSet.add(header.toLowerCase());
|
|
3902
|
+
}
|
|
3903
|
+
if (sensitiveSet.size) {
|
|
3904
|
+
options.sensitiveHeaders = Array.from(sensitiveSet);
|
|
3905
|
+
options.beforeRedirects.sensitiveHeaders = function beforeRedirectSensitiveHeaders(redirectOptions, requestDetails) {
|
|
3906
|
+
if (!isSameOriginRedirect(redirectOptions, requestDetails)) {
|
|
3907
|
+
stripMatchingHeaders(redirectOptions.headers, sensitiveSet);
|
|
3908
|
+
}
|
|
3909
|
+
};
|
|
3910
|
+
}
|
|
3911
|
+
}
|
|
3641
3912
|
transport = isHttpsRequest ? httpsFollow : httpFollow;
|
|
3642
3913
|
}
|
|
3643
3914
|
}
|
|
3644
|
-
|
|
3645
|
-
|
|
3915
|
+
|
|
3916
|
+
// Set an explicit maxBodyLength option for transports that inspect it.
|
|
3917
|
+
// When maxBodyLength is -1 (default/unlimited), use Infinity so
|
|
3918
|
+
// follow-redirects does not fall back to its own 10MB default.
|
|
3919
|
+
if (maxBodyLength > -1) {
|
|
3920
|
+
options.maxBodyLength = maxBodyLength;
|
|
3646
3921
|
} else {
|
|
3647
|
-
// follow-redirects does not skip comparison, so it should always succeed for axios -1 unlimited
|
|
3648
3922
|
options.maxBodyLength = Infinity;
|
|
3649
3923
|
}
|
|
3650
3924
|
|
|
@@ -3674,7 +3948,7 @@ var httpAdapter = isHttpAdapterSupported && function httpAdapter(config) {
|
|
|
3674
3948
|
const lastRequest = res.req || req;
|
|
3675
3949
|
|
|
3676
3950
|
// if decompress disabled we should not decompress
|
|
3677
|
-
if (
|
|
3951
|
+
if (decompress !== false && res.headers['content-encoding']) {
|
|
3678
3952
|
// if no content, but headers still say that it is encoded,
|
|
3679
3953
|
// remove the header not confuse downstream operations
|
|
3680
3954
|
if (method === 'HEAD' || res.statusCode === 204) {
|
|
@@ -3726,8 +4000,8 @@ var httpAdapter = isHttpAdapterSupported && function httpAdapter(config) {
|
|
|
3726
4000
|
if (responseType === 'stream') {
|
|
3727
4001
|
// Enforce maxContentLength on streamed responses; previously this
|
|
3728
4002
|
// was applied only to buffered responses.
|
|
3729
|
-
if (
|
|
3730
|
-
const limit =
|
|
4003
|
+
if (maxContentLength > -1) {
|
|
4004
|
+
const limit = maxContentLength;
|
|
3731
4005
|
const source = responseStream;
|
|
3732
4006
|
async function* enforceMaxContentLength() {
|
|
3733
4007
|
let totalResponseBytes = 0;
|
|
@@ -3753,11 +4027,11 @@ var httpAdapter = isHttpAdapterSupported && function httpAdapter(config) {
|
|
|
3753
4027
|
totalResponseBytes += chunk.length;
|
|
3754
4028
|
|
|
3755
4029
|
// make sure the content length is not over the maxContentLength if specified
|
|
3756
|
-
if (
|
|
4030
|
+
if (maxContentLength > -1 && totalResponseBytes > maxContentLength) {
|
|
3757
4031
|
// stream.destroy() emit aborted event before calling reject() on Node.js v16
|
|
3758
4032
|
rejected = true;
|
|
3759
4033
|
responseStream.destroy();
|
|
3760
|
-
abort(new AxiosError('maxContentLength size of ' +
|
|
4034
|
+
abort(new AxiosError('maxContentLength size of ' + maxContentLength + ' exceeded', AxiosError.ERR_BAD_RESPONSE, config, lastRequest));
|
|
3761
4035
|
}
|
|
3762
4036
|
});
|
|
3763
4037
|
responseStream.on('aborted', function handlerStreamAborted() {
|
|
@@ -3820,7 +4094,11 @@ var httpAdapter = isHttpAdapterSupported && function httpAdapter(config) {
|
|
|
3820
4094
|
const boundSockets = new Set();
|
|
3821
4095
|
req.on('socket', function handleRequestSocket(socket) {
|
|
3822
4096
|
// default interval of sending ack packet is 1 minute
|
|
3823
|
-
|
|
4097
|
+
// proxy agents (e.g. agent-base) may return a generic Duplex stream
|
|
4098
|
+
// that doesn't have setKeepAlive, so guard before calling
|
|
4099
|
+
if (typeof socket.setKeepAlive === 'function') {
|
|
4100
|
+
socket.setKeepAlive(true, 1000 * 60);
|
|
4101
|
+
}
|
|
3824
4102
|
|
|
3825
4103
|
// Install a single 'error' listener per socket (not per request) to avoid
|
|
3826
4104
|
// accumulating listeners on pooled keep-alive sockets that get reassigned
|
|
@@ -3850,9 +4128,9 @@ var httpAdapter = isHttpAdapterSupported && function httpAdapter(config) {
|
|
|
3850
4128
|
});
|
|
3851
4129
|
|
|
3852
4130
|
// Handle request timeout
|
|
3853
|
-
if (
|
|
4131
|
+
if (own('timeout')) {
|
|
3854
4132
|
// This is forcing a int timeout to avoid problems if the `req` interface doesn't handle other types.
|
|
3855
|
-
const timeout = parseInt(
|
|
4133
|
+
const timeout = parseInt(own('timeout'), 10);
|
|
3856
4134
|
if (Number.isNaN(timeout)) {
|
|
3857
4135
|
abort(new AxiosError('error trying to parse `config.timeout` to int', AxiosError.ERR_BAD_OPTION_VALUE, config, req));
|
|
3858
4136
|
return;
|
|
@@ -3896,12 +4174,13 @@ var httpAdapter = isHttpAdapterSupported && function httpAdapter(config) {
|
|
|
3896
4174
|
}
|
|
3897
4175
|
});
|
|
3898
4176
|
|
|
3899
|
-
// Enforce maxBodyLength for streamed uploads on
|
|
3900
|
-
//
|
|
3901
|
-
//
|
|
4177
|
+
// Enforce maxBodyLength for streamed uploads on every transport that
|
|
4178
|
+
// does not apply options.maxBodyLength itself (native http/https, http2,
|
|
4179
|
+
// and user-supplied custom transports). The follow-redirects transport
|
|
4180
|
+
// enforces it on the redirected HTTP/1 path.
|
|
3902
4181
|
let uploadStream = data;
|
|
3903
|
-
if (
|
|
3904
|
-
const limit =
|
|
4182
|
+
if (maxBodyLength > -1 && !transportEnforcesMaxBodyLength) {
|
|
4183
|
+
const limit = maxBodyLength;
|
|
3905
4184
|
let bytesSent = 0;
|
|
3906
4185
|
uploadStream = stream.pipeline([data, new stream.Transform({
|
|
3907
4186
|
transform(chunk, _enc, cb) {
|
|
@@ -3964,7 +4243,11 @@ var cookies = platform.hasStandardBrowserEnv ?
|
|
|
3964
4243
|
const cookie = cookies[i].replace(/^\s+/, '');
|
|
3965
4244
|
const eq = cookie.indexOf('=');
|
|
3966
4245
|
if (eq !== -1 && cookie.slice(0, eq) === name) {
|
|
3967
|
-
|
|
4246
|
+
try {
|
|
4247
|
+
return decodeURIComponent(cookie.slice(eq + 1));
|
|
4248
|
+
} catch (e) {
|
|
4249
|
+
return cookie.slice(eq + 1);
|
|
4250
|
+
}
|
|
3968
4251
|
}
|
|
3969
4252
|
}
|
|
3970
4253
|
return null;
|
|
@@ -3997,6 +4280,7 @@ const headersToObject = thing => thing instanceof AxiosHeaders ? {
|
|
|
3997
4280
|
*/
|
|
3998
4281
|
function mergeConfig(config1, config2) {
|
|
3999
4282
|
// eslint-disable-next-line no-param-reassign
|
|
4283
|
+
config1 = config1 || {};
|
|
4000
4284
|
config2 = config2 || {};
|
|
4001
4285
|
|
|
4002
4286
|
// Use a null-prototype object so that downstream reads such as `config.auth`
|
|
@@ -4048,6 +4332,23 @@ function mergeConfig(config1, config2) {
|
|
|
4048
4332
|
return getMergedValue(undefined, a);
|
|
4049
4333
|
}
|
|
4050
4334
|
}
|
|
4335
|
+
function getMergedTransitionalOption(prop) {
|
|
4336
|
+
const transitional2 = utils$1.hasOwnProp(config2, 'transitional') ? config2.transitional : undefined;
|
|
4337
|
+
if (!utils$1.isUndefined(transitional2)) {
|
|
4338
|
+
if (utils$1.isPlainObject(transitional2)) {
|
|
4339
|
+
if (utils$1.hasOwnProp(transitional2, prop)) {
|
|
4340
|
+
return transitional2[prop];
|
|
4341
|
+
}
|
|
4342
|
+
} else {
|
|
4343
|
+
return undefined;
|
|
4344
|
+
}
|
|
4345
|
+
}
|
|
4346
|
+
const transitional1 = utils$1.hasOwnProp(config1, 'transitional') ? config1.transitional : undefined;
|
|
4347
|
+
if (utils$1.isPlainObject(transitional1) && utils$1.hasOwnProp(transitional1, prop)) {
|
|
4348
|
+
return transitional1[prop];
|
|
4349
|
+
}
|
|
4350
|
+
return undefined;
|
|
4351
|
+
}
|
|
4051
4352
|
|
|
4052
4353
|
// eslint-disable-next-line consistent-return
|
|
4053
4354
|
function mergeDirectKeys(a, b, prop) {
|
|
@@ -4100,6 +4401,13 @@ function mergeConfig(config1, config2) {
|
|
|
4100
4401
|
const configValue = merge(a, b, prop);
|
|
4101
4402
|
utils$1.isUndefined(configValue) && merge !== mergeDirectKeys || (config[prop] = configValue);
|
|
4102
4403
|
});
|
|
4404
|
+
if (utils$1.hasOwnProp(config2, 'validateStatus') && utils$1.isUndefined(config2.validateStatus) && getMergedTransitionalOption('validateStatusUndefinedResolves') === false) {
|
|
4405
|
+
if (utils$1.hasOwnProp(config1, 'validateStatus')) {
|
|
4406
|
+
config.validateStatus = getMergedValue(undefined, config1.validateStatus);
|
|
4407
|
+
} else {
|
|
4408
|
+
delete config.validateStatus;
|
|
4409
|
+
}
|
|
4410
|
+
}
|
|
4103
4411
|
return config;
|
|
4104
4412
|
}
|
|
4105
4413
|
|
|
@@ -4109,7 +4417,7 @@ function setFormDataHeaders(headers, formHeaders, policy) {
|
|
|
4109
4417
|
headers.set(formHeaders);
|
|
4110
4418
|
return;
|
|
4111
4419
|
}
|
|
4112
|
-
Object.entries(formHeaders).forEach(([key, val]) => {
|
|
4420
|
+
Object.entries(formHeaders || {}).forEach(([key, val]) => {
|
|
4113
4421
|
if (FORM_DATA_CONTENT_HEADERS.includes(key.toLowerCase())) {
|
|
4114
4422
|
headers.set(key, val);
|
|
4115
4423
|
}
|
|
@@ -4141,11 +4449,17 @@ function resolveConfig(config) {
|
|
|
4141
4449
|
const allowAbsoluteUrls = own('allowAbsoluteUrls');
|
|
4142
4450
|
const url = own('url');
|
|
4143
4451
|
newConfig.headers = headers = AxiosHeaders.from(headers);
|
|
4144
|
-
newConfig.url = buildURL(buildFullPath(baseURL, url, allowAbsoluteUrls), own('params'), own('paramsSerializer'));
|
|
4452
|
+
newConfig.url = buildURL(buildFullPath(baseURL, url, allowAbsoluteUrls, newConfig), own('params'), own('paramsSerializer'));
|
|
4145
4453
|
|
|
4146
4454
|
// HTTP basic authentication
|
|
4147
4455
|
if (auth) {
|
|
4148
|
-
|
|
4456
|
+
const username = utils$1.getSafeProp(auth, 'username') || '';
|
|
4457
|
+
const password = utils$1.getSafeProp(auth, 'password') || '';
|
|
4458
|
+
try {
|
|
4459
|
+
headers.set('Authorization', 'Basic ' + btoa(username + ':' + (password ? encodeUTF8$1(password) : '')));
|
|
4460
|
+
} catch (e) {
|
|
4461
|
+
throw AxiosError.from(e, AxiosError.ERR_BAD_OPTION_VALUE, config);
|
|
4462
|
+
}
|
|
4149
4463
|
}
|
|
4150
4464
|
if (utils$1.isFormData(data)) {
|
|
4151
4465
|
if (platform.hasStandardBrowserEnv || platform.hasStandardBrowserWebWorkerEnv || utils$1.isReactNative(data)) {
|
|
@@ -4346,6 +4660,7 @@ var xhrAdapter = isXHRAdapterSupported && function (config) {
|
|
|
4346
4660
|
const protocol = parseProtocol(_config.url);
|
|
4347
4661
|
if (protocol && !platform.protocols.includes(protocol)) {
|
|
4348
4662
|
reject(new AxiosError('Unsupported protocol ' + protocol + ':', AxiosError.ERR_BAD_REQUEST, config));
|
|
4663
|
+
done();
|
|
4349
4664
|
return;
|
|
4350
4665
|
}
|
|
4351
4666
|
|
|
@@ -4384,7 +4699,9 @@ const composeSignals = (signals, timeout) => {
|
|
|
4384
4699
|
});
|
|
4385
4700
|
signals = null;
|
|
4386
4701
|
};
|
|
4387
|
-
signals.forEach(signal => signal.addEventListener('abort', onabort
|
|
4702
|
+
signals.forEach(signal => signal.addEventListener('abort', onabort, {
|
|
4703
|
+
once: true
|
|
4704
|
+
}));
|
|
4388
4705
|
const {
|
|
4389
4706
|
signal
|
|
4390
4707
|
} = controller;
|
|
@@ -4630,13 +4947,20 @@ const factory = env => {
|
|
|
4630
4947
|
composedSignal.unsubscribe();
|
|
4631
4948
|
});
|
|
4632
4949
|
let requestContentLength;
|
|
4950
|
+
|
|
4951
|
+
// AxiosError we raise while the request body is being streamed. Captured
|
|
4952
|
+
// by identity so the catch block can surface it directly, regardless of
|
|
4953
|
+
// how the runtime wraps the resulting fetch rejection (undici exposes it
|
|
4954
|
+
// as `err.cause`; some browsers drop the original error entirely).
|
|
4955
|
+
let pendingBodyError = null;
|
|
4956
|
+
const maxBodyLengthError = () => new AxiosError('Request body larger than maxBodyLength limit', AxiosError.ERR_BAD_REQUEST, config, request);
|
|
4633
4957
|
try {
|
|
4634
4958
|
// HTTP basic authentication
|
|
4635
4959
|
let auth = undefined;
|
|
4636
4960
|
const configAuth = own('auth');
|
|
4637
4961
|
if (configAuth) {
|
|
4638
|
-
const username = configAuth
|
|
4639
|
-
const password = configAuth
|
|
4962
|
+
const username = utils$1.getSafeProp(configAuth, 'username') || '';
|
|
4963
|
+
const password = utils$1.getSafeProp(configAuth, 'password') || '';
|
|
4640
4964
|
auth = {
|
|
4641
4965
|
username,
|
|
4642
4966
|
password
|
|
@@ -4673,30 +4997,54 @@ const factory = env => {
|
|
|
4673
4997
|
}
|
|
4674
4998
|
}
|
|
4675
4999
|
|
|
4676
|
-
// Enforce maxBodyLength against
|
|
4677
|
-
//
|
|
4678
|
-
//
|
|
4679
|
-
//
|
|
5000
|
+
// Enforce maxBodyLength against known-size bodies before dispatch using
|
|
5001
|
+
// the body's *actual* size — never a caller-declared Content-Length,
|
|
5002
|
+
// which could under-report to slip an oversized body past the check.
|
|
5003
|
+
// Unknown-size streams return undefined here and are counted per-chunk
|
|
5004
|
+
// below as fetch consumes them.
|
|
4680
5005
|
if (hasMaxBodyLength && method !== 'get' && method !== 'head') {
|
|
4681
|
-
const outboundLength = await
|
|
4682
|
-
if (typeof outboundLength === 'number' && isFinite(outboundLength)
|
|
4683
|
-
|
|
5006
|
+
const outboundLength = await getBodyLength(data);
|
|
5007
|
+
if (typeof outboundLength === 'number' && isFinite(outboundLength)) {
|
|
5008
|
+
requestContentLength = outboundLength;
|
|
5009
|
+
if (outboundLength > maxBodyLength) {
|
|
5010
|
+
throw maxBodyLengthError();
|
|
5011
|
+
}
|
|
4684
5012
|
}
|
|
4685
5013
|
}
|
|
4686
|
-
|
|
4687
|
-
|
|
4688
|
-
|
|
4689
|
-
|
|
4690
|
-
|
|
4691
|
-
|
|
4692
|
-
|
|
4693
|
-
if (utils$1.isFormData(data) && (contentTypeHeader = _request.headers.get('content-type'))) {
|
|
4694
|
-
headers.setContentType(contentTypeHeader);
|
|
5014
|
+
|
|
5015
|
+
// A streamed body under maxBodyLength must be counted as fetch consumes
|
|
5016
|
+
// it; its size is never trusted from a caller-declared Content-Length.
|
|
5017
|
+
const mustEnforceStreamBody = hasMaxBodyLength && (utils$1.isReadableStream(data) || utils$1.isStream(data));
|
|
5018
|
+
const trackRequestStream = (stream, onProgress, flush) => trackStream(stream, DEFAULT_CHUNK_SIZE, loadedBytes => {
|
|
5019
|
+
if (hasMaxBodyLength && loadedBytes > maxBodyLength) {
|
|
5020
|
+
throw pendingBodyError = maxBodyLengthError();
|
|
4695
5021
|
}
|
|
4696
|
-
|
|
4697
|
-
|
|
4698
|
-
|
|
5022
|
+
onProgress && onProgress(loadedBytes);
|
|
5023
|
+
}, flush);
|
|
5024
|
+
if (supportsRequestStream && method !== 'get' && method !== 'head' && (onUploadProgress || mustEnforceStreamBody)) {
|
|
5025
|
+
requestContentLength = requestContentLength == null ? await resolveBodyLength(headers, data) : requestContentLength;
|
|
5026
|
+
|
|
5027
|
+
// A declared length of 0 is only trusted to skip the wrap when we are
|
|
5028
|
+
// not enforcing a stream limit (which must not rely on that header).
|
|
5029
|
+
if (requestContentLength !== 0 || mustEnforceStreamBody) {
|
|
5030
|
+
let _request = new Request(url, {
|
|
5031
|
+
method: 'POST',
|
|
5032
|
+
body: data,
|
|
5033
|
+
duplex: 'half'
|
|
5034
|
+
});
|
|
5035
|
+
let contentTypeHeader;
|
|
5036
|
+
if (utils$1.isFormData(data) && (contentTypeHeader = _request.headers.get('content-type'))) {
|
|
5037
|
+
headers.setContentType(contentTypeHeader);
|
|
5038
|
+
}
|
|
5039
|
+
if (_request.body) {
|
|
5040
|
+
const [onProgress, flush] = onUploadProgress && progressEventDecorator(requestContentLength, progressEventReducer(asyncDecorator(onUploadProgress))) || [];
|
|
5041
|
+
data = trackRequestStream(_request.body, onProgress, flush);
|
|
5042
|
+
}
|
|
4699
5043
|
}
|
|
5044
|
+
} else if (mustEnforceStreamBody && !isRequestSupported && isReadableStreamSupported && method !== 'get' && method !== 'head') {
|
|
5045
|
+
data = trackRequestStream(data);
|
|
5046
|
+
} else if (mustEnforceStreamBody && isRequestSupported && !supportsRequestStream && method !== 'get' && method !== 'head') {
|
|
5047
|
+
throw new AxiosError('Stream request bodies are not supported by the current fetch implementation', AxiosError.ERR_NOT_SUPPORT, config, request);
|
|
4700
5048
|
}
|
|
4701
5049
|
if (!utils$1.isString(withCredentials)) {
|
|
4702
5050
|
withCredentials = withCredentials ? 'include' : 'omit';
|
|
@@ -4728,11 +5076,12 @@ const factory = env => {
|
|
|
4728
5076
|
};
|
|
4729
5077
|
request = isRequestSupported && new Request(url, resolvedOptions);
|
|
4730
5078
|
let response = await (isRequestSupported ? _fetch(request, fetchOptions) : _fetch(url, resolvedOptions));
|
|
5079
|
+
const responseHeaders = AxiosHeaders.from(response.headers);
|
|
4731
5080
|
|
|
4732
5081
|
// Cheap pre-check: if the server honestly declares a content-length that
|
|
4733
5082
|
// already exceeds the cap, reject before we start streaming.
|
|
4734
5083
|
if (hasMaxContentLength) {
|
|
4735
|
-
const declaredLength = utils$1.toFiniteNumber(
|
|
5084
|
+
const declaredLength = utils$1.toFiniteNumber(responseHeaders.getContentLength());
|
|
4736
5085
|
if (declaredLength != null && declaredLength > maxContentLength) {
|
|
4737
5086
|
throw new AxiosError('maxContentLength size of ' + maxContentLength + ' exceeded', AxiosError.ERR_BAD_RESPONSE, config, request);
|
|
4738
5087
|
}
|
|
@@ -4743,7 +5092,7 @@ const factory = env => {
|
|
|
4743
5092
|
['status', 'statusText', 'headers'].forEach(prop => {
|
|
4744
5093
|
options[prop] = response[prop];
|
|
4745
5094
|
});
|
|
4746
|
-
const responseContentLength = utils$1.toFiniteNumber(
|
|
5095
|
+
const responseContentLength = utils$1.toFiniteNumber(responseHeaders.getContentLength());
|
|
4747
5096
|
const [onProgress, flush] = onDownloadProgress && progressEventDecorator(responseContentLength, progressEventReducer(asyncDecorator(onDownloadProgress), true)) || [];
|
|
4748
5097
|
let bytesRead = 0;
|
|
4749
5098
|
const onChunkProgress = loadedBytes => {
|
|
@@ -4802,13 +5151,48 @@ const factory = env => {
|
|
|
4802
5151
|
const canceledError = composedSignal.reason;
|
|
4803
5152
|
canceledError.config = config;
|
|
4804
5153
|
request && (canceledError.request = request);
|
|
4805
|
-
err !== canceledError
|
|
5154
|
+
if (err !== canceledError) {
|
|
5155
|
+
// Non-enumerable to match native Error `cause` semantics so loggers
|
|
5156
|
+
// don't recurse into circular fetch internals (see #7205).
|
|
5157
|
+
Object.defineProperty(canceledError, 'cause', {
|
|
5158
|
+
__proto__: null,
|
|
5159
|
+
value: err,
|
|
5160
|
+
writable: true,
|
|
5161
|
+
enumerable: false,
|
|
5162
|
+
configurable: true
|
|
5163
|
+
});
|
|
5164
|
+
}
|
|
4806
5165
|
throw canceledError;
|
|
4807
5166
|
}
|
|
5167
|
+
|
|
5168
|
+
// Surface a maxBodyLength violation we raised while the request body was
|
|
5169
|
+
// being streamed. Matching by identity (rather than reading
|
|
5170
|
+
// `err.cause.isAxiosError`) keeps the error deterministic across runtimes
|
|
5171
|
+
// and avoids both prototype-pollution reads and mis-attributing a foreign
|
|
5172
|
+
// AxiosError that merely happened to land in `err.cause`.
|
|
5173
|
+
if (pendingBodyError) {
|
|
5174
|
+
request && !pendingBodyError.request && (pendingBodyError.request = request);
|
|
5175
|
+
throw pendingBodyError;
|
|
5176
|
+
}
|
|
5177
|
+
|
|
5178
|
+
// Re-throw AxiosErrors we raised synchronously (data: URL / content-length
|
|
5179
|
+
// pre-checks, response size enforcement) without re-wrapping them.
|
|
5180
|
+
if (err instanceof AxiosError) {
|
|
5181
|
+
request && !err.request && (err.request = request);
|
|
5182
|
+
throw err;
|
|
5183
|
+
}
|
|
4808
5184
|
if (err && err.name === 'TypeError' && /Load failed|fetch/i.test(err.message)) {
|
|
4809
|
-
|
|
4810
|
-
|
|
5185
|
+
const networkError = new AxiosError('Network Error', AxiosError.ERR_NETWORK, config, request, err && err.response);
|
|
5186
|
+
// Non-enumerable to match native Error `cause` semantics so loggers
|
|
5187
|
+
// don't recurse into circular fetch internals (see #7205).
|
|
5188
|
+
Object.defineProperty(networkError, 'cause', {
|
|
5189
|
+
__proto__: null,
|
|
5190
|
+
value: err.cause || err,
|
|
5191
|
+
writable: true,
|
|
5192
|
+
enumerable: false,
|
|
5193
|
+
configurable: true
|
|
4811
5194
|
});
|
|
5195
|
+
throw networkError;
|
|
4812
5196
|
}
|
|
4813
5197
|
throw AxiosError.from(err, err && err.code, config, request, err && err.response);
|
|
4814
5198
|
}
|
|
@@ -4927,7 +5311,7 @@ function getAdapter(adapters, config) {
|
|
|
4927
5311
|
if (!adapter) {
|
|
4928
5312
|
const reasons = Object.entries(rejectedReasons).map(([id, state]) => `adapter ${id} ` + (state === false ? 'is not supported by the environment' : 'is not available in the build'));
|
|
4929
5313
|
let s = length ? reasons.length > 1 ? 'since :\n' + reasons.map(renderReason).join('\n') : ' ' + renderReason(reasons[0]) : 'as no adapter specified';
|
|
4930
|
-
throw new AxiosError(`There is no suitable adapter to dispatch the request ` + s,
|
|
5314
|
+
throw new AxiosError(`There is no suitable adapter to dispatch the request ` + s, AxiosError.ERR_NOT_SUPPORT);
|
|
4931
5315
|
}
|
|
4932
5316
|
return adapter;
|
|
4933
5317
|
}
|
|
@@ -5070,7 +5454,7 @@ validators$1.spelling = function spelling(correctSpelling) {
|
|
|
5070
5454
|
*/
|
|
5071
5455
|
|
|
5072
5456
|
function assertOptions(options, schema, allowUnknown) {
|
|
5073
|
-
if (typeof options !== 'object') {
|
|
5457
|
+
if (typeof options !== 'object' || options === null) {
|
|
5074
5458
|
throw new AxiosError('options must be an object', AxiosError.ERR_BAD_OPTION_VALUE);
|
|
5075
5459
|
}
|
|
5076
5460
|
const keys = Object.keys(options);
|
|
@@ -5180,7 +5564,8 @@ class Axios {
|
|
|
5180
5564
|
forcedJSONParsing: validators.transitional(validators.boolean),
|
|
5181
5565
|
clarifyTimeoutError: validators.transitional(validators.boolean),
|
|
5182
5566
|
legacyInterceptorReqResOrdering: validators.transitional(validators.boolean),
|
|
5183
|
-
advertiseZstdAcceptEncoding: validators.transitional(validators.boolean)
|
|
5567
|
+
advertiseZstdAcceptEncoding: validators.transitional(validators.boolean),
|
|
5568
|
+
validateStatusUndefinedResolves: validators.transitional(validators.boolean)
|
|
5184
5569
|
}, false);
|
|
5185
5570
|
}
|
|
5186
5571
|
if (paramsSerializer != null) {
|
|
@@ -5277,7 +5662,7 @@ class Axios {
|
|
|
5277
5662
|
}
|
|
5278
5663
|
getUri(config) {
|
|
5279
5664
|
config = mergeConfig(this.defaults, config);
|
|
5280
|
-
const fullPath = buildFullPath(config.baseURL, config.url, config.allowAbsoluteUrls);
|
|
5665
|
+
const fullPath = buildFullPath(config.baseURL, config.url, config.allowAbsoluteUrls, config);
|
|
5281
5666
|
return buildURL(fullPath, config.params, config.paramsSerializer);
|
|
5282
5667
|
}
|
|
5283
5668
|
}
|
|
@@ -5289,7 +5674,7 @@ utils$1.forEach(['delete', 'get', 'head', 'options'], function forEachMethodNoDa
|
|
|
5289
5674
|
return this.request(mergeConfig(config || {}, {
|
|
5290
5675
|
method,
|
|
5291
5676
|
url,
|
|
5292
|
-
data: (config
|
|
5677
|
+
data: config && utils$1.hasOwnProp(config, 'data') ? config.data : undefined
|
|
5293
5678
|
}));
|
|
5294
5679
|
};
|
|
5295
5680
|
});
|