axios 1.14.0 β†’ 1.15.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/CHANGELOG.md CHANGED
@@ -180,7 +180,7 @@
180
180
 
181
181
  ### Bug Fixes
182
182
 
183
- - form-data npm pakcage ([#6970](https://github.com/axios/axios/issues/6970)) ([e72c193](https://github.com/axios/axios/commit/e72c193722530db538b19e5ddaaa4544d226b253))
183
+ - form-data npm package ([#6970](https://github.com/axios/axios/issues/6970)) ([e72c193](https://github.com/axios/axios/commit/e72c193722530db538b19e5ddaaa4544d226b253))
184
184
  - prevent RangeError when using large Buffers ([#6961](https://github.com/axios/axios/issues/6961)) ([a2214ca](https://github.com/axios/axios/commit/a2214ca1bc60540baf2c80573cea3a0ff91ba9d1))
185
185
  - **types:** resolve type discrepancies between ESM and CJS TypeScript declaration files ([#6956](https://github.com/axios/axios/issues/6956)) ([8517aa1](https://github.com/axios/axios/commit/8517aa16f8d082fc1d5309c642220fa736159110))
186
186
 
package/README.md CHANGED
@@ -1,4 +1,6 @@
1
1
  <h3 align="center"> πŸ’Ž Platinum sponsors <br> </h3> <table align="center"><tr><td align="center" width="50%"> <a href="https://thanks.dev/?utm_source&#x3D;axios&amp;utm_medium&#x3D;sponsorlist&amp;utm_campaign&#x3D;sponsorship" style="padding: 10px; display: inline-block" target="_blank"> <img width="90px" height="90px" src="https://axios-http.com/assets/sponsors/opencollective/ed51c2ee8f1b70aa3484d6dd678652134079a036.png" alt="THANKS.DEV"/> </a> <p align="center" title="We&#x27;re passionate about making open source sustainable. Scan your dependancy tree to better understand which open source projects need funding the most. Maintainers can also register their projects to become eligible for funding.">We&#x27;re passionate about making open source sustainable. Scan your dependancy tree to better understand which open source projects need funding the...</p> <p align="center"> <a href="https://thanks.dev/?utm_source&#x3D;axios&amp;utm_medium&#x3D;readme_sponsorlist&amp;utm_campaign&#x3D;sponsorship" target="_blank"><b>thanks.dev</b></a> </p>
2
+ </td><td align="center" width="50%"> <a href="https://opencollective.com/hopper-security?utm_source&#x3D;axios&amp;utm_medium&#x3D;sponsorlist&amp;utm_campaign&#x3D;sponsorship" style="padding: 10px; display: inline-block" target="_blank"> <img width="90px" height="90px" src="https://axios-http.com/assets/sponsors/opencollective/180d02a83ee99448f850e39eed6dbb95f56000ba.png" alt="Hopper Security"/> </a> <p align="center"> </p>
3
+ </td></tr></table><table align="center"><tr><td align="center" width="50%"> <a href="https://opencollective.com/axios/contribute" target="_blank" >πŸ’œ Become a sponsor</a>
2
4
  </td><td align="center" width="50%"> <a href="https://opencollective.com/axios/contribute" target="_blank" >πŸ’œ Become a sponsor</a>
3
5
  </td></tr></table>
4
6
  <h3 align="center"> πŸ₯‡ Gold sponsors <br> </h3> <table align="center" width="100%"><tr width="33.333333333333336%"><td align="center" width="33.333333333333336%"> <a href="https://www.principal.com/about-us?utm_source&#x3D;axios&amp;utm_medium&#x3D;sponsorlist&amp;utm_campaign&#x3D;sponsorship" style="padding: 10px; display: inline-block" target="_blank"> <img width="133px" height="43px" src="https://axios-http.com/assets/sponsors/principal.svg" alt="Principal Financial Group"/> </a> <p align="center" title="We’re bound by one common purpose: to give you the financial tools, resources and information you need to live your best life.">We’re bound by one common purpose: to give you the financial tools, resources and information you ne...</p> <p align="center"> <a href="https://www.principal.com/about-us?utm_source&#x3D;axios&amp;utm_medium&#x3D;readme_sponsorlist&amp;utm_campaign&#x3D;sponsorship" target="_blank"><b>www.principal.com</b></a> </p>
@@ -8,7 +10,7 @@
8
10
  </td><td align="center" width="33.333333333333336%"> <a href="https://buzzoid.com/buy-instagram-followers/?utm_source&#x3D;axios&amp;utm_medium&#x3D;sponsorlist&amp;utm_campaign&#x3D;sponsorship" style="padding: 10px; display: inline-block" target="_blank"> <img width="62px" height="70px" src="https://axios-http.com/assets/sponsors/opencollective/e1625cb54e10ee40180c99d1495a462e9d6664a4.png" alt="Buzzoid - Buy Instagram Followers"/> </a> <p align="center" title="At Buzzoid, you can buy Instagram followers quickly, safely, and easily with just a few clicks. Rated world&#x27;s #1 IG service since 2012.">At Buzzoid, you can buy Instagram followers quickly, safely, and easily with just a few clicks. Rate...</p> <p align="center"> <a href="https://buzzoid.com/buy-instagram-followers/?utm_source&#x3D;axios&amp;utm_medium&#x3D;readme_sponsorlist&amp;utm_campaign&#x3D;sponsorship" target="_blank"><b>buzzoid.com</b></a> </p>
9
11
  </td><td align="center" width="33.333333333333336%"> <a href="https://poprey.com/?utm_source&#x3D;axios&amp;utm_medium&#x3D;sponsorlist&amp;utm_campaign&#x3D;sponsorship" style="padding: 10px; display: inline-block" target="_blank"> <img width="70px" height="70px" src="https://axios-http.com/assets/sponsors/opencollective/e699ec99f7df3a203ddbc49d3c7712a907e628ea.png" alt="Poprey - Buy Instagram Likes"/> </a> <p align="center" title="Buy Instagram Likes">Buy Instagram Likes</p> <p align="center"> <a href="https://poprey.com/?utm_source&#x3D;axios&amp;utm_medium&#x3D;readme_sponsorlist&amp;utm_campaign&#x3D;sponsorship" target="_blank"><b>poprey.com</b></a> </p>
10
12
  </td></tr><tr width="33.333333333333336%"><td align="center" width="33.333333333333336%"> <a href="https://requestly.com/?utm_source&#x3D;axios&amp;utm_medium&#x3D;sponsorlist&amp;utm_campaign&#x3D;sponsorship" style="padding: 10px; display: inline-block" target="_blank"> <img width="71px" height="70px" src="https://axios-http.com/assets/sponsors/opencollective/16450b4dc0deb9dab5a511bf2bc8b8b4ac33412f.png" alt="Requestly"/> </a> <p align="center" title="A lightweight open-source API Development, Testing &amp; Mocking platform">A lightweight open-source API Development, Testing &amp; Mocking platform</p> <p align="center"> <a href="https://requestly.com/?utm_source&#x3D;axios&amp;utm_medium&#x3D;readme_sponsorlist&amp;utm_campaign&#x3D;sponsorship" target="_blank"><b>requestly.com</b></a> </p>
11
- </td><td align="center" width="33.333333333333336%"> <a href="https://opencollective.com/axios/contribute" target="_blank" >πŸ’œ Become a sponsor</a>
13
+ </td><td align="center" width="33.333333333333336%"> <a href="https://rxdb.info/?utm_source&#x3D;opencollective&amp;utm_medium&#x3D;banner&amp;utm_campaign&#x3D;opencollective_sponsor&amp;utm_content&#x3D;logo" style="padding: 10px; display: inline-block" target="_blank"> <img width="158px" height="70px" src="https://axios-http.com/assets/sponsors/opencollective/b28cc6ed919b414cb5f3d4a6d666cb8e06c5ff07.png" alt="RxDB"/> </a> <p align="center" title="RxDB is a fast, local-first NoSQL-database for JavaScript Applications like Websites, hybrid Apps, Electron-Apps, Progressive Web Apps and Node.js">RxDB is a fast, local-first NoSQL-database for JavaScript Applications like Websites, hybrid Apps, E...</p> <p align="center"> <a href="https://rxdb.info/?utm_source&#x3D;opencollective&amp;utm_medium&#x3D;banner&amp;utm_campaign&#x3D;opencollective_sponsor&amp;utm_content&#x3D;logo" target="_blank"><b>rxdb.info</b></a> </p>
12
14
  </td><td align="center" width="33.333333333333336%"> <a href="https://opencollective.com/axios/contribute" target="_blank" >πŸ’œ Become a sponsor</a>
13
15
  </td></tr></table>
14
16
 
@@ -458,6 +460,8 @@ These are the available config options for making requests. Only the `url` is re
458
460
 
459
461
  // `withCredentials` indicates whether or not cross-site Access-Control requests
460
462
  // should be made using credentials
463
+ // This only controls whether the browser sends credentials.
464
+ // It does not control whether the XSRF header is added.
461
465
  withCredentials: false, // default
462
466
 
463
467
  // `adapter` allows custom handling of requests which makes testing easier.
@@ -497,7 +501,11 @@ These are the available config options for making requests. Only the `url` is re
497
501
  // `xsrfHeaderName` is the name of the http header that carries the xsrf token value
498
502
  xsrfHeaderName: 'X-XSRF-TOKEN', // default
499
503
 
504
+ // `withXSRFToken` defines whether to send the XSRF header in browser requests.
500
505
  // `undefined` (default) - set XSRF header only for the same origin requests
506
+ // `true` - always set XSRF header, including for cross-origin requests
507
+ // `false` - never set XSRF header
508
+ // function - resolve with custom logic; receives the internal config object
501
509
  withXSRFToken: boolean | undefined | ((config: InternalAxiosRequestConfig) => boolean | undefined),
502
510
 
503
511
  // `withXSRFToken` controls whether Axios reads the XSRF cookie and sets the XSRF header.
@@ -552,11 +560,27 @@ These are the available config options for making requests. Only the `url` is re
552
560
  // to inspect the latest response headers,
553
561
  // or to cancel the request by throwing an error
554
562
  // If maxRedirects is set to 0, `beforeRedirect` is not used.
563
+
555
564
  beforeRedirect: (options, { headers }) => {
556
- if (options.hostname === "example.com") {
565
+ if (
566
+ options.hostname === "example.com" &&
567
+ options.protocol === "https:"
568
+ ) {
557
569
  options.auth = "user:password";
558
570
  }
559
571
  },
572
+ // Security note:
573
+ // The `beforeRedirect` hook runs after sensitive headers are stripped during redirects.
574
+ //The `follow-redirects` library removes credentials on protocol downgrade (HTTPS β†’ HTTP) for security.
575
+ //Since `beforeRedirect` runs after this, re-injecting credentials without checking the protocol can expose sensitive data.
576
+ //Always ensure credentials are only added for trusted HTTPS destinations.
577
+
578
+ // Security note:
579
+ // The beforeRedirect hook runs after sensitive headers are stripped during redirects.
580
+ // Re-injecting credentials without checking the destination can expose sensitive data.
581
+ // Only add credentials for trusted HTTPS destinations.
582
+ // Avoid re-adding credentials on downgraded redirects.
583
+
560
584
 
561
585
  // `socketPath` defines a UNIX Socket to be used in node.js.
562
586
  // e.g. '/var/run/docker.sock' to send requests to the docker daemon.
@@ -664,6 +688,15 @@ These are the available config options for making requests. Only the `url` is re
664
688
  ]
665
689
  }
666
690
  ```
691
+ ## πŸ”₯ HTTP/2 Support
692
+
693
+ Axios has experimental HTTP/2 support available via the Node.js HTTP adapter.
694
+
695
+ Support depends on the runtime environment and Node.js version. Features like redirects and some behaviors may not be fully supported with HTTP/2.
696
+
697
+ Options like `httpVersion` and `http2Options` are adapter-specific and may not work consistently across all environments.
698
+
699
+ If HTTP/2 functionality is required, ensure your runtime environment supports it or consider using alternative libraries or custom adapters.
667
700
 
668
701
  ## Response Schema
669
702
 
@@ -994,15 +1027,25 @@ async function fetchWithTimeout() {
994
1027
  try {
995
1028
  const response = await axios.get("https://example.com/data", {
996
1029
  timeout: 5000, // 5 seconds
1030
+ transitional: {
1031
+ // set to true if you prefer ETIMEDOUT over ECONNABORTED
1032
+ clarifyTimeoutError: false,
1033
+ },
997
1034
  });
998
1035
 
999
1036
  console.log("Response:", response.data);
1000
1037
  } catch (error) {
1001
- if (axios.isAxiosError(error) && error.code === "ECONNABORTED") {
1002
- console.error("❌ Request timed out!");
1003
- } else {
1004
- console.error("❌ Error:", error.message);
1038
+ if (axios.isAxiosError(error)) {
1039
+ if (error.code === "ECONNABORTED" || error.code === "ETIMEDOUT") {
1040
+ console.error("Request timed out. Please try again.");
1041
+ return;
1042
+ }
1043
+
1044
+ console.error("Axios error:", error.message);
1045
+ return;
1005
1046
  }
1047
+
1048
+ console.error("Unexpected error:", error);
1006
1049
  }
1007
1050
  }
1008
1051
  ```
@@ -1553,6 +1596,38 @@ for (const [header, value] of headers) {
1553
1596
  // baz 3
1554
1597
  ```
1555
1598
 
1599
+ ### Preserving a specific header case
1600
+
1601
+ Header names are case-insensitive, but `AxiosHeaders` keeps the case of the first matching key it sees.
1602
+ If you need a specific case for non-standard case-sensitive servers, define a case preset with `undefined` and then set the value later:
1603
+
1604
+ ```js
1605
+ const api = axios.create();
1606
+
1607
+ api.defaults.headers.common = {
1608
+ 'content-type': undefined,
1609
+ accept: undefined,
1610
+ };
1611
+
1612
+ await api.put(url, data, {
1613
+ headers: {
1614
+ 'Content-Type': 'application/octet-stream',
1615
+ Accept: 'application/json',
1616
+ },
1617
+ });
1618
+ ```
1619
+
1620
+ You can also compose the same behavior with `AxiosHeaders.concat`:
1621
+
1622
+ ```js
1623
+ const headers = axios.AxiosHeaders.concat(
1624
+ { 'content-type': undefined },
1625
+ { 'Content-Type': 'application/octet-stream' }
1626
+ );
1627
+
1628
+ await axios.put(url, data, { headers });
1629
+ ```
1630
+
1556
1631
  ### new AxiosHeaders(headers?)
1557
1632
 
1558
1633
  Constructs a new `AxiosHeaders` instance.
@@ -1843,12 +1918,15 @@ export async function load({ fetch }) {
1843
1918
  }
1844
1919
  ```
1845
1920
 
1846
- ## πŸ”₯ HTTP2
1921
+ #### HTTP/2 Support
1922
+
1923
+ Axios supports HTTP/2 via the Node.js `http` adapter (introduced in v1.13.0).
1924
+
1925
+ This support depends on the runtime environment. Since Axios relies on Node.js APIs, HTTP/2 functionality is available in supported Node.js versions, but may not work in other environments (such as Bun or Deno).
1847
1926
 
1848
- In version `1.13.0`, experimental `HTTP2` support was added to the `http` adapter.
1849
- The `httpVersion` option is now available to select the protocol version used.
1850
- Additional native options for the internal `session.request()` call can be passed via the `http2Options` config.
1851
- This config also includes the custom `sessionTimeout` parameter, which defaults to `1000ms`.
1927
+ Options like `httpVersion` and `http2Options` are adapter-specific and may not behave consistently across all environments.
1928
+
1929
+ Note: HTTP/2 redirects are currently not supported by the HTTP/2 adapter.
1852
1930
 
1853
1931
  ```js
1854
1932
  const form = new FormData();
@@ -1859,11 +1937,6 @@ const { data, headers, status } = await axios.post(
1859
1937
  "https://httpbin.org/post",
1860
1938
  form,
1861
1939
  {
1862
- httpVersion: 2,
1863
- http2Options: {
1864
- // rejectUnauthorized: false,
1865
- // sessionTimeout: 1000
1866
- },
1867
1940
  onUploadProgress(e) {
1868
1941
  console.log("upload progress", e);
1869
1942
  },
@@ -1871,7 +1944,7 @@ const { data, headers, status } = await axios.post(
1871
1944
  console.log("download progress", e);
1872
1945
  },
1873
1946
  responseType: "arraybuffer",
1874
- },
1947
+ }
1875
1948
  );
1876
1949
  ```
1877
1950
 
package/dist/axios.js CHANGED
@@ -1,4 +1,4 @@
1
- /*! Axios v1.14.0 Copyright (c) 2026 Matt Zabriskie and contributors */
1
+ /*! Axios v1.15.0 Copyright (c) 2026 Matt Zabriskie and contributors */
2
2
  (function (global, factory) {
3
3
  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
4
4
  typeof define === 'function' && define.amd ? define(factory) :
@@ -2196,14 +2196,42 @@
2196
2196
  });
2197
2197
 
2198
2198
  var $internals = Symbol('internals');
2199
+ var isValidHeaderValue = function isValidHeaderValue(value) {
2200
+ return !/[\r\n]/.test(value);
2201
+ };
2202
+ function assertValidHeaderValue(value, header) {
2203
+ if (value === false || value == null) {
2204
+ return;
2205
+ }
2206
+ if (utils$1.isArray(value)) {
2207
+ value.forEach(function (v) {
2208
+ return assertValidHeaderValue(v, header);
2209
+ });
2210
+ return;
2211
+ }
2212
+ if (!isValidHeaderValue(String(value))) {
2213
+ throw new Error("Invalid character in header content [\"".concat(header, "\"]"));
2214
+ }
2215
+ }
2199
2216
  function normalizeHeader(header) {
2200
2217
  return header && String(header).trim().toLowerCase();
2201
2218
  }
2219
+ function stripTrailingCRLF(str) {
2220
+ var end = str.length;
2221
+ while (end > 0) {
2222
+ var charCode = str.charCodeAt(end - 1);
2223
+ if (charCode !== 10 && charCode !== 13) {
2224
+ break;
2225
+ }
2226
+ end -= 1;
2227
+ }
2228
+ return end === str.length ? str : str.slice(0, end);
2229
+ }
2202
2230
  function normalizeValue(value) {
2203
2231
  if (value === false || value == null) {
2204
2232
  return value;
2205
2233
  }
2206
- return utils$1.isArray(value) ? value.map(normalizeValue) : String(value).replace(/[\r\n]+$/, '');
2234
+ return utils$1.isArray(value) ? value.map(normalizeValue) : stripTrailingCRLF(String(value));
2207
2235
  }
2208
2236
  function parseTokens(str) {
2209
2237
  var tokens = Object.create(null);
@@ -2264,6 +2292,7 @@
2264
2292
  }
2265
2293
  var key = utils$1.findKey(self, lHeader);
2266
2294
  if (!key || self[key] === undefined || _rewrite === true || _rewrite === undefined && self[key] !== false) {
2295
+ assertValidHeaderValue(_value, _header);
2267
2296
  self[key || _header] = normalizeValue(_value);
2268
2297
  }
2269
2298
  }
@@ -3831,7 +3860,7 @@
3831
3860
  });
3832
3861
  }
3833
3862
 
3834
- var VERSION = "1.14.0";
3863
+ var VERSION = "1.15.0";
3835
3864
 
3836
3865
  var validators$1 = {};
3837
3866
 
@@ -3946,7 +3975,7 @@
3946
3975
  key: "request",
3947
3976
  value: (function () {
3948
3977
  var _request2 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee(configOrUrl, config) {
3949
- var dummy, stack, _t;
3978
+ var dummy, stack, firstNewlineIndex, secondNewlineIndex, stackWithoutTwoTopLines, _t;
3950
3979
  return _regenerator().w(function (_context) {
3951
3980
  while (1) switch (_context.p = _context.n) {
3952
3981
  case 0:
@@ -3963,13 +3992,24 @@
3963
3992
  Error.captureStackTrace ? Error.captureStackTrace(dummy) : dummy = new Error();
3964
3993
 
3965
3994
  // slice off the Error: ... line
3966
- stack = dummy.stack ? dummy.stack.replace(/^.+\n/, '') : '';
3995
+ stack = function () {
3996
+ if (!dummy.stack) {
3997
+ return '';
3998
+ }
3999
+ var firstNewlineIndex = dummy.stack.indexOf('\n');
4000
+ return firstNewlineIndex === -1 ? '' : dummy.stack.slice(firstNewlineIndex + 1);
4001
+ }();
3967
4002
  try {
3968
4003
  if (!_t.stack) {
3969
4004
  _t.stack = stack;
3970
4005
  // match without the 2 top stack lines
3971
- } else if (stack && !String(_t.stack).endsWith(stack.replace(/^.+\n.+\n/, ''))) {
3972
- _t.stack += '\n' + stack;
4006
+ } else if (stack) {
4007
+ firstNewlineIndex = stack.indexOf('\n');
4008
+ secondNewlineIndex = firstNewlineIndex === -1 ? -1 : stack.indexOf('\n', firstNewlineIndex + 1);
4009
+ stackWithoutTwoTopLines = secondNewlineIndex === -1 ? '' : stack.slice(secondNewlineIndex + 1);
4010
+ if (!String(_t.stack).endsWith(stackWithoutTwoTopLines)) {
4011
+ _t.stack += '\n' + stack;
4012
+ }
3973
4013
  }
3974
4014
  } catch (e) {
3975
4015
  // ignore the case where "stack" is an un-writable property