axios 1.16.0 → 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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,76 @@
1
1
  # Changelog
2
2
 
3
+ ## v1.16.0 — May 2, 2026
4
+
5
+ This release adds support for the QUERY HTTP method and a new `ECONNREFUSED` error constant, lands a substantial wave of HTTP, fetch, and XHR adapter bug fixes around redirects, aborts, headers, and timeouts, and welcomes 23 new contributors.
6
+
7
+ ## ⚠️ Notable Changes
8
+
9
+ A handful of fixes in this release are either security-adjacent or change observable behaviour. Please review before upgrading:
10
+
11
+ - **Fetch adapter now enforces `maxBodyLength` and `maxContentLength`.** These limits were silently ignored on the fetch adapter prior to 1.16.0 — anyone relying on them as a safety net (DoS protection, accidental large uploads) had no protection. (**#10795**)
12
+ - **Proxy requests now preserve user-supplied `Host` headers.** Previously, the proxy path could overwrite a custom `Host`. Virtual-host-style routing through a proxy will now behave correctly. (**#10822**)
13
+ - **Basic auth credentials embedded in URLs are now URL-decoded.** If you have percent-encoded credentials in a URL (e.g. `https://user:p%40ss@host`), the decoded value is what now goes on the wire. (**#10825**)
14
+ - **`parseProtocol` now strictly requires a colon in the protocol separator.** Strings that loosely parsed as protocols before may no longer match. (**#10729**)
15
+ - **Deprecated `unescape()` replaced with modern UTF-8 encoding.** Non-ASCII URL handling is now spec-correct; consumers depending on legacy `unescape()` quirks may see different output bytes. (**#7378**)
16
+ - **`transformRequest` input typing change was reverted.** The typing change introduced in #10745 was reverted in #10810 after follow-up review — net behavior is unchanged from 1.15.2. (**#10745**, **#10810**)
17
+
18
+ ## 🚀 New Features
19
+
20
+ - **QUERY HTTP Method:** Added support for the QUERY HTTP method across adapters and type definitions. (**#10802**)
21
+ - **ECONNREFUSED Error Constant:** Exposed `ECONNREFUSED` as a constant on `AxiosError` so callers can match connection-refused failures without comparing string literals (closes #6485). (**#10680**)
22
+ - **Encode Helper Export:** Exported the internal `encode` helper from `buildURL` so userland param serializers can reuse the same encoding logic that axios uses internally. (**#6897**)
23
+
24
+ ## 🐛 Bug Fixes
25
+
26
+ - **HTTP Adapter — Redirects & Headers:** Cleared stale headers when a redirect targets a no-proxy host, fixed the redirect listener chain so listeners no longer stack across hops, restored the missing `requestDetails` argument on `beforeRedirect`, preserved user-supplied `Host` headers when forwarding through a proxy, and properly URL-decoded basic auth credentials. (**#10794**, **#10800**, **#6241**, **#10822**, **#10825**)
27
+ - **HTTP Adapter — Streams & Timeouts:** Preserved the partial response object on `AxiosError` when a stream is aborted after headers arrive, honoured the `timeout` option during the connect phase when redirects are disabled, and resolved an unsettled-promise hang when an aborted request was combined with compression and `maxRedirects: 0`. (**#10708**, **#10819**, **#7149**)
28
+ - **Fetch Adapter:** Enforced `maxBodyLength` / `maxContentLength` in the fetch adapter, set the `User-Agent` header to match the HTTP adapter, preserved the original abort reason instead of replacing it with a generic error, and deferred global access so importing the module no longer throws a `TypeError` in restricted environments. (**#10795**, **#10772**, **#10806**, **#7260**)
29
+ - **XHR Adapter:** Unsubscribed the `cancelToken` and `AbortSignal` listeners on the error, timeout, and abort code paths to prevent leaked subscriptions. (**#10787**)
30
+ - **Error Handling:** Attached the parsed response to `AxiosError` when `JSON.parse` fails inside `dispatchRequest`, prevented `settle` from emitting `undefined` error codes, and tightened the `parseProtocol` regex to require a colon in the protocol separator. (**#10724**, **#7276**, **#10729**)
31
+ - **Types & Exports:** Aligned the CommonJS `CancelToken` typings with the ESM build, fixed a compiler error caused by `RawAxiosHeaders`, and re-exported `create` from the package index. (**#7414**, **#6389**, **#6460**)
32
+ - **UTF-8 Encoding:** Replaced the deprecated `unescape()` call with a modern UTF-8 encoding implementation. (**#7378**)
33
+ - **Misc Cleanup:** Resolved a batch of small inconsistencies and gadget-level issues across the codebase. (**#10833**)
34
+
35
+ ## 🔧 Maintenance & Chores
36
+
37
+ - **Refactor — ES6 Modernisation:** Modernised the `utils` module and XHR adapter to use ES6 features, and tidied the multipart boundary error message. (**#10588**, **#7419**)
38
+ - **Tests:** Hardened the HTTP test server lifecycle to fix flaky `FormData` EPIPE failures, fixed Win32 platform support for the pipe tests, and corrected an incorrect test assumption. (**#10820**, **#10791**, **#10796**)
39
+ - **Docs:** Documented `paramsSerializer.encode` for strict RFC 3986 query encoding, updated the `parseReviver` TypeScript definitions and configuration docs for ES2023, added timeout guidance to the README's first async example, and expanded notes around the recent type changes. (**#10821**, **#10782**, **#10759**, **#10804**)
40
+ - **Reverted:** Reverted the `transformRequest` input typing change from #10745 after follow-up review. (**#10745**, **#10810**)
41
+ - **Dependencies:** Bumped `actions/setup-node`, the `github-actions` group, and `postcss` (in `/docs`) to their latest versions. (**#10785**, **#10813**, **#10814**)
42
+ - **Release:** Updated changelog and packages, and prepared the 1.16.0 release. (**#10790**, **#10834**)
43
+
44
+ ## 🌟 New Contributors
45
+
46
+ We are thrilled to welcome our new contributors. Thank you for helping improve axios:
47
+
48
+ - **@singhankit001** (**#10588**)
49
+ - **@cuiweixie** (**#7419**)
50
+ - **@iruizsalinas** (**#10787**)
51
+ - **@MarcosNocetti** (**#10680**)
52
+ - **@deepview-autofix** (**#10729**)
53
+ - **@atharvasingh7007** (**#10745**)
54
+ - **@OfekDanny** (**#10772**)
55
+ - **@mnahkies** (**#7414**)
56
+ - **@tboyila** (**#10759**)
57
+ - **@Kingo64** (**#6897**)
58
+ - **@ramram1048** (**#6389**)
59
+ - **@FLNacif** (**#6460**)
60
+ - **@zozo123** (**#10806**)
61
+ - **@pierluigilenoci** (**#10802**)
62
+ - **@afurm** (**#10708**)
63
+ - **@karan-lrn** (**#7378**)
64
+ - **@ebeigarts** (**#7149**)
65
+ - **@Raymondo97** (**#10782**)
66
+ - **@mixelburg** (**#10821**)
67
+ - **@ashishkr96** (**#10822**)
68
+ - **@cyphercodes** (**#10819**)
69
+ - **@Jye10032** (**#7260**)
70
+ - **@VeerShah41** (**#7276**)
71
+
72
+ [Full Changelog](https://github.com/axios/axios/compare/v1.15.2...v1.16.0)
73
+
3
74
  ## v1.15.2 - April 21, 2026
4
75
 
5
76
  This release delivers prototype-pollution hardening for the Node HTTP adapter, adds an opt-in `allowedSocketPaths` allowlist to mitigate SSRF via Unix domain sockets, fixes a keep-alive socket memory leak, and ships supply-chain hardening across CI and security docs.
package/README.md CHANGED
@@ -244,14 +244,13 @@
244
244
  width="71px"
245
245
  height="70px"
246
246
  src="https://images.opencollective.com/buzzoid-buy-instagram-followers/56a09fe/logo.png"
247
- alt="Buzzoid"
247
+ alt="Buzzoid - Buy Instagram Followers"
248
248
  />
249
249
  </a>
250
250
  <p
251
251
  align="center"
252
252
  >
253
- A lightweight open-source API Development, Testing &amp; Mocking
254
- platform
253
+ At Buzzoid, you can buy Instagram followers quickly, safely, and easily with just a few clicks. Rated world&#39;s #1 IG service since 2012.
255
254
  </p>
256
255
  <p align="center">
257
256
  <a
@@ -263,10 +262,29 @@
263
262
  </td>
264
263
  <td align="center" width="33.333333333333336%">
265
264
  <a
266
- href="https://opencollective.com/axios/contribute"
265
+ href="https://twicsy.com/buy-instagram-followers/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship"
266
+ style="padding: 10px; display: inline-block"
267
267
  target="_blank"
268
- >💜 Become a sponsor</a
269
268
  >
269
+ <img
270
+ width="71px"
271
+ height="70px"
272
+ src="https://images.opencollective.com/buy-instagram-followers-twicsy/b4c5d7f/logo/256.png?height=256"
273
+ alt="Buy Instagram Followers Twicsy"
274
+ />
275
+ </a>
276
+ <p
277
+ align="center"
278
+ >
279
+ Buy real Instagram followers from Twicsy. Twicsy has been voted the best site to buy followers from the likes of US Magazine.
280
+ </p>
281
+ <p align="center">
282
+ <a
283
+ href="https://twicsy.com/buy-instagram-followers/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship"
284
+ target="_blank"
285
+ ><b>twicsy.com</b></a
286
+ >
287
+ </p>
270
288
  </td>
271
289
  <td align="center" width="33.333333333333336%">
272
290
  <a
@@ -495,8 +513,16 @@ axios
495
513
  // Want to use async/await? Add the `async` keyword to your outer function/method.
496
514
  async function getUser() {
497
515
  try {
498
- const response = await axios.get('/user?ID=12345');
499
- console.log(response);
516
+ // Example: GET request with query parameters
517
+ const response = await axios.get('/user', {
518
+ params: {
519
+ ID: 12345
520
+ }
521
+ });
522
+
523
+ // Using the `params` option improves readability and automatically formats query strings
524
+
525
+ console.log(response);
500
526
  } catch (error) {
501
527
  console.error(error);
502
528
  }
@@ -934,15 +960,24 @@ These are the available config options for making requests. Only the `url` is re
934
960
  // Use `false` to disable proxies, ignoring environment variables.
935
961
  // `auth` indicates that HTTP Basic auth should be used to connect to the proxy, and
936
962
  // supplies credentials.
937
- // This will set a `Proxy-Authorization` header, overwriting any existing
938
- // `Proxy-Authorization` custom headers you have set using `headers`.
963
+ // For `http://` targets, axios sends the request to the proxy in
964
+ // forward-proxy mode and stamps `Proxy-Authorization` onto the request
965
+ // headers (overwriting any user-supplied `Proxy-Authorization` header).
966
+ // For `https://` targets, axios establishes a CONNECT tunnel through the
967
+ // proxy and performs TLS end-to-end with the origin; `Proxy-Authorization`
968
+ // is sent on the CONNECT request only, never on the wrapped TLS request,
969
+ // so the proxy never sees the URL, headers, or body. Supply a custom
970
+ // `httpsAgent` to opt out of automatic CONNECT tunneling.
939
971
  // If the proxy server uses HTTPS, then you must set the protocol to `https`.
940
972
  // A user-supplied `Host` header in `headers` is preserved when forwarding
941
973
  // through a proxy (case-insensitive match on `host`/`Host`/`HOST`); this
942
974
  // lets you target a virtual host that differs from the request URL — for
943
975
  // example, hitting `127.0.0.1:4000` while having the proxy treat the
944
976
  // request as `example.com`. If no `Host` header is supplied, axios
945
- // defaults it to the request URL's `hostname:port` as before.
977
+ // defaults it to the request URL's `hostname:port` as before. The Host
978
+ // header is only set in forward-proxy mode (HTTP targets); for HTTPS
979
+ // tunneling the Host header is sent inside the TLS connection, not seen
980
+ // by the proxy.
946
981
  proxy: {
947
982
  protocol: 'https',
948
983
  host: '127.0.0.1',
@@ -1180,7 +1215,7 @@ const instance = axios.create();
1180
1215
  const myInterceptor = instance.interceptors.request.use(function () {
1181
1216
  /*...*/
1182
1217
  });
1183
- axios.interceptors.request.eject(myInterceptor);
1218
+ instance.interceptors.request.eject(myInterceptor);
1184
1219
  ```
1185
1220
 
1186
1221
  You can also clear all interceptors for requests or responses.
package/dist/axios.js CHANGED
@@ -1,4 +1,4 @@
1
- /*! Axios v1.16.0 Copyright (c) 2026 Matt Zabriskie and contributors */
1
+ /*! Axios v1.16.1 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) :
@@ -1291,10 +1291,10 @@
1291
1291
  * @returns {Object} The JSON-compatible object.
1292
1292
  */
1293
1293
  var toJSONObject = function toJSONObject(obj) {
1294
- var stack = new Array(10);
1295
- var _visit = function visit(source, i) {
1294
+ var visited = new WeakSet();
1295
+ var _visit = function visit(source) {
1296
1296
  if (isObject(source)) {
1297
- if (stack.indexOf(source) >= 0) {
1297
+ if (visited.has(source)) {
1298
1298
  return;
1299
1299
  }
1300
1300
 
@@ -1303,19 +1303,20 @@
1303
1303
  return source;
1304
1304
  }
1305
1305
  if (!('toJSON' in source)) {
1306
- stack[i] = source;
1306
+ // add-on descent / delete-on-ascent: preserves path semantics, so DAG nodes serialise at every occurrence (see #7230).
1307
+ visited.add(source);
1307
1308
  var target = isArray(source) ? [] : {};
1308
1309
  forEach(source, function (value, key) {
1309
- var reducedValue = _visit(value, i + 1);
1310
+ var reducedValue = _visit(value);
1310
1311
  !isUndefined(reducedValue) && (target[key] = reducedValue);
1311
1312
  });
1312
- stack[i] = undefined;
1313
+ visited["delete"](source);
1313
1314
  return target;
1314
1315
  }
1315
1316
  }
1316
1317
  return source;
1317
1318
  };
1318
- return _visit(obj, 0);
1319
+ return _visit(obj);
1319
1320
  };
1320
1321
 
1321
1322
  /**
@@ -1487,8 +1488,6 @@
1487
1488
  return parsed;
1488
1489
  });
1489
1490
 
1490
- var $internals = Symbol('internals');
1491
- var INVALID_HEADER_VALUE_CHARS_RE = /[^\x09\x20-\x7E\x80-\xFF]/g;
1492
1491
  function trimSPorHTAB(str) {
1493
1492
  var start = 0;
1494
1493
  var end = str.length;
@@ -1508,12 +1507,38 @@
1508
1507
  }
1509
1508
  return start === 0 && end === str.length ? str : str.slice(start, end);
1510
1509
  }
1510
+
1511
+ // The control-code ranges are intentional: header sanitization strips C0/DEL bytes.
1512
+ // eslint-disable-next-line no-control-regex
1513
+ var INVALID_UNICODE_HEADER_VALUE_CHARS = new RegExp("[\\u0000-\\u0008\\u000a-\\u001f\\u007f]+", 'g');
1514
+ // eslint-disable-next-line no-control-regex
1515
+ var INVALID_BYTE_STRING_HEADER_VALUE_CHARS = new RegExp("[^\\u0009\\u0020-\\u007e\\u0080-\\u00ff]+", 'g');
1516
+ function sanitizeValue(value, invalidChars) {
1517
+ if (utils$1.isArray(value)) {
1518
+ return value.map(function (item) {
1519
+ return sanitizeValue(item, invalidChars);
1520
+ });
1521
+ }
1522
+ return trimSPorHTAB(String(value).replace(invalidChars, ''));
1523
+ }
1524
+ var sanitizeHeaderValue = function sanitizeHeaderValue(value) {
1525
+ return sanitizeValue(value, INVALID_UNICODE_HEADER_VALUE_CHARS);
1526
+ };
1527
+ var sanitizeByteStringHeaderValue = function sanitizeByteStringHeaderValue(value) {
1528
+ return sanitizeValue(value, INVALID_BYTE_STRING_HEADER_VALUE_CHARS);
1529
+ };
1530
+ function toByteStringHeaderObject(headers) {
1531
+ var byteStringHeaders = Object.create(null);
1532
+ utils$1.forEach(headers.toJSON(), function (value, header) {
1533
+ byteStringHeaders[header] = sanitizeByteStringHeaderValue(value);
1534
+ });
1535
+ return byteStringHeaders;
1536
+ }
1537
+
1538
+ var $internals = Symbol('internals');
1511
1539
  function normalizeHeader(header) {
1512
1540
  return header && String(header).trim().toLowerCase();
1513
1541
  }
1514
- function sanitizeHeaderValue(str) {
1515
- return trimSPorHTAB(str.replace(INVALID_HEADER_VALUE_CHARS_RE, ''));
1516
- }
1517
1542
  function normalizeValue(value) {
1518
1543
  if (value === false || value == null) {
1519
1544
  return value;
@@ -2477,7 +2502,7 @@
2477
2502
  }
2478
2503
  return !isNumericKey;
2479
2504
  }
2480
- if (!target[name] || !utils$1.isObject(target[name])) {
2505
+ if (!utils$1.hasOwnProp(target, name) || !utils$1.isObject(target[name])) {
2481
2506
  target[name] = [];
2482
2507
  }
2483
2508
  var result = buildPath(path, value, target[name], index);
@@ -2777,6 +2802,9 @@
2777
2802
  var bytesNotified = 0;
2778
2803
  var _speedometer = speedometer(50, 250);
2779
2804
  return throttle(function (e) {
2805
+ if (!e || typeof e.loaded !== 'number') {
2806
+ return;
2807
+ }
2780
2808
  var rawLoaded = e.loaded;
2781
2809
  var total = e.lengthComputable ? e.total : undefined;
2782
2810
  var loaded = total != null ? Math.min(rawLoaded, total) : rawLoaded;
@@ -3249,7 +3277,7 @@
3249
3277
 
3250
3278
  // Add headers to the request
3251
3279
  if ('setRequestHeader' in request) {
3252
- utils$1.forEach(requestHeaders.toJSON(), function setRequestHeader(val, key) {
3280
+ utils$1.forEach(toByteStringHeaderObject(requestHeaders), function setRequestHeader(val, key) {
3253
3281
  request.setRequestHeader(key, val);
3254
3282
  });
3255
3283
  }
@@ -3311,42 +3339,43 @@
3311
3339
  };
3312
3340
 
3313
3341
  var composeSignals = function composeSignals(signals, timeout) {
3314
- var _signals = signals = signals ? signals.filter(Boolean) : [],
3315
- length = _signals.length;
3316
- if (timeout || length) {
3317
- var controller = new AbortController();
3318
- var aborted;
3319
- var onabort = function onabort(reason) {
3320
- if (!aborted) {
3321
- aborted = true;
3322
- unsubscribe();
3323
- var err = reason instanceof Error ? reason : this.reason;
3324
- controller.abort(err instanceof AxiosError ? err : new CanceledError(err instanceof Error ? err.message : err));
3325
- }
3326
- };
3327
- var timer = timeout && setTimeout(function () {
3328
- timer = null;
3329
- onabort(new AxiosError("timeout of ".concat(timeout, "ms exceeded"), AxiosError.ETIMEDOUT));
3330
- }, timeout);
3331
- var unsubscribe = function unsubscribe() {
3332
- if (signals) {
3333
- timer && clearTimeout(timer);
3334
- timer = null;
3335
- signals.forEach(function (signal) {
3336
- signal.unsubscribe ? signal.unsubscribe(onabort) : signal.removeEventListener('abort', onabort);
3337
- });
3338
- signals = null;
3339
- }
3340
- };
3342
+ signals = signals ? signals.filter(Boolean) : [];
3343
+ if (!timeout && !signals.length) {
3344
+ return;
3345
+ }
3346
+ var controller = new AbortController();
3347
+ var aborted = false;
3348
+ var onabort = function onabort(reason) {
3349
+ if (!aborted) {
3350
+ aborted = true;
3351
+ unsubscribe();
3352
+ var err = reason instanceof Error ? reason : this.reason;
3353
+ controller.abort(err instanceof AxiosError ? err : new CanceledError(err instanceof Error ? err.message : err));
3354
+ }
3355
+ };
3356
+ var timer = timeout && setTimeout(function () {
3357
+ timer = null;
3358
+ onabort(new AxiosError("timeout of ".concat(timeout, "ms exceeded"), AxiosError.ETIMEDOUT));
3359
+ }, timeout);
3360
+ var unsubscribe = function unsubscribe() {
3361
+ if (!signals) {
3362
+ return;
3363
+ }
3364
+ timer && clearTimeout(timer);
3365
+ timer = null;
3341
3366
  signals.forEach(function (signal) {
3342
- return signal.addEventListener('abort', onabort);
3367
+ signal.unsubscribe ? signal.unsubscribe(onabort) : signal.removeEventListener('abort', onabort);
3343
3368
  });
3344
- var signal = controller.signal;
3345
- signal.unsubscribe = function () {
3346
- return utils$1.asap(unsubscribe);
3347
- };
3348
- return signal;
3349
- }
3369
+ signals = null;
3370
+ };
3371
+ signals.forEach(function (signal) {
3372
+ return signal.addEventListener('abort', onabort);
3373
+ });
3374
+ var signal = controller.signal;
3375
+ signal.unsubscribe = function () {
3376
+ return utils$1.asap(unsubscribe);
3377
+ };
3378
+ return signal;
3350
3379
  };
3351
3380
 
3352
3381
  var streamChunk = /*#__PURE__*/_regenerator().m(function streamChunk(chunk, chunkSize) {
@@ -3644,7 +3673,7 @@
3644
3673
  return bytes;
3645
3674
  }
3646
3675
 
3647
- var VERSION = "1.16.0";
3676
+ var VERSION = "1.16.1";
3648
3677
 
3649
3678
  var DEFAULT_CHUNK_SIZE = 64 * 1024;
3650
3679
  var isFunction = utils$1.isFunction;
@@ -3659,8 +3688,7 @@
3659
3688
  }
3660
3689
  };
3661
3690
  var factory = function factory(env) {
3662
- var _utils$global;
3663
- var globalObject = (_utils$global = utils$1.global) !== null && _utils$global !== void 0 ? _utils$global : globalThis;
3691
+ var globalObject = utils$1.global !== undefined && utils$1.global !== null ? utils$1.global : globalThis;
3664
3692
  var ReadableStream = globalObject.ReadableStream,
3665
3693
  TextEncoder = globalObject.TextEncoder;
3666
3694
  env = utils$1.merge.call({
@@ -3900,7 +3928,7 @@
3900
3928
  resolvedOptions = _objectSpread2(_objectSpread2({}, fetchOptions), {}, {
3901
3929
  signal: composedSignal,
3902
3930
  method: method.toUpperCase(),
3903
- headers: headers.normalize().toJSON(),
3931
+ headers: toByteStringHeaderObject(headers.normalize()),
3904
3932
  body: data,
3905
3933
  duplex: 'half',
3906
3934
  credentials: isCredentialsSupported ? withCredentials : undefined