axios 1.16.1 → 1.18.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 +94 -1
- package/README.md +267 -239
- package/dist/axios.js +454 -146
- package/dist/axios.min.js +3 -3
- package/dist/axios.min.js.map +1 -1
- package/dist/browser/axios.cjs +470 -99
- package/dist/esm/axios.js +470 -99
- package/dist/esm/axios.min.js +2 -2
- package/dist/esm/axios.min.js.map +1 -1
- package/dist/node/axios.cjs +638 -201
- package/index.d.cts +10 -3
- package/index.d.ts +6 -1
- package/lib/adapters/fetch.js +190 -35
- package/lib/adapters/http.js +192 -159
- package/lib/core/Axios.js +4 -2
- package/lib/core/AxiosHeaders.js +12 -9
- package/lib/core/buildFullPath.js +29 -1
- package/lib/core/mergeConfig.js +34 -0
- package/lib/defaults/transitional.js +2 -0
- package/lib/env/data.js +1 -1
- package/lib/helpers/Http2Sessions.js +119 -0
- package/lib/helpers/buildURL.js +6 -4
- package/lib/helpers/estimateDataURLDecodedBytes.js +16 -11
- package/lib/helpers/formDataToJSON.js +25 -3
- package/lib/helpers/formDataToStream.js +2 -2
- package/lib/helpers/resolveConfig.js +17 -9
- package/lib/helpers/shouldBypassProxy.js +33 -1
- package/lib/helpers/toFormData.js +41 -11
- package/lib/utils.js +97 -12
- package/package.json +29 -13
- package/dist/axios.js.map +0 -1
- package/dist/browser/axios.cjs.map +0 -1
- package/dist/esm/axios.js.map +0 -1
- package/dist/node/axios.cjs.map +0 -1
package/index.d.cts
CHANGED
|
@@ -66,7 +66,9 @@ declare class AxiosHeaders {
|
|
|
66
66
|
...targets: Array<AxiosHeaders | axios.RawAxiosHeaders | string | undefined | null>
|
|
67
67
|
): AxiosHeaders;
|
|
68
68
|
|
|
69
|
-
toJSON(asStrings
|
|
69
|
+
toJSON(asStrings: true): Record<string, string>;
|
|
70
|
+
toJSON(asStrings?: false): Record<string, string | string[]>;
|
|
71
|
+
toJSON(asStrings?: boolean): Record<string, string | string[]>;
|
|
70
72
|
|
|
71
73
|
static from(thing?: AxiosHeaders | axios.RawAxiosHeaders | string): AxiosHeaders;
|
|
72
74
|
|
|
@@ -162,7 +164,9 @@ declare class AxiosError<T = unknown, D = any> extends Error {
|
|
|
162
164
|
static readonly ETIMEDOUT = 'ETIMEDOUT';
|
|
163
165
|
}
|
|
164
166
|
|
|
165
|
-
declare class CanceledError<T> extends AxiosError<T> {
|
|
167
|
+
declare class CanceledError<T> extends AxiosError<T> {
|
|
168
|
+
readonly name: 'CanceledError';
|
|
169
|
+
}
|
|
166
170
|
|
|
167
171
|
declare class Axios {
|
|
168
172
|
constructor(config?: axios.AxiosRequestConfig);
|
|
@@ -392,6 +396,8 @@ declare namespace axios {
|
|
|
392
396
|
forcedJSONParsing?: boolean;
|
|
393
397
|
clarifyTimeoutError?: boolean;
|
|
394
398
|
legacyInterceptorReqResOrdering?: boolean;
|
|
399
|
+
advertiseZstdAcceptEncoding?: boolean;
|
|
400
|
+
validateStatusUndefinedResolves?: boolean;
|
|
395
401
|
}
|
|
396
402
|
|
|
397
403
|
interface GenericAbortSignal {
|
|
@@ -554,6 +560,7 @@ declare namespace axios {
|
|
|
554
560
|
};
|
|
555
561
|
formDataHeaderPolicy?: 'legacy' | 'content-only';
|
|
556
562
|
redact?: string[];
|
|
563
|
+
sensitiveHeaders?: string[];
|
|
557
564
|
}
|
|
558
565
|
|
|
559
566
|
// Alias
|
|
@@ -691,7 +698,7 @@ declare namespace axios {
|
|
|
691
698
|
CanceledError: typeof CanceledError;
|
|
692
699
|
HttpStatusCode: typeof HttpStatusCode;
|
|
693
700
|
readonly VERSION: string;
|
|
694
|
-
isCancel(value: any): value is
|
|
701
|
+
isCancel<T = any>(value: any): value is CanceledError<T>;
|
|
695
702
|
all<T>(values: Array<T | Promise<T>>): Promise<T[]>;
|
|
696
703
|
spread<T, R>(callback: (...args: T[]) => R): (array: T[]) => R;
|
|
697
704
|
isAxiosError<T = any, D = any>(payload: any): payload is AxiosError<T, D>;
|
package/index.d.ts
CHANGED
|
@@ -47,7 +47,9 @@ export class AxiosHeaders {
|
|
|
47
47
|
...targets: Array<AxiosHeaders | RawAxiosHeaders | string | undefined | null>
|
|
48
48
|
): AxiosHeaders;
|
|
49
49
|
|
|
50
|
-
toJSON(asStrings
|
|
50
|
+
toJSON(asStrings: true): Record<string, string>;
|
|
51
|
+
toJSON(asStrings?: false): Record<string, string | string[]>;
|
|
52
|
+
toJSON(asStrings?: boolean): Record<string, string | string[]>;
|
|
51
53
|
|
|
52
54
|
static from(thing?: AxiosHeaders | RawAxiosHeaders | string): AxiosHeaders;
|
|
53
55
|
|
|
@@ -281,6 +283,8 @@ export interface TransitionalOptions {
|
|
|
281
283
|
forcedJSONParsing?: boolean;
|
|
282
284
|
clarifyTimeoutError?: boolean;
|
|
283
285
|
legacyInterceptorReqResOrdering?: boolean;
|
|
286
|
+
advertiseZstdAcceptEncoding?: boolean;
|
|
287
|
+
validateStatusUndefinedResolves?: boolean;
|
|
284
288
|
}
|
|
285
289
|
|
|
286
290
|
export interface GenericAbortSignal {
|
|
@@ -449,6 +453,7 @@ export interface AxiosRequestConfig<D = any> {
|
|
|
449
453
|
};
|
|
450
454
|
formDataHeaderPolicy?: 'legacy' | 'content-only';
|
|
451
455
|
redact?: string[];
|
|
456
|
+
sensitiveHeaders?: string[];
|
|
452
457
|
}
|
|
453
458
|
|
|
454
459
|
// Alias
|
package/lib/adapters/fetch.js
CHANGED
|
@@ -19,6 +19,35 @@ const DEFAULT_CHUNK_SIZE = 64 * 1024;
|
|
|
19
19
|
|
|
20
20
|
const { isFunction } = utils;
|
|
21
21
|
|
|
22
|
+
/**
|
|
23
|
+
* Encode a UTF-8 string to a Latin-1 byte string for use with btoa().
|
|
24
|
+
* This is a modern replacement for the deprecated unescape(encodeURIComponent(str)) pattern.
|
|
25
|
+
*
|
|
26
|
+
* @param {string} str The string to encode
|
|
27
|
+
*
|
|
28
|
+
* @returns {string} UTF-8 bytes as a Latin-1 string
|
|
29
|
+
*/
|
|
30
|
+
const encodeUTF8 = (str) =>
|
|
31
|
+
encodeURIComponent(str).replace(/%([0-9A-F]{2})/gi, (_, hex) =>
|
|
32
|
+
String.fromCharCode(parseInt(hex, 16))
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
// Node's WHATWG URL parser returns `username` and `password` percent-encoded.
|
|
36
|
+
// Decode before composing the `auth` option so credentials such as
|
|
37
|
+
// `my%40email.com:pass` are sent as `my@email.com:pass`. Falls back to the
|
|
38
|
+
// original value for malformed input so a bad encoding never throws.
|
|
39
|
+
const decodeURIComponentSafe = (value) => {
|
|
40
|
+
if (!utils.isString(value)) {
|
|
41
|
+
return value;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
try {
|
|
45
|
+
return decodeURIComponent(value);
|
|
46
|
+
} catch (error) {
|
|
47
|
+
return value;
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
|
|
22
51
|
const test = (fn, ...args) => {
|
|
23
52
|
try {
|
|
24
53
|
return !!fn(...args);
|
|
@@ -27,6 +56,15 @@ const test = (fn, ...args) => {
|
|
|
27
56
|
}
|
|
28
57
|
};
|
|
29
58
|
|
|
59
|
+
const maybeWithAuthCredentials = (url) => {
|
|
60
|
+
const protocolIndex = url.indexOf('://');
|
|
61
|
+
let urlToCheck = url;
|
|
62
|
+
if (protocolIndex !== -1) {
|
|
63
|
+
urlToCheck = urlToCheck.slice(protocolIndex + 3);
|
|
64
|
+
}
|
|
65
|
+
return urlToCheck.includes('@') || urlToCheck.includes(':');
|
|
66
|
+
};
|
|
67
|
+
|
|
30
68
|
const factory = (env) => {
|
|
31
69
|
const globalObject =
|
|
32
70
|
utils.global !== undefined && utils.global !== null
|
|
@@ -174,6 +212,7 @@ const factory = (env) => {
|
|
|
174
212
|
|
|
175
213
|
const hasMaxContentLength = utils.isNumber(maxContentLength) && maxContentLength > -1;
|
|
176
214
|
const hasMaxBodyLength = utils.isNumber(maxBodyLength) && maxBodyLength > -1;
|
|
215
|
+
const own = (key) => (utils.hasOwnProp(config, key) ? config[key] : undefined);
|
|
177
216
|
|
|
178
217
|
let _fetch = envFetch || fetch;
|
|
179
218
|
|
|
@@ -195,7 +234,61 @@ const factory = (env) => {
|
|
|
195
234
|
|
|
196
235
|
let requestContentLength;
|
|
197
236
|
|
|
237
|
+
// AxiosError we raise while the request body is being streamed. Captured
|
|
238
|
+
// by identity so the catch block can surface it directly, regardless of
|
|
239
|
+
// how the runtime wraps the resulting fetch rejection (undici exposes it
|
|
240
|
+
// as `err.cause`; some browsers drop the original error entirely).
|
|
241
|
+
let pendingBodyError = null;
|
|
242
|
+
|
|
243
|
+
const maxBodyLengthError = () =>
|
|
244
|
+
new AxiosError(
|
|
245
|
+
'Request body larger than maxBodyLength limit',
|
|
246
|
+
AxiosError.ERR_BAD_REQUEST,
|
|
247
|
+
config,
|
|
248
|
+
request
|
|
249
|
+
);
|
|
250
|
+
|
|
198
251
|
try {
|
|
252
|
+
// HTTP basic authentication
|
|
253
|
+
let auth = undefined;
|
|
254
|
+
const configAuth = own('auth');
|
|
255
|
+
|
|
256
|
+
if (configAuth) {
|
|
257
|
+
const username = utils.getSafeProp(configAuth, 'username') || '';
|
|
258
|
+
const password = utils.getSafeProp(configAuth, 'password') || '';
|
|
259
|
+
auth = {
|
|
260
|
+
username,
|
|
261
|
+
password
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
if (maybeWithAuthCredentials(url)) {
|
|
266
|
+
const parsedURL = new URL(url, platform.origin);
|
|
267
|
+
|
|
268
|
+
if (!auth && (parsedURL.username || parsedURL.password)) {
|
|
269
|
+
const urlUsername = decodeURIComponentSafe(parsedURL.username);
|
|
270
|
+
const urlPassword = decodeURIComponentSafe(parsedURL.password);
|
|
271
|
+
auth = {
|
|
272
|
+
username: urlUsername,
|
|
273
|
+
password: urlPassword
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
if (parsedURL.username || parsedURL.password) {
|
|
278
|
+
parsedURL.username = '';
|
|
279
|
+
parsedURL.password = '';
|
|
280
|
+
url = parsedURL.href;
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
if (auth) {
|
|
285
|
+
headers.delete('authorization');
|
|
286
|
+
headers.set(
|
|
287
|
+
'Authorization',
|
|
288
|
+
'Basic ' + btoa(encodeUTF8((auth.username || '') + ':' + (auth.password || '')))
|
|
289
|
+
);
|
|
290
|
+
}
|
|
291
|
+
|
|
199
292
|
// Enforce maxContentLength for data: URLs up-front so we never materialize
|
|
200
293
|
// an oversized payload. The HTTP adapter applies the same check (see http.js
|
|
201
294
|
// "if (protocol === 'data:')" branch).
|
|
@@ -211,53 +304,96 @@ const factory = (env) => {
|
|
|
211
304
|
}
|
|
212
305
|
}
|
|
213
306
|
|
|
214
|
-
// Enforce maxBodyLength against
|
|
215
|
-
//
|
|
216
|
-
//
|
|
217
|
-
//
|
|
307
|
+
// Enforce maxBodyLength against known-size bodies before dispatch using
|
|
308
|
+
// the body's *actual* size — never a caller-declared Content-Length,
|
|
309
|
+
// which could under-report to slip an oversized body past the check.
|
|
310
|
+
// Unknown-size streams return undefined here and are counted per-chunk
|
|
311
|
+
// below as fetch consumes them.
|
|
218
312
|
if (hasMaxBodyLength && method !== 'get' && method !== 'head') {
|
|
219
|
-
const outboundLength = await
|
|
220
|
-
if (
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
throw new AxiosError(
|
|
226
|
-
'Request body larger than maxBodyLength limit',
|
|
227
|
-
AxiosError.ERR_BAD_REQUEST,
|
|
228
|
-
config,
|
|
229
|
-
request
|
|
230
|
-
);
|
|
313
|
+
const outboundLength = await getBodyLength(data);
|
|
314
|
+
if (typeof outboundLength === 'number' && isFinite(outboundLength)) {
|
|
315
|
+
requestContentLength = outboundLength;
|
|
316
|
+
if (outboundLength > maxBodyLength) {
|
|
317
|
+
throw maxBodyLengthError();
|
|
318
|
+
}
|
|
231
319
|
}
|
|
232
320
|
}
|
|
233
321
|
|
|
322
|
+
// A streamed body under maxBodyLength must be counted as fetch consumes
|
|
323
|
+
// it; its size is never trusted from a caller-declared Content-Length.
|
|
324
|
+
const mustEnforceStreamBody =
|
|
325
|
+
hasMaxBodyLength && (utils.isReadableStream(data) || utils.isStream(data));
|
|
326
|
+
|
|
327
|
+
const trackRequestStream = (stream, onProgress, flush) =>
|
|
328
|
+
trackStream(
|
|
329
|
+
stream,
|
|
330
|
+
DEFAULT_CHUNK_SIZE,
|
|
331
|
+
(loadedBytes) => {
|
|
332
|
+
if (hasMaxBodyLength && loadedBytes > maxBodyLength) {
|
|
333
|
+
throw (pendingBodyError = maxBodyLengthError());
|
|
334
|
+
}
|
|
335
|
+
onProgress && onProgress(loadedBytes);
|
|
336
|
+
},
|
|
337
|
+
flush
|
|
338
|
+
);
|
|
339
|
+
|
|
234
340
|
if (
|
|
235
|
-
onUploadProgress &&
|
|
236
341
|
supportsRequestStream &&
|
|
237
342
|
method !== 'get' &&
|
|
238
343
|
method !== 'head' &&
|
|
239
|
-
(
|
|
344
|
+
(onUploadProgress || mustEnforceStreamBody)
|
|
240
345
|
) {
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
346
|
+
requestContentLength =
|
|
347
|
+
requestContentLength == null ? await resolveBodyLength(headers, data) : requestContentLength;
|
|
348
|
+
|
|
349
|
+
// A declared length of 0 is only trusted to skip the wrap when we are
|
|
350
|
+
// not enforcing a stream limit (which must not rely on that header).
|
|
351
|
+
if (requestContentLength !== 0 || mustEnforceStreamBody) {
|
|
352
|
+
let _request = new Request(url, {
|
|
353
|
+
method: 'POST',
|
|
354
|
+
body: data,
|
|
355
|
+
duplex: 'half',
|
|
356
|
+
});
|
|
246
357
|
|
|
247
|
-
|
|
358
|
+
let contentTypeHeader;
|
|
248
359
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
360
|
+
if (utils.isFormData(data) && (contentTypeHeader = _request.headers.get('content-type'))) {
|
|
361
|
+
headers.setContentType(contentTypeHeader);
|
|
362
|
+
}
|
|
252
363
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
364
|
+
if (_request.body) {
|
|
365
|
+
const [onProgress, flush] =
|
|
366
|
+
(onUploadProgress &&
|
|
367
|
+
progressEventDecorator(
|
|
368
|
+
requestContentLength,
|
|
369
|
+
progressEventReducer(asyncDecorator(onUploadProgress))
|
|
370
|
+
)) ||
|
|
371
|
+
[];
|
|
258
372
|
|
|
259
|
-
|
|
373
|
+
data = trackRequestStream(_request.body, onProgress, flush);
|
|
374
|
+
}
|
|
260
375
|
}
|
|
376
|
+
} else if (
|
|
377
|
+
mustEnforceStreamBody &&
|
|
378
|
+
!isRequestSupported &&
|
|
379
|
+
isReadableStreamSupported &&
|
|
380
|
+
method !== 'get' &&
|
|
381
|
+
method !== 'head'
|
|
382
|
+
) {
|
|
383
|
+
data = trackRequestStream(data);
|
|
384
|
+
} else if (
|
|
385
|
+
mustEnforceStreamBody &&
|
|
386
|
+
isRequestSupported &&
|
|
387
|
+
!supportsRequestStream &&
|
|
388
|
+
method !== 'get' &&
|
|
389
|
+
method !== 'head'
|
|
390
|
+
) {
|
|
391
|
+
throw new AxiosError(
|
|
392
|
+
'Stream request bodies are not supported by the current fetch implementation',
|
|
393
|
+
AxiosError.ERR_NOT_SUPPORT,
|
|
394
|
+
config,
|
|
395
|
+
request
|
|
396
|
+
);
|
|
261
397
|
}
|
|
262
398
|
|
|
263
399
|
if (!utils.isString(withCredentials)) {
|
|
@@ -300,10 +436,12 @@ const factory = (env) => {
|
|
|
300
436
|
? _fetch(request, fetchOptions)
|
|
301
437
|
: _fetch(url, resolvedOptions));
|
|
302
438
|
|
|
439
|
+
const responseHeaders = AxiosHeaders.from(response.headers);
|
|
440
|
+
|
|
303
441
|
// Cheap pre-check: if the server honestly declares a content-length that
|
|
304
442
|
// already exceeds the cap, reject before we start streaming.
|
|
305
443
|
if (hasMaxContentLength) {
|
|
306
|
-
const declaredLength = utils.toFiniteNumber(
|
|
444
|
+
const declaredLength = utils.toFiniteNumber(responseHeaders.getContentLength());
|
|
307
445
|
if (declaredLength != null && declaredLength > maxContentLength) {
|
|
308
446
|
throw new AxiosError(
|
|
309
447
|
'maxContentLength size of ' + maxContentLength + ' exceeded',
|
|
@@ -328,7 +466,7 @@ const factory = (env) => {
|
|
|
328
466
|
options[prop] = response[prop];
|
|
329
467
|
});
|
|
330
468
|
|
|
331
|
-
const responseContentLength = utils.toFiniteNumber(
|
|
469
|
+
const responseContentLength = utils.toFiniteNumber(responseHeaders.getContentLength());
|
|
332
470
|
|
|
333
471
|
const [onProgress, flush] =
|
|
334
472
|
(onDownloadProgress &&
|
|
@@ -423,6 +561,23 @@ const factory = (env) => {
|
|
|
423
561
|
throw canceledError;
|
|
424
562
|
}
|
|
425
563
|
|
|
564
|
+
// Surface a maxBodyLength violation we raised while the request body was
|
|
565
|
+
// being streamed. Matching by identity (rather than reading
|
|
566
|
+
// `err.cause.isAxiosError`) keeps the error deterministic across runtimes
|
|
567
|
+
// and avoids both prototype-pollution reads and mis-attributing a foreign
|
|
568
|
+
// AxiosError that merely happened to land in `err.cause`.
|
|
569
|
+
if (pendingBodyError) {
|
|
570
|
+
request && !pendingBodyError.request && (pendingBodyError.request = request);
|
|
571
|
+
throw pendingBodyError;
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
// Re-throw AxiosErrors we raised synchronously (data: URL / content-length
|
|
575
|
+
// pre-checks, response size enforcement) without re-wrapping them.
|
|
576
|
+
if (err instanceof AxiosError) {
|
|
577
|
+
request && !err.request && (err.request = request);
|
|
578
|
+
throw err;
|
|
579
|
+
}
|
|
580
|
+
|
|
426
581
|
if (err && err.name === 'TypeError' && /Load failed|fetch/i.test(err.message)) {
|
|
427
582
|
throw Object.assign(
|
|
428
583
|
new AxiosError(
|