axios 1.18.1 → 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.
@@ -1,4 +1,4 @@
1
- /*! Axios v1.18.1 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,9 +1449,33 @@ 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);
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);
1356
1479
  // Match native `Error` `cause` semantics: non-enumerable. The wrapped
1357
1480
  // error often carries circular internals (sockets, requests, agents), so
1358
1481
  // an enumerable `cause` makes structured loggers (pino/winston) and any
@@ -1456,6 +1579,15 @@ AxiosError.ERR_NOT_SUPPORT = 'ERR_NOT_SUPPORT';
1456
1579
  AxiosError.ERR_INVALID_URL = 'ERR_INVALID_URL';
1457
1580
  AxiosError.ERR_FORM_DATA_DEPTH_EXCEEDED = 'ERR_FORM_DATA_DEPTH_EXCEEDED';
1458
1581
 
1582
+ var PlatformBuffer = {
1583
+ isBufferAvailable() {
1584
+ return typeof Buffer !== 'undefined';
1585
+ },
1586
+ from(value) {
1587
+ return Buffer.from(value);
1588
+ }
1589
+ };
1590
+
1459
1591
  // Default nesting limit shared with the inverse transform (formDataToJSON) so
1460
1592
  // the FormData <-> JSON round-trip stays symmetric.
1461
1593
  const DEFAULT_FORM_DATA_MAX_DEPTH = 100;
@@ -1581,8 +1713,8 @@ function toFormData(obj, formData, options) {
1581
1713
  if (useBlob && typeof _Blob === 'function') {
1582
1714
  return new _Blob([value]);
1583
1715
  }
1584
- if (typeof Buffer !== 'undefined') {
1585
- return Buffer.from(value);
1716
+ if (PlatformBuffer && PlatformBuffer.isBufferAvailable()) {
1717
+ return PlatformBuffer.from(value);
1586
1718
  }
1587
1719
  throw new AxiosError('Blob is not supported. Use a Buffer instead.', AxiosError.ERR_NOT_SUPPORT);
1588
1720
  }
@@ -1962,12 +2094,18 @@ function throwIfDepthExceeded(index) {
1962
2094
  * @returns An array of strings.
1963
2095
  */
1964
2096
  function parsePropPath(name) {
1965
- // foo[x][y][z]
1966
- // foo.x.y.z
1967
- // foo-x-y-z
1968
- // 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.
1969
2107
  const path = [];
1970
- const pattern = /\w+|\[(\w*)]/g;
2108
+ const pattern = /[^.[\]]+|\[([^.[\]]*)]/g;
1971
2109
  let match;
1972
2110
  while ((match = pattern.exec(name)) !== null) {
1973
2111
  throwIfDepthExceeded(path.length);
@@ -2243,7 +2381,14 @@ function isAbsoluteURL(url) {
2243
2381
  * @returns {string} The combined URL
2244
2382
  */
2245
2383
  function combineURLs(baseURL, relativeURL) {
2246
- 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(/^\/+/, '');
2247
2392
  }
2248
2393
 
2249
2394
  const malformedHttpProtocol = /^https?:(?!\/\/)/i;
@@ -2258,9 +2403,39 @@ function stripLeadingC0ControlOrSpace(url) {
2258
2403
  function normalizeURLForProtocolCheck(url) {
2259
2404
  return stripLeadingC0ControlOrSpace(url).replace(httpProtocolControlCharacters, '');
2260
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
+ }
2261
2433
  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);
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
+ }
2264
2439
  }
2265
2440
  }
2266
2441
 
@@ -2380,7 +2555,7 @@ function getEnv(key) {
2380
2555
  return process.env[key.toLowerCase()] || process.env[key.toUpperCase()] || '';
2381
2556
  }
2382
2557
 
2383
- const VERSION = "1.18.1";
2558
+ const VERSION = "1.19.0";
2384
2559
 
