axios 1.18.0 → 1.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/README.md +192 -23
  3. package/dist/axios.js +410 -101
  4. package/dist/axios.min.js +3 -3
  5. package/dist/axios.min.js.map +1 -1
  6. package/dist/browser/axios.cjs +484 -119
  7. package/dist/esm/axios.js +484 -119
  8. package/dist/esm/axios.min.js +2 -2
  9. package/dist/esm/axios.min.js.map +1 -1
  10. package/dist/node/axios.cjs +589 -139
  11. package/index.d.cts +114 -74
  12. package/index.d.ts +112 -68
  13. package/lib/adapters/adapters.js +1 -1
  14. package/lib/adapters/fetch.js +27 -12
  15. package/lib/adapters/http.js +95 -34
  16. package/lib/adapters/xhr.js +1 -0
  17. package/lib/core/Axios.js +24 -6
  18. package/lib/core/AxiosError.js +46 -3
  19. package/lib/core/AxiosHeaders.js +124 -1
  20. package/lib/core/buildFullPath.js +45 -7
  21. package/lib/core/mergeConfig.js +19 -3
  22. package/lib/core/setFormDataHeaders.js +27 -0
  23. package/lib/env/data.js +1 -1
  24. package/lib/helpers/AxiosURLSearchParams.js +1 -3
  25. package/lib/helpers/HttpStatusCode.js +1 -0
  26. package/lib/helpers/buildURL.js +1 -0
  27. package/lib/helpers/combineURLs.js +11 -3
  28. package/lib/helpers/composeSignals.js +12 -1
  29. package/lib/helpers/cookies.js +5 -1
  30. package/lib/helpers/estimateDataURLDecodedBytes.js +115 -54
  31. package/lib/helpers/formDataToJSON.js +11 -5
  32. package/lib/helpers/fromDataURI.js +4 -2
  33. package/lib/helpers/parseHeaders.js +5 -3
  34. package/lib/helpers/progressEventReducer.js +3 -3
  35. package/lib/helpers/resolveConfig.js +10 -19
  36. package/lib/helpers/shouldBypassProxy.js +120 -1
  37. package/lib/helpers/toFormData.js +8 -1
  38. package/lib/helpers/validator.js +1 -1
  39. package/lib/platform/node/classes/Buffer.js +11 -0
  40. package/lib/utils.js +17 -5
  41. package/package.json +22 -20
@@ -1,4 +1,4 @@
1
- /*! Axios v1.18.0 Copyright (c) 2026 Matt Zabriskie and contributors */
1
+ /*! Axios v1.19.0 Copyright (c) 2026 Matt Zabriskie and contributors */
2
2
  'use strict';
3
3
 
4
4
  var FormData$1 = require('form-data');
@@ -295,6 +295,7 @@ const isBlob = kindOfTest('Blob');
295
295
  * @returns {boolean} True if value is a FileList, otherwise false
296
296
  */
297
297
  const isFileList = kindOfTest('FileList');
298
+ const isSet = kindOfTest('Set');
298
299
 
