...**/!(*.map|*.min.js)Size
Gzip
Dependencies
Publish
Install
Publish
Install
Size
Gzip
Dependencies
@@ -1,7 +1,3 @@ | |||
| 1 | interface RawAxiosHeaders { | ||
| 2 | [key: string]: axios.AxiosHeaderValue; | ||
| 3 | } | ||
| 4 | |||
| 5 | type MethodsHeaders = Partial< | 1 | type MethodsHeaders = Partial< |
| 6 | { | 2 | { |
| 7 | [Key in axios.Method as Lowercase<Key>]: AxiosHeaders; | 3 | [Key in axios.Method as Lowercase<Key>]: AxiosHeaders; |
@@ -44,7 +40,7 @@ | |||
| 44 | type BrowserProgressEvent = any; | 40 | type BrowserProgressEvent = any; |
| 45 | 41 | ||
| 46 | declare class AxiosHeaders { | 42 | declare class AxiosHeaders { |
| 47 | constructor(headers?: RawAxiosHeaders | AxiosHeaders | string); | 43 | constructor(headers?: axios.RawAxiosHeaders | AxiosHeaders | string); |
| 48 | 44 | ||
| 49 | [key: string]: any; | 45 | [key: string]: any; |
| 50 | 46 | ||
@@ -53,7 +49,7 @@ | |||
| 53 | value?: axios.AxiosHeaderValue, | 49 | value?: axios.AxiosHeaderValue, |
| 54 | rewrite?: boolean | AxiosHeaderMatcher | 50 | rewrite?: boolean | AxiosHeaderMatcher |
| 55 | ): AxiosHeaders; | 51 | ): AxiosHeaders; |
| 56 | set(headers?: RawAxiosHeaders | AxiosHeaders | string, rewrite?: boolean): AxiosHeaders; | 52 | set(headers?: axios.RawAxiosHeaders | AxiosHeaders | string, rewrite?: boolean): AxiosHeaders; |
| 57 | 53 | ||
| 58 | get(headerName: string, parser: RegExp): RegExpExecArray | null; | 54 | get(headerName: string, parser: RegExp): RegExpExecArray | null; |
| 59 | get(headerName: string, matcher?: true | AxiosHeaderParser): axios.AxiosHeaderValue; | 55 | get(headerName: string, matcher?: true | AxiosHeaderParser): axios.AxiosHeaderValue; |
@@ -67,17 +63,17 @@ | |||
| 67 | normalize(format: boolean): AxiosHeaders; | 63 | normalize(format: boolean): AxiosHeaders; |
| 68 | 64 | ||
| 69 | concat( | 65 | concat( |
| 70 | ...targets: Array<AxiosHeaders | RawAxiosHeaders | string | undefined | null> | 66 | ...targets: Array<AxiosHeaders | axios.RawAxiosHeaders | string | undefined | null> |
| 71 | ): AxiosHeaders; | 67 | ): AxiosHeaders; |
| 72 | 68 | ||
| 73 | toJSON(asStrings?: boolean): RawAxiosHeaders; | 69 | toJSON(asStrings?: boolean): axios.RawAxiosHeaders; |
| 74 | 70 | ||
| 75 | static from(thing?: AxiosHeaders | RawAxiosHeaders | string): AxiosHeaders; | 71 | static from(thing?: AxiosHeaders | axios.RawAxiosHeaders | string): AxiosHeaders; |
| 76 | 72 | ||
| 77 | static accessor(header: string | string[]): AxiosHeaders; | 73 | static accessor(header: string | string[]): AxiosHeaders; |
| 78 | 74 | ||
| 79 | static concat( | 75 | static concat( |
| 80 | ...targets: Array<AxiosHeaders | RawAxiosHeaders | string | undefined | null> | 76 | ...targets: Array<AxiosHeaders | axios.RawAxiosHeaders | string | undefined | null> |
| 81 | ): AxiosHeaders; | 77 | ): AxiosHeaders; |
| 82 | 78 | ||
| 83 | setContentType(value: ContentType, rewrite?: boolean | AxiosHeaderMatcher): AxiosHeaders; | 79 | setContentType(value: ContentType, rewrite?: boolean | AxiosHeaderMatcher): AxiosHeaders; |
@@ -162,6 +158,7 @@ | |||
| 162 | static readonly ERR_CANCELED = 'ERR_CANCELED'; | 158 | static readonly ERR_CANCELED = 'ERR_CANCELED'; |
| 163 | static readonly ERR_FORM_DATA_DEPTH_EXCEEDED = 'ERR_FORM_DATA_DEPTH_EXCEEDED'; | 159 | static readonly ERR_FORM_DATA_DEPTH_EXCEEDED = 'ERR_FORM_DATA_DEPTH_EXCEEDED'; |
| 164 | static readonly ECONNABORTED = 'ECONNABORTED'; | 160 | static readonly ECONNABORTED = 'ECONNABORTED'; |
| 161 | static readonly ECONNREFUSED = 'ECONNREFUSED'; | ||
| 165 | static readonly ETIMEDOUT = 'ETIMEDOUT'; | 162 | static readonly ETIMEDOUT = 'ETIMEDOUT'; |
| 166 | } | 163 | } |
| 167 | 164 | ||
@@ -224,6 +221,11 @@ | |||
| 224 | data?: D, | 221 | data?: D, |
| 225 | config?: axios.AxiosRequestConfig<D> | 222 | config?: axios.AxiosRequestConfig<D> |
| 226 | ): Promise<R>; | 223 | ): Promise<R>; |
| 224 | query<T = any, R = axios.AxiosResponse<T>, D = any>( | ||
| 225 | url: string, | ||
| 226 | data?: D, | ||
| 227 | config?: axios.AxiosRequestConfig<D> | ||
| 228 | ): Promise<R>; | ||
| 227 | } | 229 | } |
| 228 | 230 | ||
| 229 | declare enum HttpStatusCode { | 231 | declare enum HttpStatusCode { |
@@ -297,6 +299,10 @@ | |||
| 297 | declare namespace axios { | 299 | declare namespace axios { |
| 298 | type AxiosError<T = unknown, D = any> = InternalAxiosError<T, D>; | 300 | type AxiosError<T = unknown, D = any> = InternalAxiosError<T, D>; |
| 299 | 301 | ||
| 302 | interface RawAxiosHeaders { | ||
| 303 | [key: string]: AxiosHeaderValue; | ||
| 304 | } | ||
| 305 | |||
| 300 | type RawAxiosRequestHeaders = Partial< | 306 | type RawAxiosRequestHeaders = Partial< |
| 301 | RawAxiosHeaders & { | 307 | RawAxiosHeaders & { |
| 302 | [Key in CommonRequestHeadersList]: AxiosHeaderValue; | 308 | [Key in CommonRequestHeadersList]: AxiosHeaderValue; |
@@ -358,7 +364,8 @@ | |||
| 358 | | 'PATCH' | 364 | | 'PATCH' |
| 359 | | 'PURGE' | 365 | | 'PURGE' |
| 360 | | 'LINK' | 366 | | 'LINK' |
| 361 | | 'UNLINK'; | 367 | | 'UNLINK' |
| 368 | | 'QUERY'; | ||
| 362 | 369 | ||
| 363 | type Method = (UppercaseMethod | Lowercase<UppercaseMethod>) & {}; | 370 | type Method = (UppercaseMethod | Lowercase<UppercaseMethod>) & {}; |
| 364 | 371 | ||
@@ -494,7 +501,8 @@ | |||
| 494 | maxRate?: number | [MaxUploadRate, MaxDownloadRate]; | 501 | maxRate?: number | [MaxUploadRate, MaxDownloadRate]; |
| 495 | beforeRedirect?: ( | 502 | beforeRedirect?: ( |
| 496 | options: Record<string, any>, | 503 | options: Record<string, any>, |
| 497 | responseDetails: { headers: Record<string, string>; statusCode: HttpStatusCode } | 504 | responseDetails: { headers: Record<string, string>; statusCode: HttpStatusCode }, |
| 505 | requestDetails: { headers: Record<string, string>; url: string; method: string }, | ||
| 498 | ) => void; | 506 | ) => void; |
| 499 | socketPath?: string | null; | 507 | socketPath?: string | null; |
| 500 | allowedSocketPaths?: string | string[] | null; | 508 | allowedSocketPaths?: string | string[] | null; |
@@ -502,7 +510,7 @@ | |||
| 502 | httpAgent?: any; | 510 | httpAgent?: any; |
| 503 | httpsAgent?: any; | 511 | httpsAgent?: any; |
| 504 | proxy?: AxiosProxyConfig | false; | 512 | proxy?: AxiosProxyConfig | false; |
| 505 | cancelToken?: CancelToken; | 513 | cancelToken?: CancelToken | undefined; |
| 506 | decompress?: boolean; | 514 | decompress?: boolean; |
| 507 | transitional?: TransitionalOptions; | 515 | transitional?: TransitionalOptions; |
| 508 | signal?: GenericAbortSignal; | 516 | signal?: GenericAbortSignal; |
@@ -536,6 +544,7 @@ | |||
| 536 | | LookupAddress | 544 | | LookupAddress |
| 537 | >); | 545 | >); |
| 538 | withXSRFToken?: boolean | ((config: InternalAxiosRequestConfig) => boolean | undefined); | 546 | withXSRFToken?: boolean | ((config: InternalAxiosRequestConfig) => boolean | undefined); |
| 547 | parseReviver?: (this: any, key: string, value: any, context?: { source: string }) => any; | ||
| 539 | fetchOptions?: | 548 | fetchOptions?: |
| 540 | | Omit<RequestInit, 'body' | 'headers' | 'method' | 'signal'> | 549 | | Omit<RequestInit, 'body' | 'headers' | 'method' | 'signal'> |
| 541 | | Record<string, any>; | 550 | | Record<string, any>; |
@@ -543,6 +552,8 @@ | |||
| 543 | http2Options?: Record<string, any> & { | 552 | http2Options?: Record<string, any> & { |
| 544 | sessionTimeout?: number; | 553 | sessionTimeout?: number; |
| 545 | }; | 554 | }; |
| 555 | formDataHeaderPolicy?: 'legacy' | 'content-only'; | ||
| 556 | redact?: string[]; | ||
| 546 | } | 557 | } |
| 547 | 558 | ||
| 548 | // Alias | 559 | // Alias |
@@ -564,6 +575,7 @@ | |||
| 564 | purge?: RawAxiosRequestHeaders; | 575 | purge?: RawAxiosRequestHeaders; |
| 565 | link?: RawAxiosRequestHeaders; | 576 | link?: RawAxiosRequestHeaders; |
| 566 | unlink?: RawAxiosRequestHeaders; | 577 | unlink?: RawAxiosRequestHeaders; |
| 578 | query?: RawAxiosRequestHeaders; | ||
| 567 | } | 579 | } |
| 568 | 580 | ||
| 569 | interface AxiosDefaults<D = any> extends Omit<AxiosRequestConfig<D>, 'headers'> { | 581 | interface AxiosDefaults<D = any> extends Omit<AxiosRequestConfig<D>, 'headers'> { |
@@ -25,11 +25,13 @@ | |||
| 25 | utils.forEach(knownAdapters, (fn, value) => { | 25 | utils.forEach(knownAdapters, (fn, value) => { |
| 26 | if (fn) { | 26 | if (fn) { |
| 27 | try { | 27 | try { |
| 28 | Object.defineProperty(fn, 'name', { value }); | 28 | // Null-proto descriptors so a polluted Object.prototype.get cannot turn |
| 29 | // these data descriptors into accessor descriptors on the way in. | ||
| 30 | Object.defineProperty(fn, 'name', { __proto__: null, value }); | ||
| 29 | } catch (e) { | 31 | } catch (e) { |
| 30 | // eslint-disable-next-line no-empty | 32 | // eslint-disable-next-line no-empty |
| 31 | } | 33 | } |
| 32 | Object.defineProperty(fn, 'adapterName', { value }); | 34 | Object.defineProperty(fn, 'adapterName', { __proto__: null, value }); |
| 33 | } | 35 | } |
| 34 | }); | 36 | }); |
| 35 | 37 | ||
@@ -148,7 +148,7 @@ | |||
| 148 | let contextHeaders = headers && utils.merge(headers.common, headers[config.method]); | 148 | let contextHeaders = headers && utils.merge(headers.common, headers[config.method]); |
| 149 | 149 | ||
| 150 | headers && | 150 | headers && |
| 151 | utils.forEach(['delete', 'get', 'head', 'post', 'put', 'patch', 'common'], (method) => { | 151 | utils.forEach(['delete', 'get', 'head', 'post', 'put', 'patch', 'query', 'common'], (method) => { |
| 152 | delete headers[method]; | 152 | delete headers[method]; |
| 153 | }); | 153 | }); |
| 154 | 154 | ||
@@ -251,7 +251,7 @@ | |||
| 251 | }; | 251 | }; |
| 252 | }); | 252 | }); |
| 253 | 253 | ||
| 254 | utils.forEach(['post', 'put', 'patch'], function forEachMethodWithData(method) { | 254 | utils.forEach(['post', 'put', 'patch', 'query'], function forEachMethodWithData(method) { |
| 255 | function generateHTTPMethod(isForm) { | 255 | function generateHTTPMethod(isForm) { |
| 256 | return function httpMethod(url, data, config) { | 256 | return function httpMethod(url, data, config) { |
| 257 | return this.request( | 257 | return this.request( |
@@ -271,7 +271,11 @@ | |||
| 271 | 271 | ||
| 272 | Axios.prototype[method] = generateHTTPMethod(); | 272 | Axios.prototype[method] = generateHTTPMethod(); |
| 273 | 273 | ||
| 274 | Axios.prototype[method + 'Form'] = generateHTTPMethod(true); | 274 | // QUERY is a safe/idempotent read method; multipart form bodies don't fit |
| 275 | // its semantics, so no queryForm shorthand is generated. | ||
| 276 | if (method !== 'query') { | ||
| 277 | Axios.prototype[method + 'Form'] = generateHTTPMethod(true); | ||
| 278 | } | ||
| 275 | }); | 279 | }); |
| 276 | 280 | ||
| 277 | export default Axios; | 281 | export default Axios; |
@@ -1,7 +1,77 @@ | |||
| 1 | 'use strict'; | 1 | 'use strict'; |
| 2 | 2 | ||
| 3 | import utils from '../utils.js'; | 3 | import utils from '../utils.js'; |
| 4 | import AxiosHeaders from './AxiosHeaders.js'; | ||
| 4 | 5 | ||
| 6 | const REDACTED = '[REDACTED ****]'; | ||
| 7 | |||
| 8 | function hasOwnOrPrototypeToJSON(source) { | ||
| 9 | if (utils.hasOwnProp(source, 'toJSON')) { | ||
| 10 | return true; | ||
| 11 | } | ||
| 12 | |||
| 13 | let prototype = Object.getPrototypeOf(source); | ||
| 14 | |||
| 15 | while (prototype && prototype !== Object.prototype) { | ||
| 16 | if (utils.hasOwnProp(prototype, 'toJSON')) { | ||
| 17 | return true; | ||
| 18 | } | ||
| 19 | |||
| 20 | prototype = Object.getPrototypeOf(prototype); | ||
| 21 | } | ||
| 22 | |||
| 23 | return false; | ||
| 24 | } | ||
| 25 | |||
| 26 | // Build a plain-object snapshot of `config` and replace the value of any key | ||
| 27 | // (case-insensitive) listed in `redactKeys` with REDACTED. Walks through arrays | ||
| 28 | // and AxiosHeaders, and short-circuits on circular references. | ||
| 29 | function redactConfig(config, redactKeys) { | ||
| 30 | const lowerKeys = new Set(redactKeys.map((k) => String(k).toLowerCase())); | ||
| 31 | const seen = []; | ||
| 32 | |||
| 33 | const visit = (source) => { | ||
| 34 | if (source === null || typeof source !== 'object') return source; | ||
| 35 | if (utils.isBuffer(source)) return source; | ||
| 36 | if (seen.indexOf(source) !== -1) return undefined; | ||
| 37 | |||
| 38 | if (source instanceof AxiosHeaders) { | ||
| 39 | source = source.toJSON(); | ||
| 40 | } | ||
| 41 | |||
| 42 | seen.push(source); | ||
| 43 | |||
| 44 | let result; | ||
| 45 | if (utils.isArray(source)) { | ||
| 46 | result = []; | ||
| 47 | source.forEach((v, i) => { | ||
| 48 | const reducedValue = visit(v); | ||
| 49 | if (!utils.isUndefined(reducedValue)) { | ||
| 50 | result[i] = reducedValue; | ||
| 51 | } | ||
| 52 | }); | ||
| 53 | } else { | ||
| 54 | if (!utils.isPlainObject(source) && hasOwnOrPrototypeToJSON(source)) { | ||
| 55 | seen.pop(); | ||
| 56 | return source; | ||
| 57 | } | ||
| 58 | |||
| 59 | result = Object.create(null); | ||
| 60 | for (const [key, value] of Object.entries(source)) { | ||
| 61 | const reducedValue = lowerKeys.has(key.toLowerCase()) ? REDACTED : visit(value); | ||
| 62 | if (!utils.isUndefined(reducedValue)) { | ||
| 63 | result[key] = reducedValue; | ||
| 64 | } | ||
| 65 | } | ||
| 66 | } | ||
| 67 | |||
| 68 | seen.pop(); | ||
| 69 | return result; | ||
| 70 | }; | ||
| 71 | |||
| 72 | return visit(config); | ||
| 73 | } | ||
| 74 | |||
| 5 | class AxiosError extends Error { | 75 | class AxiosError extends Error { |
| 6 | static from(error, code, config, request, response, customProps) { | 76 | static from(error, code, config, request, response, customProps) { |
| 7 | const axiosError = new AxiosError(error.message, code || error.code, config, request, response); | 77 | const axiosError = new AxiosError(error.message, code || error.code, config, request, response); |
@@ -35,6 +105,9 @@ | |||
| 35 | // The native Error constructor sets message as non-enumerable, | 105 | // The native Error constructor sets message as non-enumerable, |
| 36 | // but axios < v1.13.3 had it as enumerable | 106 | // but axios < v1.13.3 had it as enumerable |
| 37 | Object.defineProperty(this, 'message', { | 107 | Object.defineProperty(this, 'message', { |
| 108 | // Null-proto descriptor so a polluted Object.prototype.get cannot turn | ||
| 109 | // this data descriptor into an accessor descriptor on the way in. | ||
| 110 | __proto__: null, | ||
| 38 | value: message, | 111 | value: message, |
| 39 | enumerable: true, | 112 | enumerable: true, |
| 40 | writable: true, | 113 | writable: true, |
@@ -53,6 +126,17 @@ | |||
| 53 | } | 126 | } |
| 54 | 127 | ||
| 55 | toJSON() { | 128 | toJSON() { |
| 129 | // Opt-in redaction: when the request config carries a `redact` array, the | ||
| 130 | // value of any matching key (case-insensitive, at any depth) is replaced | ||
| 131 | // with REDACTED in the serialized snapshot. Undefined or empty leaves the | ||
| 132 | // existing serialization behavior unchanged. | ||
| 133 | const config = this.config; | ||
| 134 | const redactKeys = config && utils.hasOwnProp(config, 'redact') ? config.redact : undefined; | ||
| 135 | const serializedConfig = | ||
| 136 | utils.isArray(redactKeys) && redactKeys.length > 0 | ||
| 137 | ? redactConfig(config, redactKeys) | ||
| 138 | : utils.toJSONObject(config); | ||
| 139 | |||
| 56 | return { | 140 | return { |
| 57 | // Standard | 141 | // Standard |
| 58 | message: this.message, | 142 | message: this.message, |
@@ -66,7 +150,7 @@ | |||
| 66 | columnNumber: this.columnNumber, | 150 | columnNumber: this.columnNumber, |
| 67 | stack: this.stack, | 151 | stack: this.stack, |
| 68 | // Axios | 152 | // Axios |
| 69 | config: utils.toJSONObject(this.config), | 153 | config: serializedConfig, |
| 70 | code: this.code, | 154 | code: this.code, |
| 71 | status: this.status, | 155 | status: this.status, |
| 72 | }; | 156 | }; |
@@ -78,6 +162,7 @@ | |||
| 78 | AxiosError.ERR_BAD_OPTION = 'ERR_BAD_OPTION'; | 162 | AxiosError.ERR_BAD_OPTION = 'ERR_BAD_OPTION'; |
| 79 | AxiosError.ECONNABORTED = 'ECONNABORTED'; | 163 | AxiosError.ECONNABORTED = 'ECONNABORTED'; |
| 80 | AxiosError.ETIMEDOUT = 'ETIMEDOUT'; | 164 | AxiosError.ETIMEDOUT = 'ETIMEDOUT'; |
| 165 | AxiosError.ECONNREFUSED = 'ECONNREFUSED'; | ||
| 81 | AxiosError.ERR_NETWORK = 'ERR_NETWORK'; | 166 | AxiosError.ERR_NETWORK = 'ERR_NETWORK'; |
| 82 | AxiosError.ERR_FR_TOO_MANY_REDIRECTS = 'ERR_FR_TOO_MANY_REDIRECTS'; | 167 | AxiosError.ERR_FR_TOO_MANY_REDIRECTS = 'ERR_FR_TOO_MANY_REDIRECTS'; |
| 83 | AxiosError.ERR_DEPRECATED = 'ERR_DEPRECATED'; | 168 | AxiosError.ERR_DEPRECATED = 'ERR_DEPRECATED'; |
@@ -98,6 +98,9 @@ | |||
| 98 | 98 | ||
| 99 | ['get', 'set', 'has'].forEach((methodName) => { | 99 | ['get', 'set', 'has'].forEach((methodName) => { |
| 100 | Object.defineProperty(obj, methodName + accessorName, { | 100 | Object.defineProperty(obj, methodName + accessorName, { |
| 101 | // Null-proto descriptor so a polluted Object.prototype.get cannot turn | ||
| 102 | // this data descriptor into an accessor descriptor on the way in. | ||
| 103 | __proto__: null, | ||
| 101 | value: function (arg1, arg2, arg3) { | 104 | value: function (arg1, arg2, arg3) { |
| 102 | return this[methodName].call(this, header, arg1, arg2, arg3); | 105 | return this[methodName].call(this, header, arg1, arg2, arg3); |
| 103 | }, | 106 | }, |
@@ -11,7 +11,7 @@ | |||
| 11 | * | 11 | * |
| 12 | * @returns {string} The encoded value. | 12 | * @returns {string} The encoded value. |
| 13 | */ | 13 | */ |
| 14 | function encode(val) { | 14 | export function encode(val) { |
| 15 | return encodeURIComponent(val) | 15 | return encodeURIComponent(val) |
| 16 | .replace(/%3A/gi, ':') | 16 | .replace(/%3A/gi, ':') |
| 17 | .replace(/%24/g, '$') | 17 | .replace(/%24/g, '$') |
@@ -30,8 +30,20 @@ | |||
| 30 | 30 | ||
| 31 | read(name) { | 31 | read(name) { |
| 32 | if (typeof document === 'undefined') return null; | 32 | if (typeof document === 'undefined') return null; |
| 33 | const match = document.cookie.match(new RegExp('(?:^|; )' + name + '=([^;]*)')); | ||
| 34 | return match ? decodeURIComponent(match[1]) : null; | 33 | // Match name=value by splitting on the semicolon separator instead of building a |
| 34 | // RegExp from `name` — interpolating an unescaped string into a RegExp would let | ||
| 35 | // metacharacters (e.g. `.+?` in an attacker-influenced cookie name) cause ReDoS or | ||
| 36 | // match the wrong cookie. Browsers may serialize cookie pairs as either ";" or | ||
| 37 | // "; ", so ignore optional whitespace before each cookie name. | ||
| 38 | const cookies = document.cookie.split(';'); | ||
| 39 | for (let i = 0; i < cookies.length; i++) { | ||
| 40 | const cookie = cookies[i].replace(/^\s+/, ''); | ||
| 41 | const eq = cookie.indexOf('='); | ||
| 42 | if (eq !== -1 && cookie.slice(0, eq) === name) { | ||
| 43 | return decodeURIComponent(cookie.slice(eq + 1)); | ||
| 44 | } | ||
| 45 | } | ||
| 46 | return null; | ||
| 35 | }, | 47 | }, |
| 36 | 48 | ||
| 37 | remove(name) { | 49 | remove(name) { |
@@ -49,8 +49,15 @@ | |||
| 49 | function onAdapterResolution(response) { | 49 | function onAdapterResolution(response) { |
| 50 | throwIfCancellationRequested(config); | 50 | throwIfCancellationRequested(config); |
| 51 | 51 | ||
| 52 | // Transform response data | ||
| 53 | response.data = transformData.call(config, config.transformResponse, response); | 52 | // Expose the current response on config so that transformResponse can |
| 53 | // attach it to any AxiosError it throws (e.g. on JSON parse failure). | ||
| 54 | // We clean it up afterwards to avoid polluting the config object. | ||
| 55 | config.response = response; | ||
| 56 | try { | ||
| 57 | response.data = transformData.call(config, config.transformResponse, response); | ||
| 58 | } finally { | ||
| 59 | delete config.response; | ||
| 60 | } | ||
| 54 | 61 | ||
| 55 | response.headers = AxiosHeaders.from(response.headers); | 62 | response.headers = AxiosHeaders.from(response.headers); |
| 56 | 63 | ||
@@ -62,11 +69,16 @@ | |||
| 62 | 69 | ||
| 63 | // Transform response data | 70 | // Transform response data |
| 64 | if (reason && reason.response) { | 71 | if (reason && reason.response) { |
| 65 | reason.response.data = transformData.call( | ||
| 66 | config, | ||
| 67 | config.transformResponse, | ||
| 68 | reason.response | ||
| 69 | ); | 72 | config.response = reason.response; |
| 73 | try { | ||
| 74 | reason.response.data = transformData.call( | ||
| 75 | config, | ||
| 76 | config.transformResponse, | ||
| 77 | reason.response | ||
| 78 | ); | ||
| 79 | } finally { | ||
| 80 | delete config.response; | ||
| 81 | } | ||
| 70 | reason.response.headers = AxiosHeaders.from(reason.response.headers); | 82 | reason.response.headers = AxiosHeaders.from(reason.response.headers); |
| 71 | } | 83 | } |
| 72 | } | 84 | } |
@@ -69,5 +69,32 @@ | |||
| 69 | return bytes > 0 ? bytes : 0; | 69 | return bytes > 0 ? bytes : 0; |
| 70 | } | 70 | } |
| 71 | 71 | ||
| 72 | return Buffer.byteLength(body, 'utf8'); | 72 | if (typeof Buffer !== 'undefined' && typeof Buffer.byteLength === 'function') { |
| 73 | return Buffer.byteLength(body, 'utf8'); | ||
| 74 | } | ||
| 75 | |||
| 76 | // Compute UTF-8 byte length directly from UTF-16 code units without allocating | ||
| 77 | // a byte buffer (TextEncoder.encode would defeat the DoS guard on large bodies). | ||
| 78 | // Using body.length here would undercount non-ASCII (e.g. '€' is 1 code unit | ||
| 79 | // but 3 UTF-8 bytes). | ||
| 80 | let bytes = 0; | ||
| 81 | for (let i = 0, len = body.length; i < len; i++) { | ||
| 82 | const c = body.charCodeAt(i); | ||
| 83 | if (c < 0x80) { | ||
| 84 | bytes += 1; | ||
| 85 | } else if (c < 0x800) { | ||
| 86 | bytes += 2; | ||
| 87 | } else if (c >= 0xd800 && c <= 0xdbff && i + 1 < len) { | ||
| 88 | const next = body.charCodeAt(i + 1); | ||
| 89 | if (next >= 0xdc00 && next <= 0xdfff) { | ||
| 90 | bytes += 4; | ||
| 91 | i++; | ||
| 92 | } else { | ||
| 93 | bytes += 3; | ||
| 94 | } | ||
| 95 | } else { | ||
| 96 | bytes += 3; | ||
| 97 | } | ||
| 98 | } | ||
| 99 | return bytes; | ||
| 73 | } | 100 | } |
@@ -77,7 +77,7 @@ | |||
| 77 | } | 77 | } |
| 78 | 78 | ||
| 79 | if (boundary.length < 1 || boundary.length > 70) { | 79 | if (boundary.length < 1 || boundary.length > 70) { |
| 80 | throw Error('boundary must be 10-70 characters long'); | 80 | throw Error('boundary must be 1-70 characters long'); |
| 81 | } | 81 | } |
| 82 | 82 | ||
| 83 | const boundaryBytes = textEncoder.encode('--' + boundary + CRLF); | 83 | const boundaryBytes = textEncoder.encode('--' + boundary + CRLF); |
@@ -170,7 +170,7 @@ | |||
| 170 | }, | 170 | }, |
| 171 | }; | 171 | }; |
| 172 | 172 | ||
| 173 | utils.forEach(['delete', 'get', 'head', 'post', 'put', 'patch'], (method) => { | 173 | utils.forEach(['delete', 'get', 'head', 'post', 'put', 'patch', 'query'], (method) => { |
| 174 | defaults.headers[method] = {}; | 174 | defaults.headers[method] = {}; |
| 175 | }); | 175 | }); |
| 176 | 176 | ||
@@ -19,11 +19,14 @@ | |||
| 19 | config2 = config2 || {}; | 19 | config2 = config2 || {}; |
| 20 | 20 | ||
| 21 | // Use a null-prototype object so that downstream reads such as `config.auth` | 21 | // Use a null-prototype object so that downstream reads such as `config.auth` |
| 22 | // or `config.baseURL` cannot inherit polluted values from Object.prototype | ||
| 23 | // (see GHSA-q8qp-cvcw-x6jj). `hasOwnProperty` is restored as a non-enumerable | ||
| 24 | // own slot to preserve ergonomics for user code that relies on it. | 22 | // or `config.baseURL` cannot inherit polluted values from Object.prototype. |
| 23 | // `hasOwnProperty` is restored as a non-enumerable own slot to preserve | ||
| 24 | // ergonomics for user code that relies on it. | ||
| 25 | const config = Object.create(null); | 25 | const config = Object.create(null); |
| 26 | Object.defineProperty(config, 'hasOwnProperty', { | 26 | Object.defineProperty(config, 'hasOwnProperty', { |
| 27 | // Null-proto descriptor so a polluted Object.prototype.get cannot turn | ||
| 28 | // this data descriptor into an accessor descriptor on the way in. | ||
| 29 | __proto__: null, | ||
| 27 | value: Object.prototype.hasOwnProperty, | 30 | value: Object.prototype.hasOwnProperty, |
| 28 | enumerable: false, | 31 | enumerable: false, |
| 29 | writable: true, | 32 | writable: true, |
@@ -1,6 +1,6 @@ | |||
| 1 | 'use strict'; | 1 | 'use strict'; |
| 2 | 2 | ||
| 3 | export default function parseProtocol(url) { | 3 | export default function parseProtocol(url) { |
| 4 | const match = /^([-+\w]{1,25})(:?\/\/|:)/.exec(url); | 4 | const match = /^([-+\w]{1,25}):(?:\/\/)?/.exec(url); |
| 5 | return (match && match[1]) || ''; | 5 | return (match && match[1]) || ''; |
| 6 | } | 6 | } |
@@ -7,11 +7,39 @@ | |||
| 7 | import AxiosHeaders from '../core/AxiosHeaders.js'; | 7 | import AxiosHeaders from '../core/AxiosHeaders.js'; |
| 8 | import buildURL from './buildURL.js'; | 8 | import buildURL from './buildURL.js'; |
| 9 | 9 | ||
| 10 | const FORM_DATA_CONTENT_HEADERS = ['content-type', 'content-length']; | ||
| 11 | |||
| 12 | function setFormDataHeaders(headers, formHeaders, policy) { | ||
| 13 | if (policy !== 'content-only') { | ||
| 14 | headers.set(formHeaders); | ||
| 15 | return; | ||
| 16 | } | ||
| 17 | |||
| 18 | Object.entries(formHeaders).forEach(([key, val]) => { | ||
| 19 | if (FORM_DATA_CONTENT_HEADERS.includes(key.toLowerCase())) { | ||
| 20 | headers.set(key, val); | ||
| 21 | } | ||
| 22 | }); | ||
| 23 | } | ||
| 24 | |||
| 25 | /** | ||
| 26 | * Encode a UTF-8 string to a Latin-1 byte string for use with btoa(). | ||
| 27 | * This is a modern replacement for the deprecated unescape(encodeURIComponent(str)) pattern. | ||
| 28 | * | ||
| 29 | * @param {string} str The string to encode | ||
| 30 | * | ||
| 31 | * @returns {string} UTF-8 bytes as a Latin-1 string | ||
| 32 | */ | ||
| 33 | const encodeUTF8 = (str) => | ||
| 34 | encodeURIComponent(str).replace(/%([0-9A-F]{2})/gi, (_, hex) => | ||
| 35 | String.fromCharCode(parseInt(hex, 16)) | ||
| 36 | ); | ||
| 37 | |||
| 10 | export default (config) => { | 38 | export default (config) => { |
| 11 | const newConfig = mergeConfig({}, config); | 39 | const newConfig = mergeConfig({}, config); |
| 12 | 40 | ||
| 13 | // Read only own properties to prevent prototype pollution gadgets | 41 | // Read only own properties to prevent prototype pollution gadgets |
| 14 | // (e.g. Object.prototype.baseURL = 'https://evil.com'). See GHSA-q8qp-cvcw-x6jj. | 42 | // (e.g. Object.prototype.baseURL = 'https://evil.com'). |
| 15 | const own = (key) => (utils.hasOwnProp(newConfig, key) ? newConfig[key] : undefined); | 43 | const own = (key) => (utils.hasOwnProp(newConfig, key) ? newConfig[key] : undefined); |
| 16 | 44 | ||
| 17 | const data = own('data'); | 45 | const data = own('data'); |
@@ -37,11 +65,7 @@ | |||
| 37 | headers.set( | 65 | headers.set( |
| 38 | 'Authorization', | 66 | 'Authorization', |
| 39 | 'Basic ' + | 67 | 'Basic ' + |
| 40 | btoa( | ||
| 41 | (auth.username || '') + | ||
| 42 | ':' + | ||
| 43 | (auth.password ? unescape(encodeURIComponent(auth.password)) : '') | ||
| 44 | ) | 68 | btoa((auth.username || '') + ':' + (auth.password ? encodeUTF8(auth.password) : '')) |
| 45 | ); | 69 | ); |
| 46 | } | 70 | } |
| 47 | 71 | ||
@@ -50,14 +74,7 @@ | |||
| 50 | headers.setContentType(undefined); // browser handles it | 74 | headers.setContentType(undefined); // browser handles it |
| 51 | } else if (utils.isFunction(data.getHeaders)) { | 75 | } else if (utils.isFunction(data.getHeaders)) { |
| 52 | // Node.js FormData (like form-data package) | 76 | // Node.js FormData (like form-data package) |
| 53 | const formHeaders = data.getHeaders(); | ||
| 54 | // Only set safe headers to avoid overwriting security headers | ||
| 55 | const allowedHeaders = ['content-type', 'content-length']; | ||
| 56 | Object.entries(formHeaders).forEach(([key, val]) => { | ||
| 57 | if (allowedHeaders.includes(key.toLowerCase())) { | ||
| 58 | headers.set(key, val); | ||
| 59 | } | ||
| 60 | }); | 77 | setFormDataHeaders(headers, data.getHeaders(), own('formDataHeaderPolicy')); |
| 61 | } | 78 | } |
| 62 | } | 79 | } |
| 63 | 80 | ||
@@ -72,10 +89,9 @@ | |||
| 72 | 89 | ||
| 73 | // Strict boolean check — prevents proto-pollution gadgets (e.g. Object.prototype.withXSRFToken = 1) | 90 | // Strict boolean check — prevents proto-pollution gadgets (e.g. Object.prototype.withXSRFToken = 1) |
| 74 | // and misconfigurations (e.g. "false") from short-circuiting the same-origin check and leaking | 91 | // and misconfigurations (e.g. "false") from short-circuiting the same-origin check and leaking |
| 75 | // the XSRF token cross-origin. See GHSA-xx6v-rp6x-q39c. | 92 | // the XSRF token cross-origin. |
| 76 | const shouldSendXSRF = | 93 | const shouldSendXSRF = |
| 77 | withXSRFToken === true || | ||
| 78 | (withXSRFToken == null && isURLSameOrigin(newConfig.url)); | 94 | withXSRFToken === true || (withXSRFToken == null && isURLSameOrigin(newConfig.url)); |
| 79 | 95 | ||
| 80 | if (shouldSendXSRF) { | 96 | if (shouldSendXSRF) { |
| 81 | const xsrfValue = xsrfHeaderName && xsrfCookieName && cookies.read(xsrfCookieName); | 97 | const xsrfValue = xsrfHeaderName && xsrfCookieName && cookies.read(xsrfCookieName); |
@@ -16,16 +16,12 @@ | |||
| 16 | if (!response.status || !validateStatus || validateStatus(response.status)) { | 16 | if (!response.status || !validateStatus || validateStatus(response.status)) { |
| 17 | resolve(response); | 17 | resolve(response); |
| 18 | } else { | 18 | } else { |
| 19 | reject( | ||
| 20 | new AxiosError( | ||
| 21 | 'Request failed with status code ' + response.status, | ||
| 22 | [AxiosError.ERR_BAD_REQUEST, AxiosError.ERR_BAD_RESPONSE][ | ||
| 23 | Math.floor(response.status / 100) - 4 | ||
| 24 | ], | ||
| 25 | response.config, | ||
| 26 | response.request, | ||
| 27 | response | ||
| 28 | ) | ||
| 29 | ); | 19 | reject(new AxiosError( |
| 20 | 'Request failed with status code ' + response.status, | ||
| 21 | response.status >= 400 && response.status < 500 ? AxiosError.ERR_BAD_REQUEST : AxiosError.ERR_BAD_RESPONSE, | ||
| 22 | response.config, | ||
| 23 | response.request, | ||
| 24 | response | ||
| 25 | )); | ||
| 30 | } | 26 | } |
| 31 | } | 27 | } |
@@ -87,6 +87,31 @@ | |||
| 87 | return [entryHost, entryPort]; | 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 | const normalizeNoProxyHost = (hostname) => { | 115 | const normalizeNoProxyHost = (hostname) => { |
| 91 | if (!hostname) { | 116 | if (!hostname) { |
| 92 | return hostname; | 117 | return hostname; |
@@ -96,7 +121,7 @@ | |||
| 96 | hostname = hostname.slice(1, -1); | 121 | hostname = hostname.slice(1, -1); |
| 97 | } | 122 | } |
| 98 | 123 | ||
| 99 | return hostname.replace(/\.+$/, ''); | 124 | return unmapIPv4MappedIPv6(hostname.replace(/\.+$/, '')); |
| 100 | }; | 125 | }; |
| 101 | 126 | ||
| 102 | export default function shouldBypassProxy(location) { | 127 | export default function shouldBypassProxy(location) { |
@@ -192,21 +192,21 @@ | |||
| 192 | * also have a `name` and `type` attribute to specify filename and content type | 192 | * also have a `name` and `type` attribute to specify filename and content type |
| 193 | * | 193 | * |
| 194 | * @see https://github.com/facebook/react-native/blob/26684cf3adf4094eb6c405d345a75bf8c7c0bf88/Libraries/Network/FormData.js#L68-L71 | 194 | * @see https://github.com/facebook/react-native/blob/26684cf3adf4094eb6c405d345a75bf8c7c0bf88/Libraries/Network/FormData.js#L68-L71 |
| 195 | * | 195 | * |
| 196 | * @param {*} value The value to test | 196 | * @param {*} value The value to test |
| 197 | * | 197 | * |
| 198 | * @returns {boolean} True if value is a React Native Blob, otherwise false | 198 | * @returns {boolean} True if value is a React Native Blob, otherwise false |
| 199 | */ | 199 | */ |
| 200 | const isReactNativeBlob = (value) => { | 200 | const isReactNativeBlob = (value) => { |
| 201 | return !!(value && typeof value.uri !== 'undefined'); | 201 | return !!(value && typeof value.uri !== 'undefined'); |
| 202 | } | 202 | }; |
| 203 | 203 | ||
| 204 | /** | 204 | /** |
| 205 | * Determine if environment is React Native | 205 | * Determine if environment is React Native |
| 206 | * ReactNative `FormData` has a non-standard `getParts()` method | 206 | * ReactNative `FormData` has a non-standard `getParts()` method |
| 207 | * | 207 | * |
| 208 | * @param {*} formData The formData to test | 208 | * @param {*} formData The formData to test |
| 209 | * | 209 | * |
| 210 | * @returns {boolean} True if environment is React Native, otherwise false | 210 | * @returns {boolean} True if environment is React Native, otherwise false |
| 211 | */ | 211 | */ |
| 212 | const isReactNative = (formData) => formData && typeof formData.getParts !== 'undefined'; | 212 | const isReactNative = (formData) => formData && typeof formData.getParts !== 'undefined'; |
@@ -225,7 +225,7 @@ | |||
| 225 | * | 225 | * |
| 226 | * @param {*} val The value to test | 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 | const isFileList = kindOfTest('FileList'); | 230 | const isFileList = kindOfTest('FileList'); |
| 231 | 231 | ||
@@ -259,14 +259,16 @@ | |||
| 259 | const isFormData = (thing) => { | 259 | const isFormData = (thing) => { |
| 260 | if (!thing) return false; | 260 | if (!thing) return false; |
| 261 | if (FormDataCtor && thing instanceof FormDataCtor) return true; | 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 | const proto = getPrototypeOf(thing); | 263 | const proto = getPrototypeOf(thing); |
| 264 | if (!proto || proto === Object.prototype) return false; | 264 | if (!proto || proto === Object.prototype) return false; |
| 265 | if (!isFunction(thing.append)) return false; | 265 | if (!isFunction(thing.append)) return false; |
| 266 | const kind = kindOf(thing); | 266 | const kind = kindOf(thing); |
| 267 | return kind === 'formdata' || | 267 | return ( |
| 268 | kind === 'formdata' || | ||
| 268 | // detect form-data instance | 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 @@ | |||
| 401 | * | 403 | * |
| 402 | * @returns {Object} Result of all merge properties | 404 | * @returns {Object} Result of all merge properties |
| 403 | */ | 405 | */ |
| 404 | function merge(/* obj1, obj2, obj3, ... */) { | 406 | function merge(...objs) { |
| 405 | const { caseless, skipUndefined } = (isContextDefined(this) && this) || {}; | 407 | const { caseless, skipUndefined } = (isContextDefined(this) && this) || {}; |
| 406 | const result = {}; | 408 | const result = {}; |
| 407 | const assignValue = (val, key) => { | 409 | const assignValue = (val, key) => { |
@@ -411,8 +413,12 @@ | |||
| 411 | } | 413 | } |
| 412 | 414 | ||
| 413 | const targetKey = (caseless && findKey(result, key)) || key; | 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 | } else if (isPlainObject(val)) { | 422 | } else if (isPlainObject(val)) { |
| 417 | result[targetKey] = merge({}, val); | 423 | result[targetKey] = merge({}, val); |
| 418 | } else if (isArray(val)) { | 424 | } else if (isArray(val)) { |
@@ -422,8 +428,8 @@ | |||
| 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 | return result; | 434 | return result; |
| 429 | } | 435 | } |
@@ -445,6 +451,9 @@ | |||
| 445 | (val, key) => { | 451 | (val, key) => { |
| 446 | if (thisArg && isFunction(val)) { | 452 | if (thisArg && isFunction(val)) { |
| 447 | Object.defineProperty(a, key, { | 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 | value: bind(val, thisArg), | 457 | value: bind(val, thisArg), |
| 449 | writable: true, | 458 | writable: true, |
| 450 | enumerable: true, | 459 | enumerable: true, |
@@ -452,6 +461,7 @@ | |||
| 452 | }); | 461 | }); |
| 453 | } else { | 462 | } else { |
| 454 | Object.defineProperty(a, key, { | 463 | Object.defineProperty(a, key, { |
| 464 | __proto__: null, | ||
| 455 | value: val, | 465 | value: val, |
| 456 | writable: true, | 466 | writable: true, |
| 457 | enumerable: true, | 467 | enumerable: true, |
@@ -490,12 +500,14 @@ | |||
| 490 | const inherits = (constructor, superConstructor, props, descriptors) => { | 500 | const inherits = (constructor, superConstructor, props, descriptors) => { |
| 491 | constructor.prototype = Object.create(superConstructor.prototype, descriptors); | 501 | constructor.prototype = Object.create(superConstructor.prototype, descriptors); |
| 492 | Object.defineProperty(constructor.prototype, 'constructor', { | 502 | Object.defineProperty(constructor.prototype, 'constructor', { |
| 503 | __proto__: null, | ||
| 493 | value: constructor, | 504 | value: constructor, |
| 494 | writable: true, | 505 | writable: true, |
| 495 | enumerable: false, | 506 | enumerable: false, |
| 496 | configurable: true, | 507 | configurable: true, |
| 497 | }); | 508 | }); |
| 498 | Object.defineProperty(constructor, 'super', { | 509 | Object.defineProperty(constructor, 'super', { |
| 510 | __proto__: null, | ||
| 499 | value: superConstructor.prototype, | 511 | value: superConstructor.prototype, |
| 500 | }); | 512 | }); |
| 501 | props && Object.assign(constructor.prototype, props); | 513 | props && Object.assign(constructor.prototype, props); |
@@ -677,7 +689,7 @@ | |||
| 677 | const freezeMethods = (obj) => { | 689 | const freezeMethods = (obj) => { |
| 678 | reduceDescriptors(obj, (descriptor, name) => { | 690 | reduceDescriptors(obj, (descriptor, name) => { |
| 679 | // skip restricted props in strict mode | 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 | return false; | 693 | return false; |
| 682 | } | 694 | } |
| 683 | 695 | ||
@@ -87,7 +87,7 @@ | |||
| 87 | while (i-- > 0) { | 87 | while (i-- > 0) { |
| 88 | const opt = keys[i]; | 88 | const opt = keys[i]; |
| 89 | // Use hasOwnProperty so a polluted Object.prototype.<opt> cannot supply | 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 | const validator = Object.prototype.hasOwnProperty.call(schema, opt) ? schema[opt] : undefined; | 91 | const validator = Object.prototype.hasOwnProperty.call(schema, opt) ? schema[opt] : undefined; |
| 92 | if (validator) { | 92 | if (validator) { |
| 93 | const value = options[opt]; | 93 | const value = options[opt]; |
@@ -91,7 +91,7 @@ | |||
| 91 | // will return status as 0 even though it's a successful request | 91 | // will return status as 0 even though it's a successful request |
| 92 | if ( | 92 | if ( |
| 93 | request.status === 0 && | 93 | request.status === 0 && |
| 94 | !(request.responseURL && request.responseURL.indexOf('file:') === 0) | 94 | !(request.responseURL && request.responseURL.startsWith('file:')) |
| 95 | ) { | 95 | ) { |
| 96 | return; | 96 | return; |
| 97 | } | 97 | } |
@@ -108,6 +108,7 @@ | |||
| 108 | } | 108 | } |
| 109 | 109 | ||
| 110 | reject(new AxiosError('Request aborted', AxiosError.ECONNABORTED, config, request)); | 110 | reject(new AxiosError('Request aborted', AxiosError.ECONNABORTED, config, request)); |
| 111 | done(); | ||
| 111 | 112 | ||
| 112 | // Clean up request | 113 | // Clean up request |
| 113 | request = null; | 114 | request = null; |
@@ -123,6 +124,7 @@ | |||
| 123 | // attach the underlying event for consumers who want details | 124 | // attach the underlying event for consumers who want details |
| 124 | err.event = event || null; | 125 | err.event = event || null; |
| 125 | reject(err); | 126 | reject(err); |
| 127 | done(); | ||
| 126 | request = null; | 128 | request = null; |
| 127 | }; | 129 | }; |
| 128 | 130 | ||
@@ -143,6 +145,7 @@ | |||
| 143 | request | 145 | request |
| 144 | ) | 146 | ) |
| 145 | ); | 147 | ); |
| 148 | done(); | ||
| 146 | 149 | ||
| 147 | // Clean up request | 150 | // Clean up request |
| 148 | request = null; | 151 | request = null; |
@@ -192,6 +195,7 @@ | |||
| 192 | } | 195 | } |
| 193 | reject(!cancel || cancel.type ? new CanceledError(null, config, request) : cancel); | 196 | reject(!cancel || cancel.type ? new CanceledError(null, config, request) : cancel); |
| 194 | request.abort(); | 197 | request.abort(); |
| 198 | done(); | ||
| 195 | request = null; | 199 | request = null; |
| 196 | }; | 200 | }; |
| 197 | 201 | ||
@@ -205,7 +209,7 @@ | |||
| 205 | 209 | ||
| 206 | const protocol = parseProtocol(_config.url); | 210 | const protocol = parseProtocol(_config.url); |
| 207 | 211 | ||
| 208 | if (protocol && platform.protocols.indexOf(protocol) === -1) { | 212 | if (protocol && !platform.protocols.includes(protocol)) { |
| 209 | reject( | 213 | reject( |
| 210 | new AxiosError( | 214 | new AxiosError( |
| 211 | 'Unsupported protocol ' + protocol + ':', | 215 | 'Unsupported protocol ' + protocol + ':', |
@@ -1,6 +1,6 @@ | |||
| 1 | { | 1 | { |
| 2 | "name": "axios", | 2 | "name": "axios", |
| 3 | "version": "1.15.2", | 3 | "version": "1.16.0", |
| 4 | "description": "Promise based HTTP client for the browser and node.js", | 4 | "description": "Promise based HTTP client for the browser and node.js", |
| 5 | "main": "./dist/node/axios.cjs", | 5 | "main": "./dist/node/axios.cjs", |
| 6 | "module": "./index.js", | 6 | "module": "./index.js", |
@@ -82,13 +82,13 @@ | |||
| 82 | "Dmitriy Mozgovoy (https://github.com/DigitalBrainJS)", | 82 | "Dmitriy Mozgovoy (https://github.com/DigitalBrainJS)", |
| 83 | "Nick Uraltsev (https://github.com/nickuraltsev)", | 83 | "Nick Uraltsev (https://github.com/nickuraltsev)", |
| 84 | "Emily Morehouse (https://github.com/emilyemorehouse)", | 84 | "Emily Morehouse (https://github.com/emilyemorehouse)", |
| 85 | "Rubén Norte (https://github.com/rubennorte)", | ||
| 85 | "Justin Beckwith (https://github.com/JustinBeckwith)", | 86 | "Justin Beckwith (https://github.com/JustinBeckwith)", |
| 86 | "Rubén Norte (https://github.com/rubennorte)", | ||
| 87 | "Martti Laine (https://github.com/codeclown)", | 87 | "Martti Laine (https://github.com/codeclown)", |
| 88 | "Xianming Zhong (https://github.com/chinesedfan)", | 88 | "Xianming Zhong (https://github.com/chinesedfan)", |
| 89 | "Willian Agostini (https://github.com/WillianAgostini)", | ||
| 90 | "Shaan Majid (https://github.com/shaanmajid)", | ||
| 89 | "Remco Haszing (https://github.com/remcohaszing)", | 91 | "Remco Haszing (https://github.com/remcohaszing)", |
| 90 | "Shaan Majid (https://github.com/shaanmajid)", | ||
| 91 | "Willian Agostini (https://github.com/WillianAgostini)", | ||
| 92 | "Rikki Gibson (https://github.com/RikkiGibson)" | 92 | "Rikki Gibson (https://github.com/RikkiGibson)" |
| 93 | ], | 93 | ], |
| 94 | "sideEffects": false, | 94 | "sideEffects": false, |
@@ -121,15 +121,15 @@ | |||
| 121 | "prepare": "husky" | 121 | "prepare": "husky" |
| 122 | }, | 122 | }, |
| 123 | "dependencies": { | 123 | "dependencies": { |
| 124 | "follow-redirects": "^1.15.11", | 124 | "follow-redirects": "^1.16.0", |
| 125 | "form-data": "^4.0.5", | 125 | "form-data": "^4.0.5", |
| 126 | "proxy-from-env": "^2.1.0" | 126 | "proxy-from-env": "^2.1.0" |
| 127 | }, | 127 | }, |
| 128 | "devDependencies": { | 128 | "devDependencies": { |
| 129 | "@babel/core": "^7.29.0", | 129 | "@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", | 130 | "@babel/preset-env": "^7.29.2", |
| 131 | "@commitlint/cli": "^20.5.0", | ||
| 132 | "@commitlint/config-conventional": "^20.5.0", | ||
| 133 | "@eslint/js": "^10.0.1", | 133 | "@eslint/js": "^10.0.1", |
| 134 | "@rollup/plugin-alias": "^6.0.0", | 134 | "@rollup/plugin-alias": "^6.0.0", |
| 135 | "@rollup/plugin-babel": "^7.0.0", | 135 | "@rollup/plugin-babel": "^7.0.0", |
@@ -137,40 +137,33 @@ | |||
| 137 | "@rollup/plugin-json": "^6.1.0", | 137 | "@rollup/plugin-json": "^6.1.0", |
| 138 | "@rollup/plugin-node-resolve": "^16.0.3", | 138 | "@rollup/plugin-node-resolve": "^16.0.3", |
| 139 | "@rollup/plugin-terser": "^1.0.0", | 139 | "@rollup/plugin-terser": "^1.0.0", |
| 140 | "@vitest/browser": "^4.1.1", | ||
| 141 | "@vitest/browser-playwright": "^4.1.1", | 140 | "@vitest/browser": "^4.1.5", |
| 141 | "@vitest/browser-playwright": "^4.1.5", | ||
| 142 | "abortcontroller-polyfill": "^1.7.8", | 142 | "abortcontroller-polyfill": "^1.7.8", |
| 143 | "auto-changelog": "^2.5.0", | ||
| 144 | "body-parser": "^2.2.2", | 143 | "body-parser": "^2.2.2", |
| 145 | "chalk": "^5.6.2", | 144 | "chalk": "^5.6.2", |
| 146 | "cross-env": "^10.1.0", | 145 | "cross-env": "^10.1.0", |
| 147 | "dev-null": "^0.1.1", | 146 | "dev-null": "^0.1.1", |
| 148 | "eslint": "^10.1.0", | 147 | "eslint": "^10.2.1", |
| 149 | "express": "^5.2.1", | 148 | "express": "^5.2.1", |
| 150 | "formdata-node": "^6.0.3", | 149 | "formdata-node": "^6.0.3", |
| 151 | "formidable": "^3.2.4", | 150 | "formidable": "^3.5.4", |
| 152 | "fs-extra": "^11.3.4", | 151 | "fs-extra": "^11.3.4", |
| 153 | "get-stream": "^9.0.1", | 152 | "get-stream": "^9.0.1", |
| 154 | "globals": "^17.4.0", | 153 | "globals": "^17.5.0", |
| 155 | "gulp": "^5.0.1", | 154 | "gulp": "^5.0.1", |
| 156 | "handlebars": "^4.7.8", | ||
| 157 | "husky": "^9.1.7", | 155 | "husky": "^9.1.7", |
| 158 | "lint-staged": "^16.4.0", | 156 | "lint-staged": "^16.4.0", |
| 159 | "memoizee": "^0.4.17", | ||
| 160 | "minimist": "^1.2.8", | 157 | "minimist": "^1.2.8", |
| 161 | "multer": "^2.1.1", | 158 | "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", | 159 | "playwright": "^1.59.1", |
| 160 | "prettier": "^3.8.3", | ||
| 161 | "rollup": "^4.60.2", | ||
| 167 | "rollup-plugin-bundle-size": "^1.0.3", | 162 | "rollup-plugin-bundle-size": "^1.0.3", |
| 168 | "selfsigned": "^5.5.0", | 163 | "selfsigned": "^5.5.0", |
| 169 | "stream-throttle": "^0.1.3", | 164 | "stream-throttle": "^0.1.3", |
| 170 | "string-replace-async": "^3.0.2", | ||
| 171 | "tar-stream": "^3.1.8", | ||
| 172 | "typescript": "^5.9.3", | 165 | "typescript": "^5.9.3", |
| 173 | "vitest": "^4.1.1" | 166 | "vitest": "^4.1.5" |
| 174 | }, | 167 | }, |
| 175 | "commitlint": { | 168 | "commitlint": { |
| 176 | "rules": { | 169 | "rules": { |
@@ -1,7 +1,33 @@ | |||
| 1 | # Changelog | 1 | # Changelog |
| 2 | 2 | ||
| 3 | ## v1.15.1 — April 19, 2026 | 3 | ## v1.15.2 - April 21, 2026 |
| 4 | 4 | ||
| 5 | 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. | ||
| 6 | |||
| 7 | ## 🔒 Security Fixes | ||
| 8 | |||
| 9 | - **Prototype Pollution Hardening (HTTP Adapter):** Hardened the Node HTTP adapter and `resolveConfig`/`mergeConfig`/validator paths to read only own properties and use null-prototype config objects, preventing polluted `auth`, `baseURL`, `socketPath`, `beforeRedirect`, and `insecureHTTPParser` from influencing requests. (**#10779**) | ||
| 10 | - **SSRF via `socketPath`:** Rejects non-string `socketPath` values and adds an opt-in `allowedSocketPaths` config option to restrict permitted Unix domain socket paths, returning `AxiosError` `ERR_BAD_OPTION_VALUE` on mismatch. (**#10777**) | ||
| 11 | - **Supply-chain Hardening:** Added `.npmrc` with `ignore-scripts=true`, lockfile lint CI, non-blocking reproducible build diff, scoped CODEOWNERS, expanded `SECURITY.md`/`THREATMODEL.md` with provenance verification (`npm audit signatures`), 60-day resolution policy, and maintainer incident-response runbook. (**#10776**) | ||
| 12 | |||
| 13 | ## 🚀 New Features | ||
| 14 | |||
| 15 | - **`allowedSocketPaths` Config Option:** New request config option (and TypeScript types) to allowlist Unix domain socket paths used by the Node http adapter; backwards compatible when unset. (**#10777**) | ||
| 16 | |||
| 17 | ## 🐛 Bug Fixes | ||
| 18 | |||
| 19 | - **Keep-alive Socket Memory Leak:** Installs a single per-socket `error` listener tracking the active request via `kAxiosSocketListener`/`kAxiosCurrentReq`, eliminating per-request listener accumulation, `MaxListenersExceededWarning`, and linear heap growth under concurrent or long-running keep-alive workloads (fixes #10780). (**#10788**) | ||
| 20 | |||
| 21 | ## 🔧 Maintenance & Chores | ||
| 22 | |||
| 23 | - **Changelog:** Updated `CHANGELOG.md` with v1.15.1 release notes. (**#10781**) | ||
| 24 | |||
| 25 | [Full Changelog](https://github.com/axios/axios/compare/v1.15.1...v1.15.2) | ||
| 26 | |||
| 27 | --- | ||
| 28 | |||
| 29 | ## v1.15.1 - April 19, 2026 | ||
| 30 | |||
| 5 | This release ships a coordinated set of security hardening fixes across headers, body/redirect limits, multipart handling, and XSRF/prototype-pollution vectors, alongside a broad sweep of bug fixes, test migrations, and threat-model documentation updates. | 31 | This release ships a coordinated set of security hardening fixes across headers, body/redirect limits, multipart handling, and XSRF/prototype-pollution vectors, alongside a broad sweep of bug fixes, test migrations, and threat-model documentation updates. |
| 6 | 32 | ||
| 7 | ## 🔒 Security Fixes | 33 | ## 🔒 Security Fixes |
@@ -68,7 +94,7 @@ | |||
| 68 | 94 | ||
| 69 | --- | 95 | --- |
| 70 | 96 | ||
| 71 | ## v1.15.0 — April 7, 2026 | 97 | ## v1.15.0 - April 7, 2026 |
| 72 | 98 | ||
| 73 | This release delivers two critical security patches targeting header injection and SSRF via proxy bypass, adds official runtime support for Deno and Bun, and includes significant CI security hardening. | 99 | This release delivers two critical security patches targeting header injection and SSRF via proxy bypass, adds official runtime support for Deno and Bun, and includes significant CI security hardening. |
| 74 | 100 | ||
@@ -108,7 +134,7 @@ | |||
| 108 | 134 | ||
| 109 | --- | 135 | --- |
| 110 | 136 | ||
| 111 | ## v1.14.0 — March 27, 2026 | 137 | ## v1.14.0 - March 27, 2026 |
| 112 | 138 | ||
| 113 | This release fixes a security vulnerability in the `formidable` dependency, resolves a CommonJS compatibility regression, hardens proxy and HTTP/2 handling, and modernises the build and test toolchain. | 139 | This release fixes a security vulnerability in the `formidable` dependency, resolves a CommonJS compatibility regression, hardens proxy and HTTP/2 handling, and modernises the build and test toolchain. |
| 114 | 140 | ||
@@ -146,7 +172,7 @@ | |||
| 146 | 172 | ||
| 147 | --- | 173 | --- |
| 148 | 174 | ||
| 149 | ## v1.13.6 — February 27, 2026 | 175 | ## v1.13.6 - February 27, 2026 |
| 150 | 176 | ||
| 151 | This release adds React Native Blob support, fixes several enumeration and export regressions, and patches FormData detection for WeChat Mini Program environments. | 177 | This release adds React Native Blob support, fixes several enumeration and export regressions, and patches FormData detection for WeChat Mini Program environments. |
| 152 | 178 | ||
@@ -182,7 +208,7 @@ | |||
| 182 | 208 | ||
| 183 | --- | 209 | --- |
| 184 | 210 | ||
| 185 | ## v1.13.5 — February 8, 2026 | 211 | ## v1.13.5 - February 8, 2026 |
| 186 | 212 | ||
| 187 | This release patches a prototype pollution denial-of-service vulnerability, fixes a missing `status` field regression in `AxiosError`, adds interceptor ordering control, and introduces URL validation for `isAbsoluteURL`. | 213 | This release patches a prototype pollution denial-of-service vulnerability, fixes a missing `status` field regression in `AxiosError`, adds interceptor ordering control, and introduces URL validation for `isAbsoluteURL`. |
| 188 | 214 | ||
@@ -216,7 +242,7 @@ | |||
| 216 | 242 | ||
| 217 | --- | 243 | --- |
| 218 | 244 | ||
| 219 | ## v1.13.4 — January 27, 2026 | 245 | ## v1.13.4 - January 27, 2026 |
| 220 | 246 | ||
| 221 | Patch release fixing regressions introduced in v1.13.3, including TypeScript export compatibility and CI/build stability. | 247 | Patch release fixing regressions introduced in v1.13.3, including TypeScript export compatibility and CI/build stability. |
| 222 | 248 | ||
@@ -3,7 +3,7 @@ | |||
| 3 | 3 | ||
| 4 | export type AxiosHeaderValue = AxiosHeaders | string | string[] | number | boolean | null; | 4 | export type AxiosHeaderValue = AxiosHeaders | string | string[] | number | boolean | null; |
| 5 | 5 | ||
| 6 | interface RawAxiosHeaders { | 6 | export interface RawAxiosHeaders { |
| 7 | [key: string]: AxiosHeaderValue; | 7 | [key: string]: AxiosHeaderValue; |
| 8 | } | 8 | } |
| 9 | 9 | ||
@@ -243,7 +243,8 @@ | |||
| 243 | | 'PATCH' | 243 | | 'PATCH' |
| 244 | | 'PURGE' | 244 | | 'PURGE' |
| 245 | | 'LINK' | 245 | | 'LINK' |
| 246 | | 'UNLINK'; | 246 | | 'UNLINK' |
| 247 | | 'QUERY'; | ||
| 247 | 248 | ||
| 248 | export type Method = (UppercaseMethod | Lowercase<UppercaseMethod>) & {}; | 249 | export type Method = (UppercaseMethod | Lowercase<UppercaseMethod>) & {}; |
| 249 | 250 | ||
@@ -394,7 +395,12 @@ | |||
| 394 | responseDetails: { | 395 | responseDetails: { |
| 395 | headers: Record<string, string>; | 396 | headers: Record<string, string>; |
| 396 | statusCode: HttpStatusCode; | 397 | statusCode: HttpStatusCode; |
| 397 | } | 398 | }, |
| 399 | requestDetails: { | ||
| 400 | headers: Record<string, string>; | ||
| 401 | url: string; | ||
| 402 | method: string; | ||
| 403 | }, | ||
| 398 | ) => void; | 404 | ) => void; |
| 399 | socketPath?: string | null; | 405 | socketPath?: string | null; |
| 400 | allowedSocketPaths?: string | string[] | null; | 406 | allowedSocketPaths?: string | string[] | null; |
@@ -435,12 +441,14 @@ | |||
| 435 | [address: LookupAddressEntry | LookupAddressEntry[], family?: AddressFamily] | LookupAddress | 441 | [address: LookupAddressEntry | LookupAddressEntry[], family?: AddressFamily] | LookupAddress |
| 436 | >); | 442 | >); |
| 437 | withXSRFToken?: boolean | ((config: InternalAxiosRequestConfig) => boolean | undefined); | 443 | withXSRFToken?: boolean | ((config: InternalAxiosRequestConfig) => boolean | undefined); |
| 438 | parseReviver?: (this: any, key: string, value: any) => any; | 444 | parseReviver?: (this: any, key: string, value: any, context?: { source: string }) => any; |
| 439 | fetchOptions?: Omit<RequestInit, 'body' | 'headers' | 'method' | 'signal'> | Record<string, any>; | 445 | fetchOptions?: Omit<RequestInit, 'body' | 'headers' | 'method' | 'signal'> | Record<string, any>; |
| 440 | httpVersion?: 1 | 2; | 446 | httpVersion?: 1 | 2; |
| 441 | http2Options?: Record<string, any> & { | 447 | http2Options?: Record<string, any> & { |
| 442 | sessionTimeout?: number; | 448 | sessionTimeout?: number; |
| 443 | }; | 449 | }; |
| 450 | formDataHeaderPolicy?: 'legacy' | 'content-only'; | ||
| 451 | redact?: string[]; | ||
| 444 | } | 452 | } |
| 445 | 453 | ||
| 446 | // Alias | 454 | // Alias |
@@ -462,6 +470,7 @@ | |||
| 462 | purge?: RawAxiosRequestHeaders; | 470 | purge?: RawAxiosRequestHeaders; |
| 463 | link?: RawAxiosRequestHeaders; | 471 | link?: RawAxiosRequestHeaders; |
| 464 | unlink?: RawAxiosRequestHeaders; | 472 | unlink?: RawAxiosRequestHeaders; |
| 473 | query?: RawAxiosRequestHeaders; | ||
| 465 | } | 474 | } |
| 466 | 475 | ||
| 467 | export interface AxiosDefaults<D = any> extends Omit<AxiosRequestConfig<D>, 'headers'> { | 476 | export interface AxiosDefaults<D = any> extends Omit<AxiosRequestConfig<D>, 'headers'> { |
@@ -519,6 +528,7 @@ | |||
| 519 | static readonly ERR_CANCELED = 'ERR_CANCELED'; | 528 | static readonly ERR_CANCELED = 'ERR_CANCELED'; |
| 520 | static readonly ERR_FORM_DATA_DEPTH_EXCEEDED = 'ERR_FORM_DATA_DEPTH_EXCEEDED'; | 529 | static readonly ERR_FORM_DATA_DEPTH_EXCEEDED = 'ERR_FORM_DATA_DEPTH_EXCEEDED'; |
| 521 | static readonly ECONNABORTED = 'ECONNABORTED'; | 530 | static readonly ECONNABORTED = 'ECONNABORTED'; |
| 531 | static readonly ECONNREFUSED = 'ECONNREFUSED'; | ||
| 522 | static readonly ETIMEDOUT = 'ETIMEDOUT'; | 532 | static readonly ETIMEDOUT = 'ETIMEDOUT'; |
| 523 | } | 533 | } |
| 524 | 534 | ||
@@ -644,6 +654,11 @@ | |||
| 644 | data?: D, | 654 | data?: D, |
| 645 | config?: AxiosRequestConfig<D> | 655 | config?: AxiosRequestConfig<D> |
| 646 | ): Promise<R>; | 656 | ): Promise<R>; |
| 657 | query<T = any, R = AxiosResponse<T>, D = any>( | ||
| 658 | url: string, | ||
| 659 | data?: D, | ||
| 660 | config?: AxiosRequestConfig<D> | ||
| 661 | ): Promise<R>; | ||
| 647 | } | 662 | } |
| 648 | 663 | ||
| 649 | export interface AxiosInstance extends Axios { | 664 | export interface AxiosInstance extends Axios { |
@@ -693,6 +708,8 @@ | |||
| 693 | config2: AxiosRequestConfig<D> | 708 | config2: AxiosRequestConfig<D> |
| 694 | ): AxiosRequestConfig<D>; | 709 | ): AxiosRequestConfig<D>; |
| 695 | 710 | ||
| 711 | export function create(config?: CreateAxiosDefaults): AxiosInstance; | ||
| 712 | |||
| 696 | export interface AxiosStatic extends AxiosInstance { | 713 | export interface AxiosStatic extends AxiosInstance { |
| 697 | Cancel: CancelStatic; | 714 | Cancel: CancelStatic; |
| 698 | CancelToken: CancelTokenStatic; | 715 | CancelToken: CancelTokenStatic; |