axios 1.16.0 → 1.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/esm/axios.js CHANGED
@@ -1,4 +1,4 @@
1
- /*! Axios v1.16.0 Copyright (c) 2026 Matt Zabriskie and contributors */
1
+ /*! Axios v1.17.0 Copyright (c) 2026 Matt Zabriskie and contributors */
2
2
  /**
3
3
  * Create a bound version of a function with a specified `this` context
4
4
  *
@@ -422,7 +422,9 @@ function merge(...objs) {
422
422
  return;
423
423
  }
424
424
 
425
- const targetKey = (caseless && findKey(result, key)) || key;
425
+ // findKey lowercases the key, so caseless lookup only applies to strings —
426
+ // symbol keys are identity-matched.
427
+ const targetKey = (caseless && typeof key === 'string' && findKey(result, key)) || key;
426
428
  // Read via own-prop only — a bare `result[targetKey]` walks the prototype
427
429
  // chain, so a polluted Object.prototype value could surface here and get
428
430
  // copied into the merged result.
@@ -439,7 +441,24 @@ function merge(...objs) {
439
441
  };
440
442
 
441
443
  for (let i = 0, l = objs.length; i < l; i++) {
442
- objs[i] && forEach(objs[i], assignValue);
444
+ const source = objs[i];
445
+ if (!source || isBuffer(source)) {
446
+ continue;
447
+ }
448
+
449
+ forEach(source, assignValue);
450
+
451
+ if (typeof source !== 'object' || isArray(source)) {
452
+ continue;
453
+ }
454
+
455
+ const symbols = Object.getOwnPropertySymbols(source);
456
+ for (let j = 0; j < symbols.length; j++) {
457
+ const symbol = symbols[j];
458
+ if (propertyIsEnumerable.call(source, symbol)) {
459
+ assignValue(source[symbol], symbol);
460
+ }
461
+ }
443
462
  }
444
463
  return result;
445
464
  }
@@ -668,6 +687,8 @@ const hasOwnProperty = (
668
687
  hasOwnProperty.call(obj, prop)
669
688
  )(Object.prototype);
670
689
 
690
+ const { propertyIsEnumerable } = Object.prototype;
691
+
671
692
  /**
672
693
  * Determine if a value is a RegExp object
673
694
  *
@@ -773,11 +794,11 @@ function isSpecCompliantForm(thing) {
773
794
  * @returns {Object} The JSON-compatible object.
774
795
  */