2385
2560
  function parseProtocol(url) {
2386
2561
  const match = /^([-+\w]{1,25}):(?:\/\/)?/.exec(url);
@@ -2440,6 +2615,31 @@ function fromDataURI(uri, asBlob, options) {
2440
2615
  throw new AxiosError('Unsupported protocol ' + protocol, AxiosError.ERR_NOT_SUPPORT);
2441
2616
  }
2442
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
+
2443
2643
  const kInternals = Symbol('internals');
2444
2644
  class AxiosTransformStream extends stream.Transform {
2445
2645
  constructor(options) {
@@ -2770,6 +2970,104 @@ const isIPv4Loopback = host => {
2770
2970
  if (parts[0] !== '127') return false;
2771
2971
  return parts.every(p => /^\d+$/.test(p) && Number(p) >= 0 && Number(p) <= 255);
2772
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
+ };
2773
3071
  const isIPv6ZeroGroup = group => /^0{1,4}$/.test(group);
2774
3072
 
2775
3073
  // The unspecified address (IPv4 0.0.0.0 / IPv6 ::) resolves to the local host
@@ -2883,7 +3181,15 @@ const normalizeNoProxyHost = hostname => {
2883
3181
  if (hostname.charAt(0) === '[' && hostname.charAt(hostname.length - 1) === ']') {
2884
3182
  hostname = hostname.slice(1, -1);
2885
3183
  }
2886
- 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);
2887
3193
  };
2888
3194
  function shouldBypassProxy(location) {
2889
3195
  let parsed;
@@ -2905,6 +3211,9 @@ function shouldBypassProxy(location) {
2905
3211
  if (!entry) {
2906
3212
  return false;
2907
3213
  }
3214
+ if (entry === '*') {
3215
+ return true;
3216
+ }
2908
3217
  let [entryHost, entryPort] = parseNoProxyEntry(entry);
2909
3218
  entryHost = normalizeNoProxyHost(entryHost);
2910
3219
  if (!entryHost) {
@@ -3011,7 +3320,7 @@ const progressEventReducer = (listener, isDownloadStream, freq = 3) => {
3011
3320
  }
3012
3321
  const rawLoaded = e.loaded;
3013
3322
  const total = e.lengthComputable ? e.total : undefined;
3014
- const loaded = total != null ? Math.min(rawLoaded, total) : rawLoaded;
3323
+ const loaded = Math.max(0, total != null ? Math.min(rawLoaded, total) : rawLoaded);
3015
3324
  const progressBytes = Math.max(0, loaded - bytesNotified);
3016
3325
  const rate = _speedometer(progressBytes);
3017
3326
  bytesNotified = Math.max(bytesNotified, loaded);
@@ -3037,20 +3346,85 @@ const progressEventDecorator = (total, throttled) => {
3037
3346
  loaded
3038
3347
  }), throttled[1]];
3039
3348
  };
3040
- const asyncDecorator = fn => (...args) => utils$1.asap(() => fn(...args));
3349
+ const asyncDecorator = (fn, scheduler = utils$1.asap) => (...args) => scheduler(() => fn(...args));
3041
3350
 
3042
3351
  /**
3043
- * Estimate decoded byte length of a data:// URL *without* allocating large buffers.
3044
- * - For base64: compute exact decoded size using length and padding;
3045
- * handle %XX at the character-count level (no string allocation).
3046
- * - For non-base64: compute the exact percent-decoded UTF-8 byte length.
3047
- *
3048
- * @param {string} url
3049
- * @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.
3050
3357
  */
3051
3358
  const isHexDigit = charCode => charCode >= 48 && charCode <= 57 || charCode >= 65 && charCode <= 70 || charCode >= 97 && charCode <= 102;
3052
3359
  const isPercentEncodedByte = (str, i, len) => i + 2 < len && isHexDigit(str.charCodeAt(i + 1)) && isHexDigit(str.charCodeAt(i + 2));
3053
- 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) => {
3054
3428
  if (!url || typeof url !== 'string') return 0;
3055
3429
  if (!url.startsWith('data:')) return 0;
3056
3430
  const comma = url.indexOf(',');
@@ -3059,47 +3433,7 @@ function estimateDataURLDecodedBytes(url) {
3059
3433
  const body = url.slice(comma + 1);
3060
3434
  const isBase64 = /;base64/i.test(meta);
3061
3435
  if (isBase64) {
3062
- let effectiveLen = body.length;
3063
- const len = body.length; // cache length
3064
-
3065
- for (let i = 0; i < len; i++) {
3066
- if (body.charCodeAt(i) === 37 /* '%' */ && i + 2 < len) {
3067
- const a = body.charCodeAt(i + 1);
3068
- const b = body.charCodeAt(i + 2);
3069
- const isHex = isHexDigit(a) && isHexDigit(b);
3070
- if (isHex) {
3071
- effectiveLen -= 2;
3072
- i += 2;
3073
- }
3074
- }
3075
- }
3076
- let pad = 0;
3077
- let idx = len - 1;
3078
- const tailIsPct3D = j => j >= 2 && body.charCodeAt(j - 2) === 37 &&
3079
- // '%'
3080
- body.charCodeAt(j - 1) === 51 && (
3081
- // '3'
3082
- body.charCodeAt(j) === 68 || body.charCodeAt(j) === 100); // 'D' or 'd'
3083
-
3084
- if (idx >= 0) {
3085
- if (body.charCodeAt(idx) === 61 /* '=' */) {
3086
- pad++;
3087
- idx--;
3088
- } else if (tailIsPct3D(idx)) {
3089
- pad++;
3090
- idx -= 3;
3091
- }
3092
- }
3093
- if (pad === 1 && idx >= 0) {
3094
- if (body.charCodeAt(idx) === 61 /* '=' */) {
3095
- pad++;
3096
- } else if (tailIsPct3D(idx)) {
3097
- pad++;
3098
- }
3099
- }
3100
- const groups = Math.floor(effectiveLen / 4);
3101
- const bytes = groups * 3 - (pad || 0);
3102
- return bytes > 0 ? bytes : 0;
3436
+ return estimateBase64(body);
3103
3437
  }
3104
3438
 
3105
3439
  // Compute UTF-8 byte length directly from UTF-16 code units without allocating
@@ -3129,6 +3463,28 @@ function estimateDataURLDecodedBytes(url) {
3129
3463
  }
3130
3464
  }
3131
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);
3132
3488
  }
