axios 1.15.2 → 1.16.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/CHANGELOG.md +103 -6
  2. package/README.md +396 -25
  3. package/dist/axios.js +1455 -1109
  4. package/dist/axios.js.map +1 -1
  5. package/dist/axios.min.js +3 -3
  6. package/dist/axios.min.js.map +1 -1
  7. package/dist/browser/axios.cjs +1569 -1174
  8. package/dist/browser/axios.cjs.map +1 -1
  9. package/dist/esm/axios.js +1569 -1173
  10. package/dist/esm/axios.js.map +1 -1
  11. package/dist/esm/axios.min.js +2 -2
  12. package/dist/esm/axios.min.js.map +1 -1
  13. package/dist/node/axios.cjs +1395 -915
  14. package/dist/node/axios.cjs.map +1 -1
  15. package/index.d.cts +25 -13
  16. package/index.d.ts +21 -4
  17. package/index.js +2 -0
  18. package/lib/adapters/adapters.js +4 -2
  19. package/lib/adapters/fetch.js +131 -11
  20. package/lib/adapters/http.js +298 -69
  21. package/lib/adapters/xhr.js +8 -3
  22. package/lib/core/Axios.js +7 -3
  23. package/lib/core/AxiosError.js +86 -1
  24. package/lib/core/AxiosHeaders.js +4 -33
  25. package/lib/core/dispatchRequest.js +19 -7
  26. package/lib/core/mergeConfig.js +6 -3
  27. package/lib/core/settle.js +7 -11
  28. package/lib/defaults/index.js +1 -1
  29. package/lib/env/data.js +1 -1
  30. package/lib/helpers/buildURL.js +1 -1
  31. package/lib/helpers/composeSignals.js +48 -47
  32. package/lib/helpers/cookies.js +14 -2
  33. package/lib/helpers/estimateDataURLDecodedBytes.js +28 -1
  34. package/lib/helpers/formDataToJSON.js +1 -1
  35. package/lib/helpers/formDataToStream.js +1 -1
  36. package/lib/helpers/fromDataURI.js +18 -5
  37. package/lib/helpers/parseProtocol.js +1 -1
  38. package/lib/helpers/progressEventReducer.js +3 -0
  39. package/lib/helpers/resolveConfig.js +33 -17
  40. package/lib/helpers/sanitizeHeaderValue.js +60 -0
  41. package/lib/helpers/shouldBypassProxy.js +26 -1
  42. package/lib/helpers/validator.js +1 -1
  43. package/lib/utils.js +35 -22
  44. package/package.json +19 -24
@@ -87,6 +87,31 @@ const parseNoProxyEntry = (entry) => {
87
87
  return [entryHost, entryPort];
88
88
  };
89
89
 
