axios 1.17.0 → 1.18.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/index.d.cts CHANGED
@@ -50,6 +50,7 @@ declare class AxiosHeaders {
50
50
  rewrite?: boolean | AxiosHeaderMatcher
51
51
  ): AxiosHeaders;
52
52
  set(headers?: axios.RawAxiosHeaders | AxiosHeaders | string, rewrite?: boolean): AxiosHeaders;
53
+ set(headers?: Iterable<[string, axios.AxiosHeaderValue]>, rewrite?: boolean): AxiosHeaders;
53
54
 
54
55
  get(headerName: string, parser: RegExp): RegExpExecArray | null;
55
56
  get(headerName: string, matcher?: true | AxiosHeaderParser): axios.AxiosHeaderValue;
@@ -119,6 +120,8 @@ declare class AxiosHeaders {
119
120
 
120
121
  getSetCookie(): string[];
121
122
 
123
+ toString(): string;
124
+
122
125
  [Symbol.iterator](): IterableIterator<[string, axios.AxiosHeaderValue]>;
123
126
  }
124
127
 
@@ -165,7 +168,9 @@ declare class AxiosError<T = unknown, D = any> extends Error {
165
168
  }
166
169
 
167
170
  declare class CanceledError<T> extends AxiosError<T> {
171
+ constructor(message?: string, config?: axios.InternalAxiosRequestConfig, request?: any);
168
172
  readonly name: 'CanceledError';
173
+ __CANCEL__?: boolean;
169
174
  }
170
175
 