775
796
  const toJSONObject = (obj) => {
776
- const stack = new Array(10);
797
+ const visited = new WeakSet();
777
798
 
778
- const visit = (source, i) => {
799
+ const visit = (source) => {
779
800
  if (isObject(source)) {
780
- if (stack.indexOf(source) >= 0) {
801
+ if (visited.has(source)) {
781
802
  return;
782
803
  }
783
804
 
@@ -787,15 +808,16 @@ const toJSONObject = (obj) => {
787
808
  }
788
809
 
789
810
  if (!('toJSON' in source)) {
790
- stack[i] = source;
811
+ // add-on descent / delete-on-ascent: preserves path semantics, so DAG nodes serialise at every occurrence (see #7230).
812
+ visited.add(source);
791
813
  const target = isArray(source) ? [] : {};
792
814
 
793
815
  forEach(source, (value, key) => {
794
- const reducedValue = visit(value, i + 1);
816
+ const reducedValue = visit(value);
795
817
  !isUndefined(reducedValue) && (target[key] = reducedValue);
796
818
  });
797
819
 
798
- stack[i] = undefined;
820
+ visited.delete(source);
799
821
 
800
822
  return target;
801
823
  }
@@ -804,7 +826,7 @@ const toJSONObject = (obj) => {
804
826
  return source;
805
827
  };
806
828
 
807
- return visit(obj, 0);
829
+ return visit(obj);
808
830
  };
809
831
 
810
832
  /**
@@ -1006,10 +1028,6 @@ var parseHeaders = (rawHeaders) => {
1006
1028
  return parsed;
1007
1029
  };
1008
1030
 
1009
- const $internals = Symbol('internals');
1010
-
1011
- const INVALID_HEADER_VALUE_CHARS_RE = /[^\x09\x20-\x7E\x80-\xFF]/g;
1012
-
1013
1031
  function trimSPorHTAB(str) {
1014
1032
  let start = 0;
1015
1033
  let end = str.length;
@@ -1037,12 +1055,40 @@ function trimSPorHTAB(str) {
1037
1055
  return start === 0 && end === str.length ? str : str.slice(start, end);
1038
1056
  }
1039
1057
 
1040
- function normalizeHeader(header) {
1041
- return header && String(header).trim().toLowerCase();
1058
+ // The control-code ranges are intentional: header sanitization strips C0/DEL bytes.
1059
+ // eslint-disable-next-line no-control-regex
1060
+ const INVALID_UNICODE_HEADER_VALUE_CHARS = new RegExp('[\\u0000-\\u0008\\u000a-\\u001f\\u007f]+', 'g');
1061
+ // eslint-disable-next-line no-control-regex
1062
+ const INVALID_BYTE_STRING_HEADER_VALUE_CHARS = new RegExp('[^\\u0009\\u0020-\\u007e\\u0080-\\u00ff]+', 'g');
1063
+
1064
+ function sanitizeValue(value, invalidChars) {
1065
+ if (utils$1.isArray(value)) {
1066
+ return value.map((item) => sanitizeValue(item, invalidChars));
1067
+ }
1068
+
1069
+ return trimSPorHTAB(String(value).replace(invalidChars, ''));
1070
+ }
1071
+
1072
+ const sanitizeHeaderValue = (value) =>
1073
+ sanitizeValue(value, INVALID_UNICODE_HEADER_VALUE_CHARS);
1074
+
1075
+ const sanitizeByteStringHeaderValue = (value) =>
1076
+ sanitizeValue(value, INVALID_BYTE_STRING_HEADER_VALUE_CHARS);
1077
+
1078
+ function toByteStringHeaderObject(headers) {
1079
+ const byteStringHeaders = Object.create(null);
1080
+
1081
+ utils$1.forEach(headers.toJSON(), (value, header) => {
1082
+ byteStringHeaders[header] = sanitizeByteStringHeaderValue(value);
1083
+ });
1084
+
1085
+ return byteStringHeaders;
1042
1086
  }
1043
1087
 
1044
- function sanitizeHeaderValue(str) {
1045
- return trimSPorHTAB(str.replace(INVALID_HEADER_VALUE_CHARS_RE, ''));
1088
+ const $internals = Symbol('internals');
1089
+
1090
+ function normalizeHeader(header) {
1091
+ return header && String(header).trim().toLowerCase();
1046
1092
  }
1047
1093
 
1048
1094
  function normalizeValue(value) {
@@ -1124,7 +1170,7 @@ let AxiosHeaders$1 = class AxiosHeaders {
1124
1170
  const lHeader = normalizeHeader(_header);
1125
1171
 
1126
1172
  if (!lHeader) {
1127
- throw new Error('header name must be a non-empty string');
1173
+ return;
1128
1174
  }
1129
1175
 
1130
1176
  const key = utils$1.findKey(self, lHeader);
@@ -1152,7 +1198,7 @@ let AxiosHeaders$1 = class AxiosHeaders {
1152
1198
  key;
1153
1199
  for (const entry of header) {
1154
1200
  if (!utils$1.isArray(entry)) {
1155
- throw TypeError('Object iterator must return a key-value pair');
1201
+ throw new TypeError('Object iterator must return a key-value pair');
1156
1202
  }
1157
1203
 
1158
1204
  obj[(key = entry[0])] = (dest = obj[key])
@@ -1767,7 +1813,7 @@ function toFormData$1(obj, formData, options) {
1767
1813
  }
1768
1814
 
1769
1815
  if (stack.indexOf(value) !== -1) {
1770
- throw Error('Circular reference detected in ' + path.join('.'));
1816
+ throw new Error('Circular reference detected in ' + path.join('.'));
1771
1817
  }
1772
1818
 
1773
1819
  stack.push(value);
@@ -1984,6 +2030,7 @@ var transitionalDefaults = {
1984
2030
  forcedJSONParsing: true,
1985
2031
  clarifyTimeoutError: false,
1986
2032
  legacyInterceptorReqResOrdering: true,
2033
+ advertiseZstdAcceptEncoding: false,
1987
2034
  };
1988
2035
 
1989
2036
  var URLSearchParams$1 = typeof URLSearchParams !== 'undefined' ? URLSearchParams : AxiosURLSearchParams;
@@ -2141,7 +2188,7 @@ function formDataToJSON(formData) {
2141
2188
  return !isNumericKey;
2142
2189
  }
2143
2190
 
2144
- if (!target[name] || !utils$1.isObject(target[name])) {
2191
+ if (!utils$1.hasOwnProp(target, name) || !utils$1.isObject(target[name])) {
2145
2192
  target[name] = [];
2146
2193
  }
2147
2194
 
@@ -2506,6 +2553,9 @@ const progressEventReducer = (listener, isDownloadStream, freq = 3) => {
2506
2553
  const _speedometer = speedometer(50, 250);
2507
2554
 
2508
2555
  return throttle((e) => {
2556
+ if (!e || typeof e.loaded !== 'number') {
2557
+ return;
2558
+ }
2509
2559
  const rawLoaded = e.loaded;
2510
2560
  const total = e.lengthComputable ? e.total : undefined;
2511
2561
  const loaded = total != null ? Math.min(rawLoaded, total) : rawLoaded;
@@ -2815,12 +2865,12 @@ function setFormDataHeaders(headers, formHeaders, policy) {
2815
2865
  *
2816
2866
  * @returns {string} UTF-8 bytes as a Latin-1 string
2817
2867
  */
2818
- const encodeUTF8 = (str) =>
2868
+ const encodeUTF8$1 = (str) =>
2819
2869
  encodeURIComponent(str).replace(/%([0-9A-F]{2})/gi, (_, hex) =>
2820
2870
  String.fromCharCode(parseInt(hex, 16))
2821
2871
  );
2822
2872
 
2823
- var resolveConfig = (config) => {
2873
+ function resolveConfig(config) {
2824
2874
  const newConfig = mergeConfig$1({}, config);
2825
2875
 
2826
2876
  // Read only own properties to prevent prototype pollution gadgets
@@ -2841,8 +2891,8 @@ var resolveConfig = (config) => {
2841
2891
 
2842
2892
  newConfig.url = buildURL(
2843
2893
  buildFullPath(baseURL, url, allowAbsoluteUrls),
2844
- config.params,
2845
- config.paramsSerializer
2894
+ own('params'),
2895
+ own('paramsSerializer')
2846
2896
  );
2847
2897
 
2848
2898
  // HTTP basic authentication
@@ -2850,13 +2900,17 @@ var resolveConfig = (config) => {
2850
2900
  headers.set(
2851
2901
  'Authorization',
2852
2902
  'Basic ' +
2853
- btoa((auth.username || '') + ':' + (auth.password ? encodeUTF8(auth.password) : ''))
2903
+ btoa((auth.username || '') + ':' + (auth.password ? encodeUTF8$1(auth.password) : ''))
2854
2904
  );
2855
2905
  }
2856
2906
 
2857
2907
  if (utils$1.isFormData(data)) {
2858
- if (platform.hasStandardBrowserEnv || platform.hasStandardBrowserWebWorkerEnv) {
2859
- headers.setContentType(undefined); // browser handles it
2908
+ if (
2909
+ platform.hasStandardBrowserEnv ||
2910
+ platform.hasStandardBrowserWebWorkerEnv ||
2911
+ utils$1.isReactNative(data)
2912
+ ) {
2913
+ headers.setContentType(undefined); // browser/web worker/RN handles it
2860
2914
  } else if (utils$1.isFunction(data.getHeaders)) {
2861
2915
  // Node.js FormData (like form-data package)
2862
2916
  setFormDataHeaders(headers, data.getHeaders(), own('formDataHeaderPolicy'));
@@ -2888,7 +2942,7 @@ var resolveConfig = (config) => {
2888
2942
  }
2889
2943
 
2890
2944
  return newConfig;
2891
- };
2945
+ }
2892
2946
 
2893
2947
  const isXHRAdapterSupported = typeof XMLHttpRequest !== 'undefined';
2894
2948
 
@@ -3037,7 +3091,7 @@ var xhrAdapter = isXHRAdapterSupported &&
3037
3091
 
3038
3092
  // Add headers to the request
3039
3093
  if ('setRequestHeader' in request) {
3040
- utils$1.forEach(requestHeaders.toJSON(), function setRequestHeader(val, key) {
3094
+ utils$1.forEach(toByteStringHeaderObject(requestHeaders), function setRequestHeader(val, key) {
3041
3095
  request.setRequestHeader(key, val);
3042
3096
  });
3043
3097
  }
@@ -3107,54 +3161,55 @@ var xhrAdapter = isXHRAdapterSupported &&
3107
3161
  };
3108
3162
 
3109
3163
  const composeSignals = (signals, timeout) => {
3110
- const { length } = (signals = signals ? signals.filter(Boolean) : []);
3111
-
3112
- if (timeout || length) {
3113
- let controller = new AbortController();
3114
-
3115
- let aborted;
3116
-
3117
- const onabort = function (reason) {
3118
- if (!aborted) {
3119
- aborted = true;
3120
- unsubscribe();
3121
- const err = reason instanceof Error ? reason : this.reason;
3122
- controller.abort(
3123
- err instanceof AxiosError$1
3124
- ? err
3125
- : new CanceledError$1(err instanceof Error ? err.message : err)
3126
- );
3127
- }
3128
- };
3164
+ signals = signals ? signals.filter(Boolean) : [];
3129
3165
 
3130
- let timer =
3131
- timeout &&
3132
- setTimeout(() => {
3133
- timer = null;
3134
- onabort(new AxiosError$1(`timeout of ${timeout}ms exceeded`, AxiosError$1.ETIMEDOUT));
3135
- }, timeout);
3136
-
3137
- const unsubscribe = () => {
3138
- if (signals) {
3139
- timer && clearTimeout(timer);
3140
- timer = null;
3141
- signals.forEach((signal) => {
3142
- signal.unsubscribe
3143
- ? signal.unsubscribe(onabort)
3144
- : signal.removeEventListener('abort', onabort);
3145
- });
3146
- signals = null;
3147
- }
3148
- };
3166
+ if (!timeout && !signals.length) {
3167
+ return;
3168
+ }
3149
3169
 
3150
- signals.forEach((signal) => signal.addEventListener('abort', onabort));
3170
+ const controller = new AbortController();
3151
3171
 
3152
- const { signal } = controller;
3172
+ let aborted = false;
3153
3173
 
3154
- signal.unsubscribe = () => utils$1.asap(unsubscribe);
3174
+ const onabort = function (reason) {
3175
+ if (!aborted) {
3176
+ aborted = true;
3177
+ unsubscribe();
3178
+ const err = reason instanceof Error ? reason : this.reason;
3179
+ controller.abort(
3180
+ err instanceof AxiosError$1
3181
+ ? err
3182
+ : new CanceledError$1(err instanceof Error ? err.message : err)
3183
+ );
3184
+ }
3185
+ };
3155
3186
 
3156
- return signal;
3157
- }
3187
+ let timer =
3188
+ timeout &&
3189
+ setTimeout(() => {
3190
+ timer = null;
3191
+ onabort(new AxiosError$1(`timeout of ${timeout}ms exceeded`, AxiosError$1.ETIMEDOUT));
3192
+ }, timeout);
3193
+
3194
+ const unsubscribe = () => {
3195
+ if (!signals) { return; }
3196
+ timer && clearTimeout(timer);
3197
+ timer = null;
3198
+ signals.forEach((signal) => {
3199
+ signal.unsubscribe
3200
+ ? signal.unsubscribe(onabort)
3201
+ : signal.removeEventListener('abort', onabort);
3202
+ });
3203
+ signals = null;
3204
+ };
3205
+
3206
+ signals.forEach((signal) => signal.addEventListener('abort', onabort));
3207
+
3208
+ const { signal } = controller;
3209
+
3210
+ signal.unsubscribe = () => utils$1.asap(unsubscribe);
3211
+
3212
+ return signal;
3158
3213
  };
3159
3214
 
3160
3215
  const streamChunk = function* (chunk, chunkSize) {
@@ -3348,12 +3403,41 @@ function estimateDataURLDecodedBytes(url) {
3348
3403
  return bytes;
3349
3404
  }
3350
3405
 
3351
- const VERSION$1 = "1.16.0";
3406
+ const VERSION$1 = "1.17.0";
3352
3407
 
3353
3408
  const DEFAULT_CHUNK_SIZE = 64 * 1024;
3354
3409
 
3355
3410
  const { isFunction } = utils$1;
3356
3411
 
3412
+ /**
3413
+ * Encode a UTF-8 string to a Latin-1 byte string for use with btoa().
3414
+ * This is a modern replacement for the deprecated unescape(encodeURIComponent(str)) pattern.
3415
+ *
3416
+ * @param {string} str The string to encode
3417
+ *
3418
+ * @returns {string} UTF-8 bytes as a Latin-1 string
3419
+ */
3420
+ const encodeUTF8 = (str) =>
3421
+ encodeURIComponent(str).replace(/%([0-9A-F]{2})/gi, (_, hex) =>
3422
+ String.fromCharCode(parseInt(hex, 16))
3423
+ );
3424
+
3425
+ // Node's WHATWG URL parser returns `username` and `password` percent-encoded.
3426
+ // Decode before composing the `auth` option so credentials such as
3427
+ // `my%40email.com:pass` are sent as `my@email.com:pass`. Falls back to the
3428
+ // original value for malformed input so a bad encoding never throws.
3429
+ const decodeURIComponentSafe = (value) => {
3430
+ if (!utils$1.isString(value)) {
3431
+ return value;
3432
+ }
3433
+
3434
+ try {
3435
+ return decodeURIComponent(value);
3436
+ } catch (error) {
3437
+ return value;
3438
+ }
3439
+ };
3440
+
3357
3441
  const test = (fn, ...args) => {
3358
3442
  try {
3359
3443
  return !!fn(...args);
@@ -3362,8 +3446,20 @@ const test = (fn, ...args) => {
3362
3446
  }
3363
3447
  };
3364
3448
 
3449
+ const maybeWithAuthCredentials = (url) => {
3450
+ const protocolIndex = url.indexOf('://');
3451
+ let urlToCheck = url;
3452
+ if (protocolIndex !== -1) {
3453
+ urlToCheck = urlToCheck.slice(protocolIndex + 3);
3454
+ }
3455
+ return urlToCheck.includes('@') || urlToCheck.includes(':');
3456
+ };
3457
+
3365
3458
  const factory = (env) => {
3366
- const globalObject = utils$1.global ?? globalThis;
3459
+ const globalObject =
3460
+ utils$1.global !== undefined && utils$1.global !== null
3461
+ ? utils$1.global
3462
+ : globalThis;
3367
3463
  const { ReadableStream, TextEncoder } = globalObject;
3368
3464
 
3369
3465
  env = utils$1.merge.call(
@@ -3506,6 +3602,7 @@ const factory = (env) => {
3506
3602
 
3507
3603
  const hasMaxContentLength = utils$1.isNumber(maxContentLength) && maxContentLength > -1;
3508
3604
  const hasMaxBodyLength = utils$1.isNumber(maxBodyLength) && maxBodyLength > -1;
3605
+ const own = (key) => (utils$1.hasOwnProp(config, key) ? config[key] : undefined);
3509
3606
 
3510
3607
  let _fetch = envFetch || fetch;
3511
3608
 
@@ -3528,6 +3625,46 @@ const factory = (env) => {
3528
3625
  let requestContentLength;
3529
3626
 
3530
3627
  try {
3628
+ // HTTP basic authentication
3629
+ let auth = undefined;
3630
+ const configAuth = own('auth');
3631
+
3632
+ if (configAuth) {
3633
+ const username = configAuth.username || '';
3634
+ const password = configAuth.password || '';
3635
+ auth = {
3636
+ username,
3637
+ password
3638
+ };
3639
+ }
3640
+
3641
+ if (maybeWithAuthCredentials(url)) {
3642
+ const parsedURL = new URL(url, platform.origin);
3643
+
3644
+ if (!auth && (parsedURL.username || parsedURL.password)) {
3645
+ const urlUsername = decodeURIComponentSafe(parsedURL.username);
3646
+ const urlPassword = decodeURIComponentSafe(parsedURL.password);
3647
+ auth = {
3648
+ username: urlUsername,
3649
+ password: urlPassword
3650
+ };
3651
+ }
3652
+
3653
+ if (parsedURL.username || parsedURL.password) {
3654
+ parsedURL.username = '';
3655
+ parsedURL.password = '';
3656
+ url = parsedURL.href;
3657
+ }
3658
+ }
3659
+
3660
+ if (auth) {
3661
+ headers.delete('authorization');
3662
+ headers.set(
3663
+ 'Authorization',
3664
+ 'Basic ' + btoa(encodeUTF8((auth.username || '') + ':' + (auth.password || '')))
3665
+ );
3666
+ }
3667
+
3531
3668
  // Enforce maxContentLength for data: URLs up-front so we never materialize
3532
3669
  // an oversized payload. The HTTP adapter applies the same check (see http.js
3533
3670
  // "if (protocol === 'data:')" branch).
@@ -3620,7 +3757,7 @@ const factory = (env) => {
3620
3757
  ...fetchOptions,
3621
3758
  signal: composedSignal,
3622
3759
  method: method.toUpperCase(),
3623
- headers: headers.normalize().toJSON(),
3760
+ headers: toByteStringHeaderObject(headers.normalize()),
3624
3761
  body: data,
3625
3762
  duplex: 'half',
3626
3763
  credentials: isCredentialsSupported ? withCredentials : undefined,
@@ -4209,6 +4346,7 @@ let Axios$1 = class Axios {
4209
4346
  forcedJSONParsing: validators.transitional(validators.boolean),
4210
4347
  clarifyTimeoutError: validators.transitional(validators.boolean),
4211
4348
  legacyInterceptorReqResOrdering: validators.transitional(validators.boolean),
4349
+ advertiseZstdAcceptEncoding: validators.transitional(validators.boolean),
4212
4350
  },
4213
4351
  false
4214
4352
  );