299
300
  /**
300
301
  * Determine if a value is a Stream
@@ -817,11 +818,20 @@ const toJSONObject = obj => {
817
818
  if (!('toJSON' in source)) {
818
819
  // add-on descent / delete-on-ascent: preserves path semantics, so DAG nodes serialise at every occurrence (see #7230).
819
820
  visited.add(source);
820
- const target = isArray(source) ? [] : {};
821
- forEach(source, (value, key) => {
822
- const reducedValue = visit(value);
823
- !isUndefined(reducedValue) && (target[key] = reducedValue);
824
- });
821
+ let target;
822
+ if (isSet(source)) {
823
+ target = [];
824
+ for (const value of source) {
825
+ const reducedValue = visit(value);
826
+ !isUndefined(reducedValue) && target.push(reducedValue);
827
+ }
828
+ } else {
829
+ target = isArray(source) ? [] : {};
830
+ forEach(source, (value, key) => {
831
+ const reducedValue = visit(value);
832
+ !isUndefined(reducedValue) && (target[key] = reducedValue);
833
+ });
834
+ }
825
835
  visited.delete(source);
826
836
  return target;
827
837
  }
@@ -995,17 +1005,18 @@ var parseHeaders = rawHeaders => {
995
1005
  i = line.indexOf(':');
996
1006
  key = line.substring(0, i).trim().toLowerCase();
997
1007
  val = line.substring(i + 1).trim();
998
- if (!key || parsed[key] && ignoreDuplicateOf[key]) {
1008
+ const hasKey = utils$1.hasOwnProp(parsed, key);
1009
+ if (!key || hasKey && utils$1.hasOwnProp(ignoreDuplicateOf, key)) {
999
1010
  return;
1000
1011
  }
1001
1012
  if (key === 'set-cookie') {
1002
- if (parsed[key]) {
1013
+ if (hasKey) {
1003
1014
  parsed[key].push(val);
1004
1015
  } else {
1005
1016
  parsed[key] = [val];
1006
1017
  }
1007
1018
  } else {
1008
- parsed[key] = parsed[key] ? parsed[key] + ', ' + val : val;
1019
+ parsed[key] = hasKey ? parsed[key] + ', ' + val : val;
1009
1020
  }
1010
1021
  });
1011
1022
  return parsed;
@@ -1071,6 +1082,90 @@ function parseTokens(str) {
1071
1082
  }
1072
1083
  return tokens;
1073
1084
  }
1085
+ const parameterNameRE = /^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/;
1086
+ function trimOWS(value) {
1087
+ let start = 0;
1088
+ let end = value.length;
1089
+ while (start < end) {
1090
+ const code = value.charCodeAt(start);
1091
+ if (code !== 0x09 && code !== 0x20) {
1092
+ break;
1093
+ }
1094
+ start += 1;
1095
+ }
1096
+ while (end > start) {
1097
+ const code = value.charCodeAt(end - 1);
1098
+ if (code !== 0x09 && code !== 0x20) {
1099
+ break;
1100
+ }
1101
+ end -= 1;
1102
+ }
1103
+ return start === 0 && end === value.length ? value : value.slice(start, end);
1104
+ }
1105
+ function decodeQuotedString(value) {
1106
+ const last = value.length - 1;
1107
+ if (last < 1 || value.charCodeAt(0) !== 0x22 || value.charCodeAt(last) !== 0x22) {
1108
+ return value;
1109
+ }
1110
+ let decoded = '';
1111
+ for (let i = 1; i < last; i++) {
1112
+ const code = value.charCodeAt(i);
1113
+ if (code === 0x22) {
1114
+ return value;
1115
+ }
1116
+ if (code === 0x5c) {
1117
+ i += 1;
1118
+ if (i >= last) {
1119
+ return value;
1120
+ }
1121
+ }
1122
+ decoded += value[i];
1123
+ }
1124
+ return decoded;
1125
+ }
1126
+ function parseParameters(value) {
1127
+ const parameters = Object.create(null);
1128
+ const str = String(value);
1129
+ let start = 0;
1130
+ let quoted = false;
1131
+ let escaped = false;
1132
+ function parseParameter(end) {
1133
+ const part = trimOWS(str.slice(start, end));
1134
+ const equals = part.indexOf('=');
1135
+ if (equals < 1) {
1136
+ return;
1137
+ }
1138
+ const name = trimOWS(part.slice(0, equals));
1139
+ if (!parameterNameRE.test(name)) {
1140
+ return;
1141
+ }
1142
+ const normalizedName = name.toLowerCase();
1143
+ if (normalizedName === '__proto__' || normalizedName === 'constructor' || normalizedName === 'prototype') {
1144
+ return;
1145
+ }
1146
+ const parameterValue = trimOWS(part.slice(equals + 1));
1147
+ parameters[normalizedName] = decodeQuotedString(parameterValue);
1148
+ }
1149
+ for (let i = 0; i < str.length; i++) {
1150
+ const code = str.charCodeAt(i);
1151
+ if (quoted) {
1152
+ if (escaped) {
1153
+ escaped = false;
1154
+ } else if (code === 0x5c) {
1155
+ escaped = true;
1156
+ } else if (code === 0x22) {
1157
+ quoted = false;
1158
+ }
1159
+ } else if (code === 0x22) {
1160
+ quoted = true;
1161
+ } else if (code === 0x2c || code === 0x3b) {
1162
+ parseParameter(i);
1163
+ start = i + 1;
1164
+ }
1165
+ }
1166
+ parseParameter(str.length);
1167
+ return parameters;
1168
+ }
1074
1169
  const isValidHeaderName = str => /^[-_a-zA-Z0-9^`|~,!#$%&'*+.]+$/.test(str.trim());
1075
1170
  function matchHeaderValue(context, value, header, filter, isHeaderNameFilter) {
1076
1171
  if (utils$1.isFunction(filter)) {
@@ -1248,7 +1343,8 @@ class AxiosHeaders {
1248
1343
  return Object.entries(this.toJSON()).map(([header, value]) => header + ': ' + value).join('\n');
1249
1344
  }
1250
1345
  getSetCookie() {
1251
- return this.get('set-cookie') || [];
1346
+ const value = this.get('set-cookie');
1347
+ return utils$1.isArray(value) ? value : value == null || value === false ? [] : [value];
1252
1348
  }
1253
1349
  get [Symbol.toStringTag]() {
1254
1350
  return 'AxiosHeaders';
@@ -1256,6 +1352,9 @@ class AxiosHeaders {
1256
1352
  static from(thing) {
1257
1353
  return thing instanceof this ? thing : new this(thing);
1258
1354
  }
1355
+ static parseParameters(value) {
1356
+ return parseParameters(value);
1357
+ }
1259
1358
  static concat(first, ...targets) {
1260
1359
  const computed = new this(first);
1261
1360
  targets.forEach(target => computed.set(target));
@@ -1350,10 +1449,46 @@ function redactConfig(config, redactKeys) {
1350
1449
  };
1351
1450
  return visit(config);
1352
1451
  }
1452
+ function stringifySafely$1(value) {
1453
+ try {
1454
+ return String(value);
1455
+ } catch (err) {
1456
+ return '';
1457
+ }
1458
+ }
1459
+ function aggregateErrorMessage(error) {
1460
+ const message = error.errors.map(entry => {
1461
+ try {
1462
+ return entry && entry.message ? stringifySafely$1(entry.message) : stringifySafely$1(entry);
1463
+ } catch (err) {
1464
+ return '';
1465
+ }
1466
+ }).filter(Boolean).join('; ');
1467
+ return message || error.name || 'AggregateError';
1468
+ }
1353
1469
  class AxiosError extends Error {
1354
1470
  static from(error, code, config, request, response, customProps) {
1355
- const axiosError = new AxiosError(error.message, code || error.code, config, request, response);
1356
- axiosError.cause = error;
1471
+ // `AggregateError` (thrown by Node on dual-stack/Happy-Eyeballs connection
1472
+ // failures) has an empty `message`; its detail lives in `errors[]`. Without
1473
+ // this, the wrapped error surfaces with a blank message (see #6721).
1474
+ let message = error.message;
1475
+ if (!message && utils$1.isArray(error.errors) && error.errors.length) {
1476
+ message = aggregateErrorMessage(error);
1477
+ }
1478
+ const axiosError = new AxiosError(message, code || error.code, config, request, response);
1479
+ // Match native `Error` `cause` semantics: non-enumerable. The wrapped
1480
+ // error often carries circular internals (sockets, requests, agents), so
1481
+ // an enumerable `cause` makes structured loggers (pino/winston) and any
1482
+ // own-property walk throw "Converting circular structure to JSON".
1483
+ // Regression from #6982; see #7205. `__proto__: null` mirrors the
1484
+ // `message` descriptor below (prototype-pollution-safe descriptor).
1485
+ Object.defineProperty(axiosError, 'cause', {
1486
+ __proto__: null,
1487
+ value: error,
1488
+ writable: true,
1489
+ enumerable: false,
1490
+ configurable: true
1491
+ });
1357
1492
  axiosError.name = error.name;
1358
1493
 
1359
1494
  // Preserve status from the original error if not already set from response
@@ -1444,6 +1579,15 @@ AxiosError.ERR_NOT_SUPPORT = 'ERR_NOT_SUPPORT';
1444
1579
  AxiosError.ERR_INVALID_URL = 'ERR_INVALID_URL';
1445
1580
  AxiosError.ERR_FORM_DATA_DEPTH_EXCEEDED = 'ERR_FORM_DATA_DEPTH_EXCEEDED';
1446
1581
 
1582
+ var PlatformBuffer = {
1583
+ isBufferAvailable() {
1584
+ return typeof Buffer !== 'undefined';
1585
+ },
1586
+ from(value) {
1587
+ return Buffer.from(value);
1588
+ }
1589
+ };
1590
+
1447
1591
  // Default nesting limit shared with the inverse transform (formDataToJSON) so
1448
1592
  // the FormData <-> JSON round-trip stays symmetric.
1449
1593
  const DEFAULT_FORM_DATA_MAX_DEPTH = 100;
@@ -1566,7 +1710,13 @@ function toFormData(obj, formData, options) {
1566
1710
  throw new AxiosError('Blob is not supported. Use a Buffer instead.');
1567
1711
  }
1568
1712
  if (utils$1.isArrayBuffer(value) || utils$1.isTypedArray(value)) {
1569
- return useBlob && typeof Blob === 'function' ? new Blob([value]) : Buffer.from(value);
1713
+ if (useBlob && typeof _Blob === 'function') {
1714
+ return new _Blob([value]);
1715
+ }
1716
+ if (PlatformBuffer && PlatformBuffer.isBufferAvailable()) {
1717
+ return PlatformBuffer.from(value);
1718
+ }
1719
+ throw new AxiosError('Blob is not supported. Use a Buffer instead.', AxiosError.ERR_NOT_SUPPORT);
1570
1720
  }
1571
1721
  return value;
1572
1722
  }
@@ -1698,9 +1848,7 @@ prototype.append = function append(name, value) {
1698
1848
  this._pairs.push([name, value]);
1699
1849
  };
1700
1850
  prototype.toString = function toString(encoder) {
1701
- const _encode = encoder ? function (value) {
1702
- return encoder.call(this, value, encode$1);
1703
- } : encode$1;
1851
+ const _encode = encoder ? value => encoder.call(this, value, encode$1) : encode$1;
1704
1852
  return this._pairs.map(function each(pair) {
1705
1853
  return _encode(pair[0]) + '=' + _encode(pair[1]);
1706
1854
  }, '').join('&');
@@ -1731,6 +1879,7 @@ function buildURL(url, params, options) {
1731
1879
  if (!params) {
1732
1880
  return url;
1733
1881
  }
1882
+ url = url || '';
1734
1883
  const _options = utils$1.isFunction(options) ? {
1735
1884
  serialize: options
1736
1885
  } : options;
@@ -1945,12 +2094,18 @@ function throwIfDepthExceeded(index) {
1945
2094
  * @returns An array of strings.
1946
2095
  */