3133
3489
 
3134
3490
  const zlibOptions = {
@@ -3147,23 +3503,12 @@ const isBrotliSupported = utils$1.isFunction(zlib.createBrotliDecompress);
3147
3503
  const isZstdSupported = utils$1.isFunction(zlib.createZstdDecompress);
3148
3504
  const ACCEPT_ENCODING = 'gzip, compress, deflate' + (isBrotliSupported ? ', br' : '');
3149
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;
3150
3507
  const {
3151
3508
  http: httpFollow,
3152
3509
  https: httpsFollow
3153
3510
  } = followRedirects;
3154
3511
  const isHttps = /https:?/;
3155
- const FORM_DATA_CONTENT_HEADERS$1 = ['content-type', 'content-length'];
3156
- function setFormDataHeaders$1(headers, formHeaders, policy) {
3157
- if (policy !== 'content-only') {
3158
- headers.set(formHeaders);
3159
- return;
3160
- }
3161
- Object.entries(formHeaders).forEach(([key, val]) => {
3162
- if (FORM_DATA_CONTENT_HEADERS$1.includes(key.toLowerCase())) {
3163
- headers.set(key, val);
3164
- }
3165
- });
3166
- }
3167
3512
 
3168
3513
  // Symbols used to bind a single 'error' listener to a pooled socket and track
3169
3514
  // the request currently owning that socket across keep-alive reuse (issue #10780).
@@ -3663,7 +4008,7 @@ var httpAdapter = isHttpAdapterSupported && function httpAdapter(config) {
3663
4008
  if (maxContentLength > -1) {
3664
4009
  // Use the exact string passed to fromDataURI (the configured url); fall back to fullPath if needed.
3665
4010
  const dataUrl = String(own('url') || fullPath || '');
3666
- const estimated = estimateDataURLDecodedBytes(dataUrl);
4011
+ const estimated = estimateDataURLBufferAllocation(dataUrl);
3667
4012
  if (estimated > maxContentLength) {
3668
4013
  return reject(new AxiosError('maxContentLength size of ' + maxContentLength + ' exceeded', AxiosError.ERR_BAD_RESPONSE, config));
3669
4014
  }
@@ -3729,7 +4074,7 @@ var httpAdapter = isHttpAdapterSupported && function httpAdapter(config) {
3729
4074
  });
3730
4075
  // support for https://www.npmjs.com/package/form-data api
3731
4076
  } else if (utils$1.isFormData(data) && utils$1.isFunction(data.getHeaders) && data.getHeaders !== Object.prototype.getHeaders) {
3732
- setFormDataHeaders$1(headers, data.getHeaders(), own('formDataHeaderPolicy'));
4077
+ setFormDataHeaders(headers, data.getHeaders(), own('formDataHeaderPolicy'));
3733
4078
  if (!headers.hasContentLength()) {
3734
4079
  try {
3735
4080
  const knownLength = await util.promisify(data.getLength).call(data);
@@ -3772,7 +4117,7 @@ var httpAdapter = isHttpAdapterSupported && function httpAdapter(config) {
3772
4117
  data = stream.pipeline([data, new AxiosTransformStream({
3773
4118
  maxRate: utils$1.toFiniteNumber(maxUploadRate)
3774
4119
  })], utils$1.noop);
3775
- 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))));
3776
4121
  }