90
+ // Convert IPv4-mapped IPv6 (::ffff:0:0/96 prefix) to IPv4 dotted form so both
91
+ // sides of a NO_PROXY comparison see the same canonical address. Without this,
92
+ // `NO_PROXY=192.168.1.5` would not match a request to `http://[::ffff:192.168.1.5]/`
93
+ // (Node's URL parser normalises that to `[::ffff:c0a8:105]`), and vice-versa,
94
+ // allowing the proxy-bypass policy to be circumvented by using the alternate
95
+ // representation. Returns the input unchanged when not IPv4-mapped.
96
+ const IPV4_MAPPED_DOTTED_RE = /^(?:::|(?:0{1,4}:){1,4}:|(?:0{1,4}:){5})ffff:(\d+\.\d+\.\d+\.\d+)$/i;
97
+ const IPV4_MAPPED_HEX_RE = /^(?:::|(?:0{1,4}:){1,4}:|(?:0{1,4}:){5})ffff:([0-9a-f]{1,4}):([0-9a-f]{1,4})$/i;
98
+
99
+ const unmapIPv4MappedIPv6 = (host) => {
100
+ if (typeof host !== 'string' || host.indexOf(':') === -1) return host;
101
+
102
+ const dotted = host.match(IPV4_MAPPED_DOTTED_RE);
103
+ if (dotted) return dotted[1];
104
+
105
+ const hex = host.match(IPV4_MAPPED_HEX_RE);
106
+ if (hex) {
107
+ const high = parseInt(hex[1], 16);
108
+ const low = parseInt(hex[2], 16);
109
+ return `${high >> 8}.${high & 0xff}.${low >> 8}.${low & 0xff}`;
110
+ }
111
+
112
+ return host;
113
+ };
114
+
90
115
  const normalizeNoProxyHost = (hostname) => {
91
116
  if (!hostname) {
92
117
  return hostname;
@@ -96,7 +121,7 @@ const normalizeNoProxyHost = (hostname) => {
96
121
  hostname = hostname.slice(1, -1);
97
122
  }
98
123
 
99
- return hostname.replace(/\.+$/, '');
124
+ return unmapIPv4MappedIPv6(hostname.replace(/\.+$/, ''));
100
125
  };
101
126
 
102
127
  export default function shouldBypassProxy(location) {
@@ -87,7 +87,7 @@ function assertOptions(options, schema, allowUnknown) {
87
87
  while (i-- > 0) {
88
88
  const opt = keys[i];
89
89
  // Use hasOwnProperty so a polluted Object.prototype.<opt> cannot supply
90
- // a non-function validator and cause a TypeError. See GHSA-q8qp-cvcw-x6jj.
90
+ // a non-function validator and cause a TypeError.
91
91
  const validator = Object.prototype.hasOwnProperty.call(schema, opt) ? schema[opt] : undefined;
92
92
  if (validator) {
93
93
  const value = options[opt];
package/lib/utils.js CHANGED
@@ -192,21 +192,21 @@ const isFile = kindOfTest('File');
192
192
  * also have a `name` and `type` attribute to specify filename and content type
193
193
  *
194
194
  * @see https://github.com/facebook/react-native/blob/26684cf3adf4094eb6c405d345a75bf8c7c0bf88/Libraries/Network/FormData.js#L68-L71
195
- *
195
+ *
196
196
  * @param {*} value The value to test
197
- *
197
+ *
198
198
  * @returns {boolean} True if value is a React Native Blob, otherwise false
199
199
  */
200
200
  const isReactNativeBlob = (value) => {
201
201
  return !!(value && typeof value.uri !== 'undefined');
202
- }
202
+ };
203
203
 
204
204
  /**
205
205
  * Determine if environment is React Native
206
206
  * ReactNative `FormData` has a non-standard `getParts()` method
207
- *
207
+ *
208
208
  * @param {*} formData The formData to test
209
- *
209
+ *
210
210
  * @returns {boolean} True if environment is React Native, otherwise false
211
211
  */
212
212
  const isReactNative = (formData) => formData && typeof formData.getParts !== 'undefined';
@@ -225,7 +225,7 @@ const isBlob = kindOfTest('Blob');
225
225
  *
226
226
  * @param {*} val The value to test
227
227
  *
228
- * @returns {boolean} True if value is a File, otherwise false
228
+ * @returns {boolean} True if value is a FileList, otherwise false
229
229
  */
230
230
  const isFileList = kindOfTest('FileList');
231
231
 
@@ -259,14 +259,16 @@ const FormDataCtor = typeof G.FormData !== 'undefined' ? G.FormData : undefined;
259
259
  const isFormData = (thing) => {
260
260
  if (!thing) return false;
261
261
  if (FormDataCtor && thing instanceof FormDataCtor) return true;
262
- // Reject plain objects inheriting directly from Object.prototype so prototype-pollution gadgets can't spoof FormData (GHSA-6chq-wfr3-2hj9).
262
+ // Reject plain objects inheriting directly from Object.prototype so prototype-pollution gadgets can't spoof FormData.
263
263
  const proto = getPrototypeOf(thing);
264
264
  if (!proto || proto === Object.prototype) return false;
265
265
  if (!isFunction(thing.append)) return false;
266
266
  const kind = kindOf(thing);
267
- return kind === 'formdata' ||
267
+ return (
268
+ kind === 'formdata' ||
268
269
  // detect form-data instance
269
- (kind === 'object' && isFunction(thing.toString) && thing.toString() === '[object FormData]');
270
+ (kind === 'object' && isFunction(thing.toString) && thing.toString() === '[object FormData]')
271
+ );
270
272
  };
271
273
 
272
274
  /**
@@ -401,7 +403,7 @@ const isContextDefined = (context) => !isUndefined(context) && context !== _glob
401
403
  *
402
404
  * @returns {Object} Result of all merge properties
403
405
  */
404
- function merge(/* obj1, obj2, obj3, ... */) {
406
+ function merge(...objs) {
405
407
  const { caseless, skipUndefined } = (isContextDefined(this) && this) || {};
406
408
  const result = {};
407
409
  const assignValue = (val, key) => {
@@ -411,8 +413,12 @@ function merge(/* obj1, obj2, obj3, ... */) {
411
413
  }
412
414
 
413
415
  const targetKey = (caseless && findKey(result, key)) || key;
414
- if (isPlainObject(result[targetKey]) && isPlainObject(val)) {
415
- result[targetKey] = merge(result[targetKey], val);
416
+ // Read via own-prop only — a bare `result[targetKey]` walks the prototype
417
+ // chain, so a polluted Object.prototype value could surface here and get
418
+ // copied into the merged result.
419
+ const existing = hasOwnProperty(result, targetKey) ? result[targetKey] : undefined;
420
+ if (isPlainObject(existing) && isPlainObject(val)) {
421
+ result[targetKey] = merge(existing, val);
416
422
  } else if (isPlainObject(val)) {
417
423
  result[targetKey] = merge({}, val);
418
424
  } else if (isArray(val)) {
@@ -422,8 +428,8 @@ function merge(/* obj1, obj2, obj3, ... */) {
422
428
  }
423
429
  };
424
430
 
425
- for (let i = 0, l = arguments.length; i < l; i++) {
426
- arguments[i] && forEach(arguments[i], assignValue);
431
+ for (let i = 0, l = objs.length; i < l; i++) {
432
+ objs[i] && forEach(objs[i], assignValue);
427
433
  }
428
434
  return result;
429
435
  }
@@ -445,6 +451,9 @@ const extend = (a, b, thisArg, { allOwnKeys } = {}) => {
445
451
  (val, key) => {
446
452
  if (thisArg && isFunction(val)) {
447
453
  Object.defineProperty(a, key, {
454
+ // Null-proto descriptor so a polluted Object.prototype.get cannot
455
+ // hijack defineProperty's accessor-vs-data resolution.
456
+ __proto__: null,
448
457
  value: bind(val, thisArg),
449
458
  writable: true,
450
459
  enumerable: true,
@@ -452,6 +461,7 @@ const extend = (a, b, thisArg, { allOwnKeys } = {}) => {
452
461
  });
453
462
  } else {
454
463
  Object.defineProperty(a, key, {
464
+ __proto__: null,
455
465
  value: val,
456
466
  writable: true,
457
467
  enumerable: true,
@@ -490,12 +500,14 @@ const stripBOM = (content) => {
490
500
  const inherits = (constructor, superConstructor, props, descriptors) => {
491
501
  constructor.prototype = Object.create(superConstructor.prototype, descriptors);
492
502
  Object.defineProperty(constructor.prototype, 'constructor', {
503
+ __proto__: null,
493
504
  value: constructor,
494
505
  writable: true,
495
506
  enumerable: false,
496
507
  configurable: true,
497
508
  });
498
509
  Object.defineProperty(constructor, 'super', {
510
+ __proto__: null,
499
511
  value: superConstructor.prototype,
500
512
  });
501
513
  props && Object.assign(constructor.prototype, props);
@@ -677,7 +689,7 @@ const reduceDescriptors = (obj, reducer) => {
677
689
  const freezeMethods = (obj) => {
678
690
  reduceDescriptors(obj, (descriptor, name) => {
679
691
  // skip restricted props in strict mode
680
- if (isFunction(obj) && ['arguments', 'caller', 'callee'].indexOf(name) !== -1) {
692
+ if (isFunction(obj) && ['arguments', 'caller', 'callee'].includes(name)) {
681
693
  return false;
682
694
  }
683
695
 
@@ -751,11 +763,11 @@ function isSpecCompliantForm(thing) {
751
763
  * @returns {Object} The JSON-compatible object.
752
764
  */
753
765
  const toJSONObject = (obj) => {
754
- const stack = new Array(10);
766
+ const visited = new WeakSet();
755
767
 
756
- const visit = (source, i) => {
768
+ const visit = (source) => {
757
769
  if (isObject(source)) {
758
- if (stack.indexOf(source) >= 0) {
770
+ if (visited.has(source)) {
759
771
  return;
760
772
  }
761
773
 
@@ -765,15 +777,16 @@ const toJSONObject = (obj) => {
765
777
  }
766
778
 
767
779
  if (!('toJSON' in source)) {
768
- stack[i] = source;
780
+ // add-on descent / delete-on-ascent: preserves path semantics, so DAG nodes serialise at every occurrence (see #7230).
781
+ visited.add(source);
769
782
  const target = isArray(source) ? [] : {};
770
783
 
771
784
  forEach(source, (value, key) => {
772
- const reducedValue = visit(value, i + 1);
785
+ const reducedValue = visit(value);
773
786
  !isUndefined(reducedValue) && (target[key] = reducedValue);
774
787
  });
775
788
 
776
- stack[i] = undefined;
789
+ visited.delete(source);
777
790
 
778
791
  return target;
779
792
  }
@@ -782,7 +795,7 @@ const toJSONObject = (obj) => {
782
795
  return source;
783
796
  };
784
797
 
785
- return visit(obj, 0);
798
+ return visit(obj);
786
799
  };
787
800
 
788
801
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "axios",
3
- "version": "1.15.2",
3
+ "version": "1.16.1",
4
4
  "description": "Promise based HTTP client for the browser and node.js",
5
5
  "main": "./dist/node/axios.cjs",
6
6
  "module": "./index.js",
@@ -82,13 +82,13 @@
82
82
  "Dmitriy Mozgovoy (https://github.com/DigitalBrainJS)",
83
83
  "Nick Uraltsev (https://github.com/nickuraltsev)",
84
84
  "Emily Morehouse (https://github.com/emilyemorehouse)",
85
- "Justin Beckwith (https://github.com/JustinBeckwith)",
86
85
  "Rubén Norte (https://github.com/rubennorte)",
86
+ "Justin Beckwith (https://github.com/JustinBeckwith)",
87
87
  "Martti Laine (https://github.com/codeclown)",
88
88
  "Xianming Zhong (https://github.com/chinesedfan)",
89
- "Remco Haszing (https://github.com/remcohaszing)",
90
- "Shaan Majid (https://github.com/shaanmajid)",
91
89
  "Willian Agostini (https://github.com/WillianAgostini)",
90
+ "Shaan Majid (https://github.com/shaanmajid)",
91
+ "Remco Haszing (https://github.com/remcohaszing)",
92
92
  "Rikki Gibson (https://github.com/RikkiGibson)"
93
93
  ],
94
94
  "sideEffects": false,
@@ -121,15 +121,16 @@
121
121
  "prepare": "husky"
122
122
  },
123
123
  "dependencies": {
124
- "follow-redirects": "^1.15.11",
124
+ "follow-redirects": "^1.16.0",
125
125
  "form-data": "^4.0.5",
126
+ "https-proxy-agent": "^5.0.1",
126
127
  "proxy-from-env": "^2.1.0"
127
128
  },
128
129
  "devDependencies": {
129
130
  "@babel/core": "^7.29.0",
130
- "@babel/preset-env": "^7.29.0",
131
- "@commitlint/cli": "^20.4.4",
132
- "@commitlint/config-conventional": "^20.4.4",
131
+ "@babel/preset-env": "^7.29.2",
132
+ "@commitlint/cli": "^20.5.0",
133
+ "@commitlint/config-conventional": "^20.5.0",
133
134
  "@eslint/js": "^10.0.1",
134
135
  "@rollup/plugin-alias": "^6.0.0",
135
136
  "@rollup/plugin-babel": "^7.0.0",
@@ -137,40 +138,34 @@
137
138
  "@rollup/plugin-json": "^6.1.0",
138
139
  "@rollup/plugin-node-resolve": "^16.0.3",
139
140
  "@rollup/plugin-terser": "^1.0.0",
140
- "@vitest/browser": "^4.1.1",
141
- "@vitest/browser-playwright": "^4.1.1",
141
+ "@vitest/browser": "^4.1.5",
142
+ "@vitest/browser-playwright": "^4.1.5",
142
143
  "abortcontroller-polyfill": "^1.7.8",
143
- "auto-changelog": "^2.5.0",
144
+ "acorn": "^8.16.0",
144
145
  "body-parser": "^2.2.2",
145
146
  "chalk": "^5.6.2",
146
147
  "cross-env": "^10.1.0",
147
148
  "dev-null": "^0.1.1",
148
- "eslint": "^10.1.0",
149
+ "eslint": "^10.2.1",
149
150
  "express": "^5.2.1",
150
151
  "formdata-node": "^6.0.3",
151
- "formidable": "^3.2.4",
152
+ "formidable": "^3.5.4",
152
153
  "fs-extra": "^11.3.4",
153
154
  "get-stream": "^9.0.1",
154
- "globals": "^17.4.0",
155
+ "globals": "^17.5.0",
155
156
  "gulp": "^5.0.1",
156
- "handlebars": "^4.7.8",
157
157
  "husky": "^9.1.7",
158
158
  "lint-staged": "^16.4.0",
159
- "memoizee": "^0.4.17",
160
159
  "minimist": "^1.2.8",
161
160
  "multer": "^2.1.1",
162
- "pacote": "^21.5.0",
163
- "playwright": "^1.58.2",
164
- "prettier": "^3.8.1",
165
- "pretty-bytes": "^7.1.0",
166
- "rollup": "^4.60.0",
161
+ "playwright": "^1.59.1",
162
+ "prettier": "^3.8.3",
163
+ "rollup": "^4.60.2",
167
164
  "rollup-plugin-bundle-size": "^1.0.3",
168
165
  "selfsigned": "^5.5.0",
169
166
  "stream-throttle": "^0.1.3",
170
- "string-replace-async": "^3.0.2",
171
- "tar-stream": "^3.1.8",
172
167
  "typescript": "^5.9.3",
173
- "vitest": "^4.1.1"
168
+ "vitest": "^4.1.5"
174
169
  },
175
170
  "commitlint": {
176
171
  "rules": {