1947
2096
  function parsePropPath(name) {
1948
- // foo[x][y][z]
1949
- // foo.x.y.z
1950
- // foo-x-y-z
1951
- // foo x y z
2097
+ // foo[x][y][z] -> ['foo', 'x', 'y', 'z']
2098
+ // foo.x.y.z -> ['foo', 'x', 'y', 'z']
2099
+ // A path is split on `.` and on `[...]` groups. A segment — whether written
2100
+ // in dot notation or captured inside brackets — may contain any character
2101
+ // except `.`, `[` and `]`, so a key like `user-name` or `user name` is kept
2102
+ // literal instead of being split (#5402). `.`, `[` and `]` keep their existing
2103
+ // meaning, e.g. `foo[bar.baz]` -> ['foo', 'bar', 'baz'] and `[]` is an array push.
2104
+ // Excluding `[` from the bracket group also makes the match fail fast at the
2105
+ // next `[`, so a malformed name cannot rescan to the end of the string from
2106
+ // every unmatched `[` — parsing stays linear in the length of the name.
1952
2107
  const path = [];
1953
- const pattern = /\w+|\[(\w*)]/g;
2108
+ const pattern = /[^.[\]]+|\[([^.[\]]*)]/g;
1954
2109
  let match;
1955
2110
  while ((match = pattern.exec(name)) !== null) {
1956
2111
  throwIfDepthExceeded(path.length);
@@ -2226,7 +2381,14 @@ function isAbsoluteURL(url) {
2226
2381
  * @returns {string} The combined URL
2227
2382
  */
2228
2383
  function combineURLs(baseURL, relativeURL) {
2229
- return relativeURL ? baseURL.replace(/\/?\/$/, '') + '/' + relativeURL.replace(/^\/+/, '') : baseURL;
2384
+ if (!relativeURL) {
2385
+ return baseURL;
2386
+ }
2387
+ let end = baseURL.length;
2388
+ while (end > 0 && baseURL.charCodeAt(end - 1) === 47) {
2389
+ end--;
2390
+ }
2391
+ return baseURL.slice(0, end) + '/' + relativeURL.replace(/^\/+/, '');
2230
2392
  }
2231
2393
 
2232
2394
  const malformedHttpProtocol = /^https?:(?!\/\/)/i;
@@ -2241,9 +2403,39 @@ function stripLeadingC0ControlOrSpace(url) {
2241
2403
  function normalizeURLForProtocolCheck(url) {
2242
2404
  return stripLeadingC0ControlOrSpace(url).replace(httpProtocolControlCharacters, '');
2243
2405
  }
2406
+
2407
+ // Redact the parts of a URL that can carry secrets before it is embedded in an
2408
+ // error message. AxiosError.toJSON() serializes `message` verbatim and errors
2409
+ // are commonly logged, while the opt-in `config.redact` model only cleans
2410
+ // config keys — it cannot reach the message. Redact only the genuinely
2411
+ // sensitive substrings — userinfo (credentials), query parameter values and
2412
+ // fragment contents — with the same REDACTED marker the config redaction uses,
2413
+ // while keeping the scheme, host, path and parameter names so the offending
2414
+ // request stays accurately identifiable.
2415
+ function redactFragment(fragment) {
2416
+ if (!fragment) {
2417
+ return fragment;
2418
+ }
2419
+ return fragment.replace(/(^|&)([^=&]*=)?[^&]+/g, (match, separator, parameterName = '') => {
2420
+ return `${separator}${parameterName}${REDACTED}`;
2421
+ });
2422
+ }
2423
+ function redactSensitiveURLParts(url) {
2424
+ const redactedURL = url.replace(/^(https?:\/{0,2})[^/?#]*@/i, `$1${REDACTED}@`);
2425
+ const fragmentIndex = redactedURL.indexOf('#');
2426
+ const urlWithoutFragment = fragmentIndex === -1 ? redactedURL : redactedURL.slice(0, fragmentIndex);
2427
+ const redactedURLWithoutFragment = urlWithoutFragment.replace(/([?&][^=&#]*=)[^&#]*/g, `$1${REDACTED}`);
2428
+ if (fragmentIndex === -1) {
2429
+ return redactedURLWithoutFragment;
2430
+ }
2431
+ return `${redactedURLWithoutFragment}#${redactFragment(redactedURL.slice(fragmentIndex + 1))}`;
2432
+ }
2244
2433
  function assertValidHttpProtocolURL(url, config) {
2245
- if (typeof url === 'string' && malformedHttpProtocol.test(normalizeURLForProtocolCheck(url))) {
2246
- throw new AxiosError('Invalid URL: missing "//" after protocol', AxiosError.ERR_INVALID_URL, config);
2434
+ if (typeof url === 'string') {
2435
+ const normalizedURL = normalizeURLForProtocolCheck(url);
2436
+ if (malformedHttpProtocol.test(normalizedURL)) {
2437
+ throw new AxiosError(`Invalid URL ${JSON.stringify(redactSensitiveURLParts(normalizedURL))}: missing "//" after protocol`, AxiosError.ERR_INVALID_URL, config);
2438
+ }
2247
2439
  }
2248
2440
  }
2249
2441
 
@@ -2363,7 +2555,7 @@ function getEnv(key) {
2363
2555
  return process.env[key.toLowerCase()] || process.env[key.toUpperCase()] || '';
2364
2556
  }
2365
2557
 
2366
- const VERSION = "1.18.0";
2558
+ const VERSION = "1.19.0";
2367
2559
 
2368
2560
  function parseProtocol(url) {
2369
2561
  const match = /^([-+\w]{1,25}):(?:\/\/)?/.exec(url);
@@ -2403,13 +2595,13 @@ function fromDataURI(uri, asBlob, options) {
2403
2595
 
2404
2596
  // RFC 2397 section 3: default mediatype is text/plain;charset=US-ASCII
2405
2597
  // Bare `data:,` leaves mime undefined; Blob normalises that to "" per spec.
2406
- let mime;
2598
+ let mime = '';
2407
2599
  if (type) {
2408
2600
  mime = params ? type + params : type;
2409
2601
  } else if (params) {
2410
2602
  mime = 'text/plain' + params;
2411
2603
  }
2412
- const buffer = Buffer.from(decodeURIComponent(body), encoding);
2604
+ const buffer = encoding === 'base64' ? Buffer.from(body, 'base64') : Buffer.from(decodeURIComponent(body), encoding);
2413
2605
  if (asBlob) {
2414
2606
  if (!_Blob) {
2415
2607
  throw new AxiosError('Blob is not supported', AxiosError.ERR_NOT_SUPPORT);
@@ -2423,6 +2615,31 @@ function fromDataURI(uri, asBlob, options) {
2423
2615
  throw new AxiosError('Unsupported protocol ' + protocol, AxiosError.ERR_NOT_SUPPORT);
2424
2616
  }
2425
2617
 
2618
+ const FORM_DATA_CONTENT_HEADERS = ['content-type', 'content-length'];
2619
+
2620
+ /**
2621
+ * Apply the headers generated by a FormData implementation to the request headers,
2622
+ * honoring the `formDataHeaderPolicy` option: with 'content-only', copy only the
2623
+ * content-* headers; otherwise merge all of them.
2624
+ *
2625
+ * @param {AxiosHeaders} headers - the request headers to mutate
2626
+ * @param {Object | null | undefined} formHeaders - headers produced by the FormData implementation
2627
+ * @param {String} [policy] - the resolved `formDataHeaderPolicy` config value
2628
+ *
2629
+ * @returns {void}
2630
+ */
2631
+ function setFormDataHeaders(headers, formHeaders, policy) {
2632
+ if (policy !== 'content-only') {
2633
+ headers.set(formHeaders);
2634
+ return;
2635
+ }
2636
+ Object.entries(formHeaders || {}).forEach(([key, val]) => {
2637
+ if (FORM_DATA_CONTENT_HEADERS.includes(key.toLowerCase())) {
2638
+ headers.set(key, val);
2639
+ }
2640
+ });
2641
+ }
2642
+
2426
2643
  const kInternals = Symbol('internals');
2427
2644
  class AxiosTransformStream extends stream.Transform {
2428
2645
  constructor(options) {
@@ -2753,6 +2970,104 @@ const isIPv4Loopback = host => {
2753
2970
  if (parts[0] !== '127') return false;
2754
2971
  return parts.every(p => /^\d+$/.test(p) && Number(p) >= 0 && Number(p) <= 255);
2755
2972
  };
2973
+
2974
+ /**
2975
+ * Canonicalize an IPv4 address written in shorthand, octal, or hex form into
2976
+ * dotted-decimal. IPv6 addresses and non-IP strings are returned unchanged so
2977
+ * the existing IPv4-mapped IPv6 unmap path and the isLoopback path can still
2978
+ * see them.
2979
+ *
2980
+ * Shorthand expansion mirrors Node's URL parser: literal parts fill from the
2981
+ * left, the final part fills the remaining octets from the right with
2982
+ * zero-padding on the left.
2983
+ * 127.1 -> 127.0.0.1
2984
+ * 127.0.1 -> 127.0.0.1
2985
+ * 1.2.3 -> 1.2.0.3
2986
+ *
2987
+ * Each octet is parsed with an explicit base: 16 for `0x`/`0X` prefix, 8 for
2988
+ * zero-prefixed multi-digit all-`0-7` parts, 10 otherwise. Zero-prefixed
2989
+ * decimal-looking parts that contain `8` or `9` are rejected to match Node's
2990
+ * URL parser, and the comparison layer falls through to non-bypass if either
2991
+ * side rejects the form (fail-safe).
2992
+ *
2993
+ * Returns the input unchanged on any parse failure, out-of-range octet, or
2994
+ * unusual shape (1-part, 5+ parts) so the comparison layer fails closed.
2995
+ */
2996
+ const parseIPv4Octet = text => {
2997
+ if (/^0[xX][0-9a-fA-F]+$/.test(text)) {
2998
+ const n = parseInt(text.slice(2), 16);
2999
+ return Number.isFinite(n) ? n : null;
3000
+ }
3001
+ if (text.length > 1 && /^0[0-7]+$/.test(text)) {
3002
+ const n = parseInt(text, 8);
3003
+ return Number.isFinite(n) ? n : null;
3004
+ }
3005
+ if (text.length > 1 && /^0[0-9]+$/.test(text)) {
3006
+ return null;
3007
+ }
3008
+ if (/^[0-9]+$/.test(text)) {
3009
+ const n = parseInt(text, 10);
3010
+ return Number.isFinite(n) ? n : null;
3011
+ }
3012
+ return null;
3013
+ };
3014
+ const normalizeIPAddress = host => {
3015
+ if (typeof host !== 'string' || !host || host.indexOf(':') !== -1) {
3016
+ return host;
3017
+ }
3018
+ let h = host;
3019
+ if (h.charAt(0) === '[' && h.charAt(h.length - 1) === ']') {
3020
+ h = h.slice(1, -1);
3021
+ }
3022
+ h = h.replace(/\.+$/, '');
3023
+
3024
+ // Allowed characters for any IPv4 shape: digits, dot, 'x', 'X', hex digits.
3025
+ if (!/^[0-9.xXa-fA-F]+$/.test(h)) return host;
3026
+ const parts = h.split('.');
3027
+
3028
+ // No part may be empty (e.g. "127..0.1" or "127.0.0."). Trailing dots are
3029
+ // already stripped above; this guards against the empty-middle case.
3030
+ if (parts.some(p => p === '')) return host;
3031
+ if (parts.length === 4) {
3032
+ // Full IPv4 form: each part is an octet.
3033
+ const octets = parts.map(parseIPv4Octet);
3034
+ if (octets.some(n => n === null || n < 0 || n > 255)) return host;
3035
+ return octets.join('.');
3036
+ }
3037
+ if (parts.length > 4) {
3038
+ return host;
3039
+ }
3040
+
3041
+ // Shorthand: 1..3 parts. Node's URL parser treats a 1-part input as a 32-bit
3042
+ // integer split into octets, which has surprising semantics (e.g. "127" ->
3043
+ // "0.0.0.127"). Reject 1-part inputs to keep the helper predictable: the
3044
+ // fail-safe returns the input unchanged and the comparison layer falls
3045
+ // through to non-bypass.
3046
+ if (parts.length === 1) return host;
3047
+
3048
+ // 2..3 parts: literal parts fill from the left, tail fills remaining octets
3049
+ // from the right with zero-padding.
3050
+ const literalOctets = parts.slice(0, -1);
3051
+ const tail = parts[parts.length - 1];
3052
+ const tailSlots = 4 - literalOctets.length;
3053
+
3054
+ // Tail is parsed as a full IPv4 number (hex/octal/decimal) and packed
3055
+ // low-byte-right into the remaining octets, matching Node's URL parser.
3056
+ // e.g. 127.65535 (tail 0xFFFF into 3 slots) -> 127.0.255.255;
3057
+ // 127.0x00ff (tail 0xFF into 3 slots) -> 127.0.0.255;
3058
+ // 127.0.65535 (tail 0xFFFF into 2 slots) -> 127.0.255.255.
3059
+ const tailValue = parseIPv4Octet(tail);
3060
+ if (tailValue === null) return host;
3061
+ const maxTail = (1 << 8 * tailSlots) - 1;
3062
+ if (tailValue < 0 || tailValue > maxTail) return host;
3063
+ const tailOctets = new Array(tailSlots).fill(0);
3064
+ for (let i = tailSlots - 1, v = tailValue; i >= 0; i--, v >>= 8) {
3065
+ tailOctets[i] = v & 0xff;
3066
+ }
3067
+ const literal = literalOctets.map(parseIPv4Octet);
3068
+ if (literal.some(n => n === null || n < 0 || n > 255)) return host;
3069
+ return [...literal, ...tailOctets].join('.');
3070
+ };
2756
3071
  const isIPv6ZeroGroup = group => /^0{1,4}$/.test(group);
2757
3072
 
2758
3073
  // The unspecified address (IPv4 0.0.0.0 / IPv6 ::) resolves to the local host
@@ -2866,7 +3181,15 @@ const normalizeNoProxyHost = hostname => {
2866
3181
  if (hostname.charAt(0) === '[' && hostname.charAt(hostname.length - 1) === ']') {
2867
3182
  hostname = hostname.slice(1, -1);
2868
3183
  }
2869
- return unmapIPv4MappedIPv6(hostname.replace(/\.+$/, ''));
3184
+ const trimmed = hostname.replace(/\.+$/, '');
3185
+
3186
+ // IPv4 shorthand/octal/hex → dotted-decimal; helper is a no-op for inputs
3187
+ // containing ':' (IPv6 and IPv4-mapped IPv6) so we fall through to unmap.
3188
+ const ipv4 = normalizeIPAddress(trimmed);
3189
+ if (ipv4 !== trimmed) {
3190
+ return ipv4;
3191
+ }
3192
+ return unmapIPv4MappedIPv6(trimmed);
2870
3193
  };
2871
3194
  function shouldBypassProxy(location) {
2872
3195
  let parsed;
@@ -2888,6 +3211,9 @@ function shouldBypassProxy(location) {
2888
3211
  if (!entry) {
2889
3212
  return false;
2890
3213
  }
3214
+ if (entry === '*') {
3215
+ return true;
3216
+ }
2891
3217
  let [entryHost, entryPort] = parseNoProxyEntry(entry);
2892
3218
  entryHost = normalizeNoProxyHost(entryHost);
2893
3219
  if (!entryHost) {
@@ -2994,7 +3320,7 @@ const progressEventReducer = (listener, isDownloadStream, freq = 3) => {
2994
3320
  }
2995
3321
  const rawLoaded = e.loaded;
2996
3322
  const total = e.lengthComputable ? e.total : undefined;
2997
- const loaded = total != null ? Math.min(rawLoaded, total) : rawLoaded;
3323
+ const loaded = Math.max(0, total != null ? Math.min(rawLoaded, total) : rawLoaded);
2998
3324
  const progressBytes = Math.max(0, loaded - bytesNotified);
2999
3325
  const rate = _speedometer(progressBytes);
3000
3326
  bytesNotified = Math.max(bytesNotified, loaded);
@@ -3020,20 +3346,85 @@ const progressEventDecorator = (total, throttled) => {
3020
3346
  loaded
3021
3347
  }), throttled[1]];
3022
3348
  };
3023
- const asyncDecorator = fn => (...args) => utils$1.asap(() => fn(...args));
3349
+ const asyncDecorator = (fn, scheduler = utils$1.asap) => (...args) => scheduler(() => fn(...args));
3024
3350
 
3025
3351
  /**
3026
- * Estimate decoded byte length of a data:// URL *without* allocating large buffers.
3027
- * - For base64: compute exact decoded size using length and padding;
3028
- * handle %XX at the character-count level (no string allocation).
3029
- * - For non-base64: compute the exact percent-decoded UTF-8 byte length.
3030
- *
3031
- * @param {string} url
3032
- * @returns {number}
3352
+ * Estimate data: URL byte lengths *without* allocating large buffers.
3353
+ * - Fetch percent-decodes a base64 body before decoding it.
3354
+ * - Node's Buffer.from(body, 'base64') sizes its backing allocation from the
3355
+ * raw body, including ignored characters and content after padding.
3356
+ * - Non-base64 data is percent-decoded and then encoded as UTF-8.
3033
3357
  */
3034
3358
  const isHexDigit = charCode => charCode >= 48 && charCode <= 57 || charCode >= 65 && charCode <= 70 || charCode >= 97 && charCode <= 102;
3035
3359
  const isPercentEncodedByte = (str, i, len) => i + 2 < len && isHexDigit(str.charCodeAt(i + 1)) && isHexDigit(str.charCodeAt(i + 2));
3036
- function estimateDataURLDecodedBytes(url) {
3360
+ const hexValue = charCode => charCode <= 57 ? charCode - 48 : (charCode & 0xdf) - 55;
3361
+ const isBase64Char = charCode => charCode >= 65 && charCode <= 90 ||
3362
+ // A-Z
3363
+ charCode >= 97 && charCode <= 122 ||
3364
+ // a-z
3365
+ charCode >= 48 && charCode <= 57 ||
3366
+ // 0-9
3367
+ charCode === 43 ||
3368
+ // +
3369
+ charCode === 47 ||
3370
+ // /
3371
+ charCode === 45 ||
3372
+ // - (base64url)
3373
+ charCode === 95; // _ (base64url)
3374
+
3375
+ const isBase64Whitespace = charCode => charCode === 9 || charCode === 10 || charCode === 12 || charCode === 13 || charCode === 32;
3376
+ const base64Bytes = significant => {
3377
+ const groups = Math.floor(significant / 4);
3378
+ const remainder = significant % 4;
3379
+ return groups * 3 + (remainder === 2 ? 1 : remainder === 3 ? 2 : 0);
3380
+ };
3381
+
3382
+ // Buffer.byteLength(body, 'base64') uses the raw string length as an allocation
3383
+ // upper bound even when Buffer.from later ignores characters or stops at '='.
3384
+ const estimateBase64BufferAllocation = body => {
3385
+ const len = body.length;
3386
+ let padding = 0;
3387
+ if (len > 0 && body.charCodeAt(len - 1) === 61 /* '=' */) {
3388
+ padding++;
3389
+ if (len > 1 && body.charCodeAt(len - 2) === 61 /* '=' */) {
3390
+ padding++;
3391
+ }
3392
+ }
3393
+ return Math.floor((len - padding) * 3 / 4);
3394
+ };
3395
+ const estimatePercentDecodedBase64Bytes = body => {
3396
+ const len = body.length;
3397
+ let significant = 0;
3398
+ let padding = 0;
3399
+ let invalid = false;
3400
+ for (let i = 0; i < len; i++) {
3401
+ let code = body.charCodeAt(i);
3402
+ if (code === 37 /* '%' */ && isPercentEncodedByte(body, i, len)) {
3403
+ code = hexValue(body.charCodeAt(i + 1)) * 16 + hexValue(body.charCodeAt(i + 2));
3404
+ i += 2;
3405
+ }
3406
+ if (isBase64Whitespace(code)) {
3407
+ continue;
3408
+ }
3409
+ if (code === 61 /* '=' */) {
3410
+ padding++;
3411
+ continue;
3412
+ }
3413
+ if (!isBase64Char(code) || padding > 0) {
3414
+ invalid = true;
3415
+ continue;
3416
+ }
3417
+ significant++;
3418
+ }
3419
+
3420
+ // Fetch rejects malformed forgiving-base64 input. Returning the raw-size
3421
+ // allocation bound keeps that invalid input from becoming a pre-check bypass.
3422
+ if (invalid || padding > 2 || padding > 0 && (significant + padding) % 4 !== 0 || significant % 4 === 1) {
3423
+ return estimateBase64BufferAllocation(body);
3424
+ }
3425
+ return base64Bytes(significant);
3426
+ };
3427
+ const estimateDataURLBytes = (url, estimateBase64) => {
3037
3428
  if (!url || typeof url !== 'string') return 0;
3038
3429
  if (!url.startsWith('data:')) return 0;
3039
3430
  const comma = url.indexOf(',');
@@ -3042,47 +3433,7 @@ function estimateDataURLDecodedBytes(url) {
3042
3433
  const body = url.slice(comma + 1);
3043
3434
  const isBase64 = /;base64/i.test(meta);
3044
3435
  if (isBase64) {
3045
- let effectiveLen = body.length;
3046
- const len = body.length; // cache length
3047
-
3048
- for (let i = 0; i < len; i++) {
3049
- if (body.charCodeAt(i) === 37 /* '%' */ && i + 2 < len) {
3050
- const a = body.charCodeAt(i + 1);
3051
- const b = body.charCodeAt(i + 2);
3052
- const isHex = isHexDigit(a) && isHexDigit(b);
3053
- if (isHex) {
3054
- effectiveLen -= 2;
3055
- i += 2;
3056
- }
3057
- }
3058
- }
3059
- let pad = 0;
3060
- let idx = len - 1;
3061
- const tailIsPct3D = j => j >= 2 && body.charCodeAt(j - 2) === 37 &&
3062
- // '%'
3063
- body.charCodeAt(j - 1) === 51 && (
3064
- // '3'
3065
- body.charCodeAt(j) === 68 || body.charCodeAt(j) === 100); // 'D' or 'd'
3066
-
3067
- if (idx >= 0) {
3068
- if (body.charCodeAt(idx) === 61 /* '=' */) {
3069
- pad++;
3070
- idx--;
3071
- } else if (tailIsPct3D(idx)) {
3072
- pad++;
3073
- idx -= 3;
3074
- }
3075
- }
3076
- if (pad === 1 && idx >= 0) {
3077
- if (body.charCodeAt(idx) === 61 /* '=' */) {
3078
- pad++;
3079
- } else if (tailIsPct3D(idx)) {
3080
- pad++;
3081
- }
3082
- }
3083
- const groups = Math.floor(effectiveLen / 4);
3084
- const bytes = groups * 3 - (pad || 0);
3085
- return bytes > 0 ? bytes : 0;
3436
+ return estimateBase64(body);
3086
3437
  }
3087
3438
 
3088
3439
  // Compute UTF-8 byte length directly from UTF-16 code units without allocating
@@ -3112,6 +3463,28 @@ function estimateDataURLDecodedBytes(url) {
3112
3463
  }
3113
3464
  }
3114
3465
  return bytes;
3466
+ };
3467
+
3468
+ /**
3469
+ * Estimate the percent-decoded payload size used by Fetch data: URLs.
3470
+ *
3471
+ * @param {string} url
3472
+ * @returns {number}
3473
+ */
3474
+ function estimateDataURLDecodedBytes(url) {
3475
+ // Fetch removes URL fragments before processing a data: URL.
3476
+ const fragmentIndex = typeof url === 'string' ? url.indexOf('#') : -1;
3477
+ return estimateDataURLBytes(fragmentIndex === -1 ? url : url.slice(0, fragmentIndex), estimatePercentDecodedBase64Bytes);
3478
+ }
3479
+
3480
+ /**
3481
+ * Estimate the Buffer backing allocation used by Node's raw base64 decoder.
3482
+ *
3483
+ * @param {string} url
3484
+ * @returns {number}
3485
+ */
3486
+ function estimateDataURLBufferAllocation(url) {
3487
+ return estimateDataURLBytes(url, estimateBase64BufferAllocation);
3115
3488
  }
3116
3489
 
3117
3490
  const zlibOptions = {
@@ -3130,23 +3503,12 @@ const isBrotliSupported = utils$1.isFunction(zlib.createBrotliDecompress);
3130
3503
  const isZstdSupported = utils$1.isFunction(zlib.createZstdDecompress);
3131
3504
  const ACCEPT_ENCODING = 'gzip, compress, deflate' + (isBrotliSupported ? ', br' : '');
3132
3505
  const ACCEPT_ENCODING_WITH_ZSTD = ACCEPT_ENCODING + (isZstdSupported ? ', zstd' : '');
3506
+ const scheduleProgress = typeof process !== 'undefined' && process.nextTick ? process.nextTick.bind(process) : utils$1.asap;
3133
3507
  const {
3134
3508
  http: httpFollow,
3135
3509
  https: httpsFollow
3136
3510
  } = followRedirects;
3137
3511
  const isHttps = /https:?/;
3138
- const FORM_DATA_CONTENT_HEADERS$1 = ['content-type', 'content-length'];
3139
- function setFormDataHeaders$1(headers, formHeaders, policy) {
3140
- if (policy !== 'content-only') {
3141
- headers.set(formHeaders);
3142
- return;
3143
- }
3144
- Object.entries(formHeaders).forEach(([key, val]) => {
3145
- if (FORM_DATA_CONTENT_HEADERS$1.includes(key.toLowerCase())) {
3146
- headers.set(key, val);
3147
- }
3148
- });
3149
- }
3150
3512
 
3151
3513
  // Symbols used to bind a single 'error' listener to a pooled socket and track
3152
3514
  // the request currently owning that socket across keep-alive reuse (issue #10780).
@@ -3164,6 +3526,36 @@ const kAxiosInstalledTunnel = Symbol('axios.http.installedTunnel');
3164
3526
  // so unbounded growth is not a concern in practice.
3165
3527
  const tunnelingAgentCache = new Map();
3166
3528
  const tunnelingAgentCacheUser = new WeakMap();
3529
+ // Minimum minor versions where Node's HTTP Agent supports native proxyEnv
3530
+ // handling. Checking the selected agent below also covers startup modes such
3531
+ // as NODE_OPTIONS=--use-env-proxy and --no-use-env-proxy precedence.
3532
+ const NODE_NATIVE_ENV_PROXY_SUPPORT = {
3533
+ 22: 21,
3534
+ 24: 5
3535
+ };
3536
+ function isNodeNativeEnvProxySupported(nodeVersion = process.versions && process.versions.node) {
3537
+ if (!nodeVersion) {
3538
+ return false;
3539
+ }
3540
+ const [major, minor] = nodeVersion.split('.').map(part => Number(part));
3541
+ if (!Number.isInteger(major) || !Number.isInteger(minor)) {
3542
+ return false;
3543
+ }
3544
+ if (major > 24) {
3545
+ return true;
3546
+ }
3547
+ return NODE_NATIVE_ENV_PROXY_SUPPORT[major] != null && minor >= NODE_NATIVE_ENV_PROXY_SUPPORT[major];
3548
+ }
3549
+ function isNodeEnvProxyEnabled(agent, nodeVersion = process.versions && process.versions.node) {
3550
+ if (!isNodeNativeEnvProxySupported(nodeVersion)) {
3551
+ return false;
3552
+ }
3553
+ const agentOptions = agent && agent.options;
3554
+ return Boolean(agentOptions && utils$1.hasOwnProp(agentOptions, 'proxyEnv') && agentOptions.proxyEnv != null);
3555
+ }
3556
+ function getProxyEnvAgent(options, configHttpAgent, configHttpsAgent) {
3557
+ return isHttps.test(options.protocol) ? configHttpsAgent || https.globalAgent : configHttpAgent || http.globalAgent;
3558
+ }
3167
3559
  function getTunnelingAgent(agentOptions, userHttpsAgent) {
3168
3560
  const key = agentOptions.protocol + '//' + agentOptions.hostname + ':' + (agentOptions.port || '') + '#' + (agentOptions.auth || '');
3169
3561
  const cache = userHttpsAgent ? tunnelingAgentCacheUser.get(userHttpsAgent) || tunnelingAgentCacheUser.set(userHttpsAgent, new Map()).get(userHttpsAgent) : tunnelingAgentCache;
@@ -3271,9 +3663,10 @@ function isSameOriginRedirect(redirectOptions, requestDetails) {
3271
3663
  *
3272
3664
  * @returns {http.ClientRequestArgs}
3273
3665
  */
3274
- function setProxy(options, configProxy, location, isRedirect, configHttpsAgent) {
3666
+ function setProxy(options, configProxy, location, isRedirect, configHttpsAgent, configHttpAgent) {
3275
3667
  let proxy = configProxy;
3276
- if (!proxy && proxy !== false) {
3668
+ const proxyEnvAgent = getProxyEnvAgent(options, configHttpAgent, configHttpsAgent);
3669
+ if (!proxy && proxy !== false && !isNodeEnvProxyEnabled(proxyEnvAgent)) {
3277
3670
  const proxyUrl = getProxyForUrl(location);
3278
3671
  if (proxyUrl) {
3279
3672
  if (!shouldBypassProxy(location)) {
@@ -3408,7 +3801,7 @@ function setProxy(options, configProxy, location, isRedirect, configHttpsAgent)
3408
3801
  options.beforeRedirects.proxy = function beforeRedirect(redirectOptions) {
3409
3802
  // Configure proxy for redirected request, passing the original config proxy to apply
3410
3803
  // the exact same logic as if the redirected request was performed by axios directly.
3411
- setProxy(redirectOptions, configProxy, redirectOptions.href, true, configHttpsAgent);
3804
+ setProxy(redirectOptions, configProxy, redirectOptions.href, true, configHttpsAgent, configHttpAgent);
3412
3805
  };
3413
3806
  }
3414
3807
  const isHttpAdapterSupported = typeof process !== 'undefined' && utils$1.kindOf(process) === 'process';
@@ -3504,10 +3897,12 @@ var httpAdapter = isHttpAdapterSupported && function httpAdapter(config) {
3504
3897
  let httpVersion = own('httpVersion');
3505
3898
  if (httpVersion === undefined) httpVersion = 1;
3506
3899
  let http2Options = own('http2Options');
3507
- const responseType = own('responseType');
3508
- const responseEncoding = own('responseEncoding');
3509
3900
  const httpAgent = own('httpAgent');
3510
3901
  const httpsAgent = own('httpsAgent');
3902
+ const configProxy = own('proxy');
3903
+ const responseType = own('responseType');
3904
+ const responseEncoding = own('responseEncoding');
3905
+ const socketPath = own('socketPath');
3511
3906
  const method = own('method').toUpperCase();
3512
3907
  const maxRedirects = own('maxRedirects');
3513
3908
  const maxBodyLength = own('maxBodyLength');
@@ -3601,14 +3996,19 @@ var httpAdapter = isHttpAdapterSupported && function httpAdapter(config) {
3601
3996
 
3602
3997
  // Parse url
3603
3998
  const fullPath = buildFullPath(own('baseURL'), own('url'), own('allowAbsoluteUrls'), config);
3604
- const parsed = new URL(fullPath, platform.hasBrowserEnv ? platform.origin : undefined);
3999
+ // Unix-socket requests (own socketPath) commonly pass a path-only url
4000
+ // like '/foo'; supply a synthetic base so new URL() can still parse it.
4001
+ // Use the own-property value (not config.socketPath) so a polluted
4002
+ // prototype cannot influence URL base selection.
4003
+ const urlBase = socketPath ? 'http://localhost' : platform.hasBrowserEnv ? platform.origin : undefined;
4004
+ const parsed = new URL(fullPath, urlBase);
3605
4005
  const protocol = parsed.protocol || supportedProtocols[0];
3606
4006
  if (protocol === 'data:') {
3607
4007
  // Apply the same semantics as HTTP: only enforce if a finite, non-negative cap is set.
3608
4008
  if (maxContentLength > -1) {
3609
4009
  // Use the exact string passed to fromDataURI (the configured url); fall back to fullPath if needed.
3610
4010
  const dataUrl = String(own('url') || fullPath || '');
3611
- const estimated = estimateDataURLDecodedBytes(dataUrl);
4011
+ const estimated = estimateDataURLBufferAllocation(dataUrl);
3612
4012
  if (estimated > maxContentLength) {
3613
4013
  return reject(new AxiosError('maxContentLength size of ' + maxContentLength + ' exceeded', AxiosError.ERR_BAD_RESPONSE, config));
3614
4014
  }
@@ -3674,7 +4074,7 @@ var httpAdapter = isHttpAdapterSupported && function httpAdapter(config) {
3674
4074
  });
3675
4075
  // support for https://www.npmjs.com/package/form-data api
3676
4076
  } else if (utils$1.isFormData(data) && utils$1.isFunction(data.getHeaders) && data.getHeaders !== Object.prototype.getHeaders) {
3677
- setFormDataHeaders$1(headers, data.getHeaders(), own('formDataHeaderPolicy'));
4077
+ setFormDataHeaders(headers, data.getHeaders(), own('formDataHeaderPolicy'));
3678
4078
  if (!headers.hasContentLength()) {
3679
4079
  try {
3680
4080
  const knownLength = await util.promisify(data.getLength).call(data);
@@ -3717,7 +4117,7 @@ var httpAdapter = isHttpAdapterSupported && function httpAdapter(config) {
3717
4117
  data = stream.pipeline([data, new AxiosTransformStream({
3718
4118
  maxRate: utils$1.toFiniteNumber(maxUploadRate)
3719
4119
  })], utils$1.noop);
3720
- onUploadProgress && data.on('progress', flushOnFinish(data, progressEventDecorator(contentLength, progressEventReducer(asyncDecorator(onUploadProgress), false, 3))));
4120
+ onUploadProgress && data.on('progress', flushOnFinish(data, progressEventDecorator(contentLength, progressEventReducer(asyncDecorator(onUploadProgress, scheduleProgress), false, 3))));
3721
4121
  }
3722
4122
 
3723
4123
  // HTTP basic authentication
@@ -3738,11 +4138,10 @@ var httpAdapter = isHttpAdapterSupported && function httpAdapter(config) {
3738
4138
  try {
3739
4139
  path$1 = buildURL(parsed.pathname + parsed.search, own('params'), own('paramsSerializer')).replace(/^\?/, '');
3740
4140
  } catch (err) {
3741
- const customErr = new Error(err.message);
3742
- customErr.config = config;
3743
- customErr.url = own('url');
3744
- customErr.exists = true;
3745
- return reject(customErr);
4141
+ return reject(AxiosError.from(err, AxiosError.ERR_BAD_REQUEST, config, null, null, {
4142
+ url: own('url'),
4143
+ exists: true
4144
+ }));
3746
4145
  }
3747
4146
  headers.set('Accept-Encoding', utils$1.hasOwnProp(transitional, 'advertiseZstdAcceptEncoding') && transitional.advertiseZstdAcceptEncoding === true ? ACCEPT_ENCODING_WITH_ZSTD : ACCEPT_ENCODING, false);
3748
4147
 
@@ -3766,7 +4165,6 @@ var httpAdapter = isHttpAdapterSupported && function httpAdapter(config) {
3766
4165
 
3767
4166
  // cacheable-lookup integration hotfix
3768
4167
  !utils$1.isUndefined(lookup) && (options.lookup = lookup);
3769
- const socketPath = own('socketPath');
3770
4168
  if (socketPath) {
3771
4169
  if (typeof socketPath !== 'string') {
3772
4170
  return reject(new AxiosError('socketPath must be a string', AxiosError.ERR_BAD_OPTION_VALUE, config));
@@ -3784,7 +4182,7 @@ var httpAdapter = isHttpAdapterSupported && function httpAdapter(config) {
3784
4182
  } else {
3785
4183
  options.hostname = parsed.hostname.startsWith('[') ? parsed.hostname.slice(1, -1) : parsed.hostname;
3786
4184
  options.port = parsed.port;
3787
- setProxy(options, own('proxy'), protocol + '//' + parsed.hostname + (parsed.port ? ':' + parsed.port : '') + options.path, false, httpsAgent);
4185
+ setProxy(options, configProxy, protocol + '//' + parsed.hostname + (parsed.port ? ':' + parsed.port : '') + options.path, false, httpsAgent, httpAgent);
3788
4186
  }
3789
4187
  let transport;
3790
4188
  let isNativeTransport = false;
@@ -3859,10 +4257,13 @@ var httpAdapter = isHttpAdapterSupported && function httpAdapter(config) {
3859
4257
  transport = isHttpsRequest ? httpsFollow : httpFollow;
3860
4258
  }
3861
4259
  }
4260
+
4261
+ // Set an explicit maxBodyLength option for transports that inspect it.
4262
+ // When maxBodyLength is -1 (default/unlimited), use Infinity so
4263
+ // follow-redirects does not fall back to its own 10MB default.
3862
4264
  if (maxBodyLength > -1) {
3863
4265
  options.maxBodyLength = maxBodyLength;
3864
4266
  } else {
3865
- // follow-redirects does not skip comparison, so it should always succeed for axios -1 unlimited
3866
4267
  options.maxBodyLength = Infinity;
3867
4268
  }
3868
4269
 
@@ -3881,7 +4282,7 @@ var httpAdapter = isHttpAdapterSupported && function httpAdapter(config) {
3881
4282
  const transformStream = new AxiosTransformStream({
3882
4283
  maxRate: utils$1.toFiniteNumber(maxDownloadRate)
3883
4284
  });
3884
- onDownloadProgress && transformStream.on('progress', flushOnFinish(transformStream, progressEventDecorator(responseLength, progressEventReducer(asyncDecorator(onDownloadProgress), true, 3))));
4285
+ onDownloadProgress && transformStream.on('progress', flushOnFinish(transformStream, progressEventDecorator(responseLength, progressEventReducer(asyncDecorator(onDownloadProgress, scheduleProgress), true, 3))));
3885
4286
  streams.push(transformStream);
3886
4287
  }
3887
4288
 
@@ -4038,7 +4439,11 @@ var httpAdapter = isHttpAdapterSupported && function httpAdapter(config) {
4038
4439
  const boundSockets = new Set();
4039
4440
  req.on('socket', function handleRequestSocket(socket) {
4040
4441
  // default interval of sending ack packet is 1 minute
4041
- socket.setKeepAlive(true, 1000 * 60);
4442
+ // proxy agents (e.g. agent-base) may return a generic Duplex stream
4443
+ // that doesn't have setKeepAlive, so guard before calling
4444
+ if (typeof socket.setKeepAlive === 'function') {
4445
+ socket.setKeepAlive(true, 1000 * 60);
4446
+ }
4042
4447
 
4043
4448
  // Install a single 'error' listener per socket (not per request) to avoid
4044
4449
  // accumulating listeners on pooled keep-alive sockets that get reassigned
@@ -4183,7 +4588,11 @@ var cookies = platform.hasStandardBrowserEnv ?
4183
4588
  const cookie = cookies[i].replace(/^\s+/, '');
4184
4589
  const eq = cookie.indexOf('=');
4185
4590
  if (eq !== -1 && cookie.slice(0, eq) === name) {
4186
- return decodeURIComponent(cookie.slice(eq + 1));
4591
+ try {
4592
+ return decodeURIComponent(cookie.slice(eq + 1));
4593
+ } catch (e) {
4594
+ return cookie.slice(eq + 1);
4595
+ }
4187
4596
  }
4188
4597
  }
4189
4598
  return null;
@@ -4204,6 +4613,12 @@ var cookies = platform.hasStandardBrowserEnv ?
4204
4613
  const headersToObject = thing => thing instanceof AxiosHeaders ? {
4205
4614
  ...thing
4206
4615
  } : thing;
4616
+ const ownEnumerableKeys = thing => {
4617
+ if (Object.getOwnPropertySymbols && Object.getOwnPropertyDescriptor) {
4618
+ return Object.keys(thing).concat(Object.getOwnPropertySymbols(thing).filter(symbol => Object.getOwnPropertyDescriptor(thing, symbol).enumerable));
4619
+ }
4620
+ return Object.keys(thing);
4621
+ };
4207
4622
 
4208
4623
  /**
4209
4624
  * Config-specific merge-function which creates a new config-object
@@ -4216,6 +4631,7 @@ const headersToObject = thing => thing instanceof AxiosHeaders ? {
4216
4631
  */
4217
4632
  function mergeConfig(config1, config2) {
4218
4633
  // eslint-disable-next-line no-param-reassign
4634
+ config1 = config1 || {};
4219
4635
  config2 = config2 || {};
4220
4636
 
4221
4637
  // Use a null-prototype object so that downstream reads such as `config.auth`
@@ -4325,7 +4741,7 @@ function mergeConfig(config1, config2) {
4325
4741
  validateStatus: mergeDirectKeys,
4326
4742
  headers: (a, b, prop) => mergeDeepProperties(headersToObject(a), headersToObject(b), prop, true)
4327
4743
  };
4328
- utils$1.forEach(Object.keys({
4744
+ utils$1.forEach(ownEnumerableKeys({
4329
4745
  ...config1,
4330
4746
  ...config2
4331
4747
  }), function computeConfigValue(prop) {
@@ -4346,19 +4762,6 @@ function mergeConfig(config1, config2) {
4346
4762
  return config;
4347
4763
  }
4348
4764
 
4349
- const FORM_DATA_CONTENT_HEADERS = ['content-type', 'content-length'];
4350
- function setFormDataHeaders(headers, formHeaders, policy) {
4351
- if (policy !== 'content-only') {
4352
- headers.set(formHeaders);
4353
- return;
4354
- }
4355
- Object.entries(formHeaders).forEach(([key, val]) => {
4356
- if (FORM_DATA_CONTENT_HEADERS.includes(key.toLowerCase())) {
4357
- headers.set(key, val);
4358
- }
4359
- });
4360
- }
4361
-
4362
4765
  /**
4363
4766
  * Encode a UTF-8 string to a Latin-1 byte string for use with btoa().
4364
4767
  * This is a modern replacement for the deprecated unescape(encodeURIComponent(str)) pattern.
@@ -4390,7 +4793,11 @@ function resolveConfig(config) {
4390
4793
  if (auth) {
4391
4794
  const username = utils$1.getSafeProp(auth, 'username') || '';
4392
4795
  const password = utils$1.getSafeProp(auth, 'password') || '';
4393
- headers.set('Authorization', 'Basic ' + btoa(username + ':' + (password ? encodeUTF8$1(password) : '')));
4796
+ try {
4797
+ headers.set('Authorization', 'Basic ' + btoa(username + ':' + (password ? encodeUTF8$1(password) : '')));
4798
+ } catch (e) {
4799
+ throw AxiosError.from(e, AxiosError.ERR_BAD_OPTION_VALUE, config);
4800
+ }
4394
4801
  }
4395
4802
  if (utils$1.isFormData(data)) {
4396
4803
  if (platform.hasStandardBrowserEnv || platform.hasStandardBrowserWebWorkerEnv || utils$1.isReactNative(data)) {
@@ -4591,6 +4998,7 @@ var xhrAdapter = isXHRAdapterSupported && function (config) {
4591
4998
  const protocol = parseProtocol(_config.url);
4592
4999
  if (protocol && !platform.protocols.includes(protocol)) {
4593
5000
  reject(new AxiosError('Unsupported protocol ' + protocol + ':', AxiosError.ERR_BAD_REQUEST, config));
5001
+ done();
4594
5002
  return;
4595
5003
  }
4596
5004
 
@@ -4629,7 +5037,18 @@ const composeSignals = (signals, timeout) => {
4629
5037
  });
4630
5038
  signals = null;
4631
5039
  };
4632
- signals.forEach(signal => signal.addEventListener('abort', onabort));
5040
+ signals.forEach(signal => {
5041
+ if (aborted) {
5042
+ return;
5043
+ }
5044
+ if (signal.aborted) {
5045
+ onabort.call(signal);
5046
+ return;
5047
+ }
5048
+ signal.addEventListener('abort', onabort, {
5049
+ once: true
5050
+ });
5051
+ });
4633
5052
  const {
4634
5053
  signal
4635
5054
  } = controller;
@@ -5079,7 +5498,17 @@ const factory = env => {
5079
5498
  const canceledError = composedSignal.reason;
5080
5499
  canceledError.config = config;
5081
5500
  request && (canceledError.request = request);
5082
- err !== canceledError && (canceledError.cause = err);
5501
+ if (err !== canceledError) {
5502
+ // Non-enumerable to match native Error `cause` semantics so loggers
5503
+ // don't recurse into circular fetch internals (see #7205).
5504
+ Object.defineProperty(canceledError, 'cause', {
5505
+ __proto__: null,
5506
+ value: err,
5507
+ writable: true,
5508
+ enumerable: false,
5509
+ configurable: true
5510
+ });
5511
+ }
5083
5512
  throw canceledError;
5084
5513
  }
5085
5514
 
@@ -5100,9 +5529,17 @@ const factory = env => {
5100
5529
  throw err;
5101
5530
  }
5102
5531
  if (err && err.name === 'TypeError' && /Load failed|fetch/i.test(err.message)) {
5103
- throw Object.assign(new AxiosError('Network Error', AxiosError.ERR_NETWORK, config, request, err && err.response), {
5104
- cause: err.cause || err
5532
+ const networkError = new AxiosError('Network Error', AxiosError.ERR_NETWORK, config, request, err && err.response);
5533
+ // Non-enumerable to match native Error `cause` semantics so loggers
5534
+ // don't recurse into circular fetch internals (see #7205).
5535
+ Object.defineProperty(networkError, 'cause', {
5536
+ __proto__: null,
5537
+ value: err.cause || err,
5538
+ writable: true,
5539
+ enumerable: false,
5540
+ configurable: true
5105
5541
  });
5542
+ throw networkError;
5106
5543
  }
5107
5544
  throw AxiosError.from(err, err && err.code, config, request, err && err.response);
5108
5545
  }
@@ -5221,7 +5658,7 @@ function getAdapter(adapters, config) {
5221
5658
  if (!adapter) {
5222
5659
  const reasons = Object.entries(rejectedReasons).map(([id, state]) => `adapter ${id} ` + (state === false ? 'is not supported by the environment' : 'is not available in the build'));
5223
5660
  let s = length ? reasons.length > 1 ? 'since :\n' + reasons.map(renderReason).join('\n') : ' ' + renderReason(reasons[0]) : 'as no adapter specified';
5224
- throw new AxiosError(`There is no suitable adapter to dispatch the request ` + s, 'ERR_NOT_SUPPORT');
5661
+ throw new AxiosError(`There is no suitable adapter to dispatch the request ` + s, AxiosError.ERR_NOT_SUPPORT);
5225
5662
  }
5226
5663
  return adapter;
5227
5664
  }
@@ -5364,7 +5801,7 @@ validators$1.spelling = function spelling(correctSpelling) {
5364
5801
  */
5365
5802
 
5366
5803
  function assertOptions(options, schema, allowUnknown) {
5367
- if (typeof options !== 'object') {
5804
+ if (typeof options !== 'object' || options === null) {
5368
5805
  throw new AxiosError('options must be an object', AxiosError.ERR_BAD_OPTION_VALUE);
5369
5806
  }
5370
5807
  const keys = Object.keys(options);
@@ -5552,16 +5989,29 @@ class Axios {
5552
5989
  const onFulfilled = requestInterceptorChain[i++];
5553
5990
  const onRejected = requestInterceptorChain[i++];
5554
5991
  try {
5555
- newConfig = onFulfilled(newConfig);
5992
+ newConfig = onFulfilled ? onFulfilled(newConfig) : newConfig;
5556
5993
  } catch (error) {
5557
- onRejected.call(this, error);
5994
+ if (!onRejected) {
5995
+ promise = Promise.reject(error);
5996
+ break;
5997
+ }
5998
+ try {
5999
+ const rejectedResult = onRejected.call(this, error);
6000
+ if (utils$1.isThenable(rejectedResult)) {
6001
+ promise = Promise.resolve(rejectedResult).then(() => dispatchRequest.call(this, newConfig));
6002
+ }
6003
+ } catch (rejectedError) {
6004
+ promise = Promise.reject(rejectedError);
6005
+ }
5558
6006
  break;
5559
6007
  }
5560
6008
  }
5561
- try {
5562
- promise = dispatchRequest.call(this, newConfig);
5563
- } catch (error) {
5564
- return Promise.reject(error);
6009
+ if (!promise) {
6010
+ try {
6011
+ promise = dispatchRequest.call(this, newConfig);
6012
+ } catch (error) {
6013
+ promise = Promise.reject(error);
6014
+ }
5565
6015
  }
5566
6016
  i = 0;
5567
6017
  len = responseInterceptorChain.length;
@@ -5827,6 +6277,7 @@ const HttpStatusCode = {
5827
6277
  LoopDetected: 508,
5828
6278
  NotExtended: 510,
5829
6279
  NetworkAuthenticationRequired: 511,
6280
+ WebServerReturnsAnUnknownError: 520,
5830
6281
  WebServerIsDown: 521,
5831
6282
  ConnectionTimedOut: 522,
5832
6283
  OriginIsUnreachable: 523,
@@ -5903,4 +6354,3 @@ axios.HttpStatusCode = HttpStatusCode;
5903
6354
  axios.default = axios;
5904
6355
 
5905
6356
  module.exports = axios;
5906
- //# sourceMappingURL=axios.cjs.map