3777
4122
 
3778
4123
  // HTTP basic authentication
@@ -3937,7 +4282,7 @@ var httpAdapter = isHttpAdapterSupported && function httpAdapter(config) {
3937
4282
  const transformStream = new AxiosTransformStream({
3938
4283
  maxRate: utils$1.toFiniteNumber(maxDownloadRate)
3939
4284
  });
3940
- 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))));
3941
4286
  streams.push(transformStream);
3942
4287
  }
3943
4288
 
@@ -4268,6 +4613,12 @@ var cookies = platform.hasStandardBrowserEnv ?
4268
4613
  const headersToObject = thing => thing instanceof AxiosHeaders ? {
4269
4614
  ...thing
4270
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
+ };
4271
4622
 
4272
4623
  /**
4273
4624
  * Config-specific merge-function which creates a new config-object
@@ -4390,7 +4741,7 @@ function mergeConfig(config1, config2) {
4390
4741
  validateStatus: mergeDirectKeys,
4391
4742
  headers: (a, b, prop) => mergeDeepProperties(headersToObject(a), headersToObject(b), prop, true)
4392
4743
  };
4393
- utils$1.forEach(Object.keys({
4744
+ utils$1.forEach(ownEnumerableKeys({
4394
4745
  ...config1,
4395
4746
  ...config2
4396
4747
  }), function computeConfigValue(prop) {
@@ -4411,19 +4762,6 @@ function mergeConfig(config1, config2) {
4411
4762
  return config;
4412
4763
  }
4413
4764
 
4414
- const FORM_DATA_CONTENT_HEADERS = ['content-type', 'content-length'];
4415
- function setFormDataHeaders(headers, formHeaders, policy) {
4416
- if (policy !== 'content-only') {
4417
- headers.set(formHeaders);
4418
- return;
4419
- }
4420
- Object.entries(formHeaders || {}).forEach(([key, val]) => {
4421
- if (FORM_DATA_CONTENT_HEADERS.includes(key.toLowerCase())) {
4422
- headers.set(key, val);
4423
- }
4424
- });
4425
- }
4426
-
4427
4765
  /**
4428
4766
  * Encode a UTF-8 string to a Latin-1 byte string for use with btoa().
4429
4767
  * This is a modern replacement for the deprecated unescape(encodeURIComponent(str)) pattern.
@@ -4699,9 +5037,18 @@ const composeSignals = (signals, timeout) => {
4699
5037
  });
4700
5038
  signals = null;
4701
5039
  };
4702
- signals.forEach(signal => signal.addEventListener('abort', onabort, {
4703
- once: true
4704
- }));
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
+ });
4705
5052
  const {
4706
5053
  signal
4707
5054
  } = controller;
@@ -5642,16 +5989,29 @@ class Axios {
5642
5989
  const onFulfilled = requestInterceptorChain[i++];
5643
5990
  const onRejected = requestInterceptorChain[i++];
5644
5991
  try {
5645
- newConfig = onFulfilled(newConfig);
5992
+ newConfig = onFulfilled ? onFulfilled(newConfig) : newConfig;
5646
5993
  } catch (error) {
5647
- 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
+ }
5648
6006
  break;
5649
6007
  }
5650
6008
  }
5651
- try {
5652
- promise = dispatchRequest.call(this, newConfig);
5653
- } catch (error) {
5654
- return Promise.reject(error);
6009
+ if (!promise) {
6010
+ try {
6011
+ promise = dispatchRequest.call(this, newConfig);
6012
+ } catch (error) {
6013
+ promise = Promise.reject(error);
6014
+ }
5655
6015
  }
5656
6016
  i = 0;
5657
6017
  len = responseInterceptorChain.length;
@@ -5917,6 +6277,7 @@ const HttpStatusCode = {
5917
6277
  LoopDetected: 508,
5918
6278
  NotExtended: 510,
5919
6279
  NetworkAuthenticationRequired: 511,
6280
+ WebServerReturnsAnUnknownError: 520,
5920
6281
  WebServerIsDown: 521,
5921
6282
  ConnectionTimedOut: 522,
5922
6283
  OriginIsUnreachable: 523,
@@ -5993,4 +6354,3 @@ axios.HttpStatusCode = HttpStatusCode;
5993
6354
  axios.default = axios;
5994
6355
 
5995
6356
  module.exports = axios;
5996
- //# sourceMappingURL=axios.cjs.map