171
176
  declare class Axios {
@@ -296,6 +301,12 @@ declare enum HttpStatusCode {
296
301
  LoopDetected = 508,
297
302
  NotExtended = 510,
298
303
  NetworkAuthenticationRequired = 511,
304
+ WebServerIsDown = 521,
305
+ ConnectionTimedOut = 522,
306
+ OriginIsUnreachable = 523,
307
+ TimeoutOccurred = 524,
308
+ SslHandshakeFailed = 525,
309
+ InvalidSslCertificate = 526,
299
310
  }
300
311
 
301
312
  type InternalAxiosError<T = unknown, D = any> = AxiosError<T, D>;
@@ -397,6 +408,7 @@ declare namespace axios {
397
408
  clarifyTimeoutError?: boolean;
398
409
  legacyInterceptorReqResOrdering?: boolean;
399
410
  advertiseZstdAcceptEncoding?: boolean;
411
+ validateStatusUndefinedResolves?: boolean;
400
412
  }
401
413
 
402
414
  interface GenericAbortSignal {
@@ -427,6 +439,8 @@ declare namespace axios {
427
439
  dots?: boolean;
428
440
  metaTokens?: boolean;
429
441
  indexes?: boolean | null;
442
+ maxDepth?: number;
443
+ Blob?: { new (...args: any[]): any };
430
444
  }
431
445
 
432
446
  // tslint:disable-next-line
@@ -559,6 +573,7 @@ declare namespace axios {
559
573
  };
560
574
  formDataHeaderPolicy?: 'legacy' | 'content-only';
561
575
  redact?: string[];
576
+ sensitiveHeaders?: string[];
562
577
  }
563
578
 
564
579
  // Alias
@@ -623,6 +638,9 @@ declare namespace axios {
623
638
  promise: Promise<Cancel>;
624
639
  reason?: Cancel;
625
640
  throwIfRequested(): void;
641
+ subscribe(listener: (cancel: Cancel | any) => void): void;
642
+ unsubscribe(listener: (cancel: Cancel | any) => void): void;
643
+ toAbortSignal(): AbortSignal;
626
644
  }
627
645
 
628
646
  interface CancelTokenSource {
@@ -689,7 +707,7 @@ declare namespace axios {
689
707
  }
690
708
 
691
709
  interface AxiosStatic extends AxiosInstance {
692
- Cancel: CancelStatic;
710
+ Cancel: typeof CanceledError;
693
711
  CancelToken: CancelTokenStatic;
694
712
  Axios: typeof Axios;
695
713
  AxiosError: typeof AxiosError;
package/index.d.ts CHANGED
@@ -31,6 +31,7 @@ export class AxiosHeaders {
31
31
  rewrite?: boolean | AxiosHeaderMatcher
32
32
  ): AxiosHeaders;
33
33
  set(headers?: RawAxiosHeaders | AxiosHeaders | string, rewrite?: boolean): AxiosHeaders;
34
+ set(headers?: Iterable<[string, AxiosHeaderValue]>, rewrite?: boolean): AxiosHeaders;
34
35
 
35
36
  get(headerName: string, parser: RegExp): RegExpExecArray | null;
36
37
  get(headerName: string, matcher?: true | AxiosHeaderParser): AxiosHeaderValue;
@@ -91,6 +92,8 @@ export class AxiosHeaders {
91
92
 
92
93
  getSetCookie(): string[];
93
94
 
95
+ toString(): string;
96
+
94
97
  [Symbol.iterator](): IterableIterator<[string, AxiosHeaderValue]>;
95
98
  }
96
99
 
@@ -233,6 +236,12 @@ export enum HttpStatusCode {
233
236
  LoopDetected = 508,
234
237
  NotExtended = 510,
235
238
  NetworkAuthenticationRequired = 511,
239
+ WebServerIsDown = 521,
240
+ ConnectionTimedOut = 522,
241
+ OriginIsUnreachable = 523,
242
+ TimeoutOccurred = 524,
243
+ SslHandshakeFailed = 525,
244
+ InvalidSslCertificate = 526,
236
245
  }
237
246
 
238
247
  type UppercaseMethod =
@@ -284,6 +293,7 @@ export interface TransitionalOptions {
284
293
  clarifyTimeoutError?: boolean;
285
294
  legacyInterceptorReqResOrdering?: boolean;
286
295
  advertiseZstdAcceptEncoding?: boolean;
296
+ validateStatusUndefinedResolves?: boolean;
287
297
  }
288
298
 
289
299
  export interface GenericAbortSignal {
@@ -314,6 +324,8 @@ export interface SerializerOptions {
314
324
  dots?: boolean;
315
325
  metaTokens?: boolean;
316
326
  indexes?: boolean | null;
327
+ maxDepth?: number;
328
+ Blob?: { new (...args: any[]): any };
317
329
  }
318
330
 
319
331
  // tslint:disable-next-line
@@ -452,6 +464,7 @@ export interface AxiosRequestConfig<D = any> {
452
464
  };
453
465
  formDataHeaderPolicy?: 'legacy' | 'content-only';
454
466
  redact?: string[];
467
+ sensitiveHeaders?: string[];
455
468
  }
456
469
 
457
470
  // Alias
@@ -536,7 +549,9 @@ export class AxiosError<T = unknown, D = any> extends Error {
536
549
  }
537
550
 
538
551
  export class CanceledError<T> extends AxiosError<T> {
552
+ constructor(message?: string, config?: InternalAxiosRequestConfig, request?: any);
539
553
  readonly name: 'CanceledError';
554
+ __CANCEL__?: boolean;
540
555
  }
541
556
 
542
557
  export type AxiosPromise<T = any> = Promise<AxiosResponse<T>>;
@@ -562,6 +577,9 @@ export interface CancelToken {
562
577
  promise: Promise<Cancel>;
563
578
  reason?: Cancel;
564
579
  throwIfRequested(): void;
580
+ subscribe(listener: (cancel: Cancel | any) => void): void;
581
+ unsubscribe(listener: (cancel: Cancel | any) => void): void;
582
+ toAbortSignal(): AbortSignal;
565
583
  }
566
584
 
567
585
  export interface CancelTokenSource {
@@ -714,7 +732,7 @@ export function mergeConfig<D = any>(
714
732
  export function create(config?: CreateAxiosDefaults): AxiosInstance;
715
733
 
716
734
  export interface AxiosStatic extends AxiosInstance {
717
- Cancel: CancelStatic;
735
+ Cancel: typeof CanceledError;
718
736
  CancelToken: CancelTokenStatic;
719
737
  Axios: typeof Axios;
720
738
  AxiosError: typeof AxiosError;
@@ -107,7 +107,7 @@ function getAdapter(adapters, config) {
107
107
 
108
108
  throw new AxiosError(
109
109
  `There is no suitable adapter to dispatch the request ` + s,
110
- 'ERR_NOT_SUPPORT'
110
+ AxiosError.ERR_NOT_SUPPORT
111
111
  );
112
112
  }
113
113
 
@@ -234,14 +234,28 @@ const factory = (env) => {
234
234
 
235
235
  let requestContentLength;
236
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
+
237
251
  try {
238
252
  // HTTP basic authentication
239
253
  let auth = undefined;
240
254
  const configAuth = own('auth');
241
255
 
242
256
  if (configAuth) {
243
- const username = configAuth.username || '';
244
- const password = configAuth.password || '';
257
+ const username = utils.getSafeProp(configAuth, 'username') || '';
258
+ const password = utils.getSafeProp(configAuth, 'password') || '';
245
259
  auth = {
246
260
  username,
247
261
  password
@@ -290,53 +304,96 @@ const factory = (env) => {
290
304
  }
291
305
  }
292
306
 
293
- // Enforce maxBodyLength against the outbound request body before dispatch.
294
- // Mirrors http.js behavior (ERR_BAD_REQUEST / 'Request body larger than
295
- // maxBodyLength limit'). Skip when the body length cannot be determined
296
- // (e.g. a live ReadableStream supplied by the caller).
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.
297
312
  if (hasMaxBodyLength && method !== 'get' && method !== 'head') {
298
- const outboundLength = await resolveBodyLength(headers, data);
299
- if (
300
- typeof outboundLength === 'number' &&
301
- isFinite(outboundLength) &&
302
- outboundLength > maxBodyLength
303
- ) {
304
- throw new AxiosError(
305
- 'Request body larger than maxBodyLength limit',
306
- AxiosError.ERR_BAD_REQUEST,
307
- config,
308
- request
309
- );
313
+ const outboundLength = await getBodyLength(data);
314
+ if (typeof outboundLength === 'number' && isFinite(outboundLength)) {
315
+ requestContentLength = outboundLength;
316
+ if (outboundLength > maxBodyLength) {
317
+ throw maxBodyLengthError();
318
+ }
310
319
  }
311
320
  }
312
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
+
313
340
  if (
314
- onUploadProgress &&
315
341
  supportsRequestStream &&
316
342
  method !== 'get' &&
317
343
  method !== 'head' &&
318
- (requestContentLength = await resolveBodyLength(headers, data)) !== 0
344
+ (onUploadProgress || mustEnforceStreamBody)
319
345
  ) {
320
- let _request = new Request(url, {
321
- method: 'POST',
322
- body: data,
323
- duplex: 'half',
324
- });
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
+ });
325
357
 
326
- let contentTypeHeader;
358
+ let contentTypeHeader;
327
359
 
328
- if (utils.isFormData(data) && (contentTypeHeader = _request.headers.get('content-type'))) {
329
- headers.setContentType(contentTypeHeader);
330
- }
360
+ if (utils.isFormData(data) && (contentTypeHeader = _request.headers.get('content-type'))) {
361
+ headers.setContentType(contentTypeHeader);
362
+ }
331
363
 
332
- if (_request.body) {
333
- const [onProgress, flush] = progressEventDecorator(
334
- requestContentLength,
335
- progressEventReducer(asyncDecorator(onUploadProgress))
336
- );
364
+ if (_request.body) {
365
+ const [onProgress, flush] =
366
+ (onUploadProgress &&
367
+ progressEventDecorator(
368
+ requestContentLength,
369
+ progressEventReducer(asyncDecorator(onUploadProgress))
370
+ )) ||
371
+ [];
337
372
 
338
- data = trackStream(_request.body, DEFAULT_CHUNK_SIZE, onProgress, flush);
373
+ data = trackRequestStream(_request.body, onProgress, flush);
374
+ }
339
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
+ );
340
397
  }
341
398
 
342
399
  if (!utils.isString(withCredentials)) {
@@ -379,10 +436,12 @@ const factory = (env) => {
379
436
  ? _fetch(request, fetchOptions)
380
437
  : _fetch(url, resolvedOptions));
381
438
 
439
+ const responseHeaders = AxiosHeaders.from(response.headers);
440
+
382
441
  // Cheap pre-check: if the server honestly declares a content-length that
383
442
  // already exceeds the cap, reject before we start streaming.
384
443
  if (hasMaxContentLength) {
385
- const declaredLength = utils.toFiniteNumber(response.headers.get('content-length'));
444
+ const declaredLength = utils.toFiniteNumber(responseHeaders.getContentLength());
386
445
  if (declaredLength != null && declaredLength > maxContentLength) {
387
446
  throw new AxiosError(
388
447
  'maxContentLength size of ' + maxContentLength + ' exceeded',
@@ -407,7 +466,7 @@ const factory = (env) => {
407
466
  options[prop] = response[prop];
408
467
  });
409
468
 
410
- const responseContentLength = utils.toFiniteNumber(response.headers.get('content-length'));
469
+ const responseContentLength = utils.toFiniteNumber(responseHeaders.getContentLength());
411
470
 
412
471
  const [onProgress, flush] =
413
472
  (onDownloadProgress &&
@@ -498,23 +557,55 @@ const factory = (env) => {
498
557
  const canceledError = composedSignal.reason;
499
558
  canceledError.config = config;
500
559
  request && (canceledError.request = request);
501
- err !== canceledError && (canceledError.cause = err);
560
+ if (err !== canceledError) {
561
+ // Non-enumerable to match native Error `cause` semantics so loggers
562
+ // don't recurse into circular fetch internals (see #7205).
563
+ Object.defineProperty(canceledError, 'cause', {
564
+ __proto__: null,
565
+ value: err,
566
+ writable: true,
567
+ enumerable: false,
568
+ configurable: true,
569
+ });
570
+ }
502
571
  throw canceledError;
503
572
  }
504
573
 
574
+ // Surface a maxBodyLength violation we raised while the request body was
575
+ // being streamed. Matching by identity (rather than reading
576
+ // `err.cause.isAxiosError`) keeps the error deterministic across runtimes
577
+ // and avoids both prototype-pollution reads and mis-attributing a foreign
578
+ // AxiosError that merely happened to land in `err.cause`.
579
+ if (pendingBodyError) {
580
+ request && !pendingBodyError.request && (pendingBodyError.request = request);
581
+ throw pendingBodyError;
582
+ }
583
+
584
+ // Re-throw AxiosErrors we raised synchronously (data: URL / content-length
585
+ // pre-checks, response size enforcement) without re-wrapping them.
586
+ if (err instanceof AxiosError) {
587
+ request && !err.request && (err.request = request);
588
+ throw err;
589
+ }
590
+
505
591
  if (err && err.name === 'TypeError' && /Load failed|fetch/i.test(err.message)) {
506
- throw Object.assign(
507
- new AxiosError(
508
- 'Network Error',
509
- AxiosError.ERR_NETWORK,
510
- config,
511
- request,
512
- err && err.response
513
- ),
514
- {
515
- cause: err.cause || err,
516
- }
592
+ const networkError = new AxiosError(
593
+ 'Network Error',
594
+ AxiosError.ERR_NETWORK,
595
+ config,
596
+ request,
597
+ err && err.response
517
598
  );
599
+ // Non-enumerable to match native Error `cause` semantics so loggers
600
+ // don't recurse into circular fetch internals (see #7205).
601
+ Object.defineProperty(networkError, 'cause', {
602
+ __proto__: null,
603
+ value: err.cause || err,
604
+ writable: true,
605
+ enumerable: false,
606
+ configurable: true,
607
+ });
608
+ throw networkError;
518
609
  }
519
610
 
520
611
  throw AxiosError.from(err, err && err.code, config, request, err && err.response);