...**/!(*.map|*.min.js)Size
Gzip
Dependencies
Publish
Install
Publish
Install
Size
Gzip
Dependencies
@@ -20,7 +20,8 @@ | |||
| 20 | | 'Content-Length' | 20 | | 'Content-Length' |
| 21 | | 'User-Agent' | 21 | | 'User-Agent' |
| 22 | | 'Content-Encoding' | 22 | | 'Content-Encoding' |
| 23 | | 'Authorization'; | 23 | | 'Authorization' |
| 24 | | 'Location'; | ||
| 24 | 25 | ||
| 25 | type ContentType = | 26 | type ContentType = |
| 26 | | axios.AxiosHeaderValue | 27 | | axios.AxiosHeaderValue |
@@ -38,6 +39,8 @@ | |||
| 38 | | 'Cache-Control' | 39 | | 'Cache-Control' |
| 39 | | 'Content-Encoding'; | 40 | | 'Content-Encoding'; |
| 40 | 41 | ||
| 42 | type CommonResponseHeaderKey = CommonResponseHeadersList | Lowercase<CommonResponseHeadersList>; | ||
| 43 | |||
| 41 | type BrowserProgressEvent = any; | 44 | type BrowserProgressEvent = any; |
| 42 | 45 | ||
| 43 | declare class AxiosHeaders { | 46 | declare class AxiosHeaders { |
@@ -157,6 +160,7 @@ | |||
| 157 | static readonly ERR_NOT_SUPPORT = 'ERR_NOT_SUPPORT'; | 160 | static readonly ERR_NOT_SUPPORT = 'ERR_NOT_SUPPORT'; |
| 158 | static readonly ERR_INVALID_URL = 'ERR_INVALID_URL'; | 161 | static readonly ERR_INVALID_URL = 'ERR_INVALID_URL'; |
| 159 | static readonly ERR_CANCELED = 'ERR_CANCELED'; | 162 | static readonly ERR_CANCELED = 'ERR_CANCELED'; |
| 163 | static readonly ERR_FORM_DATA_DEPTH_EXCEEDED = 'ERR_FORM_DATA_DEPTH_EXCEEDED'; | ||
| 160 | static readonly ECONNABORTED = 'ECONNABORTED'; | 164 | static readonly ECONNABORTED = 'ECONNABORTED'; |
| 161 | static readonly ETIMEDOUT = 'ETIMEDOUT'; | 165 | static readonly ETIMEDOUT = 'ETIMEDOUT'; |
| 162 | } | 166 | } |
@@ -306,7 +310,7 @@ | |||
| 306 | type AxiosHeaderValue = AxiosHeaders | string | string[] | number | boolean | null; | 310 | type AxiosHeaderValue = AxiosHeaders | string | string[] | number | boolean | null; |
| 307 | 311 | ||
| 308 | type RawCommonResponseHeaders = { | 312 | type RawCommonResponseHeaders = { |
| 309 | [Key in CommonResponseHeadersList]: AxiosHeaderValue; | 313 | [Key in CommonResponseHeaderKey]: AxiosHeaderValue; |
| 310 | } & { | 314 | } & { |
| 311 | 'set-cookie': string[]; | 315 | 'set-cookie': string[]; |
| 312 | }; | 316 | }; |
@@ -344,56 +348,38 @@ | |||
| 344 | protocol?: string; | 348 | protocol?: string; |
| 345 | } | 349 | } |
| 346 | 350 | ||
| 347 | type Method = | ||
| 348 | | 'get' | 351 | type UppercaseMethod = |
| 349 | | 'GET' | 352 | | 'GET' |
| 350 | | 'delete' | ||
| 351 | | 'DELETE' | 353 | | 'DELETE' |
| 352 | | 'head' | ||
| 353 | | 'HEAD' | 354 | | 'HEAD' |
| 354 | | 'options' | ||
| 355 | | 'OPTIONS' | 355 | | 'OPTIONS' |
| 356 | | 'post' | ||
| 357 | | 'POST' | 356 | | 'POST' |
| 358 | | 'put' | ||
| 359 | | 'PUT' | 357 | | 'PUT' |
| 360 | | 'patch' | ||
| 361 | | 'PATCH' | 358 | | 'PATCH' |
| 362 | | 'purge' | ||
| 363 | | 'PURGE' | 359 | | 'PURGE' |
| 364 | | 'link' | ||
| 365 | | 'LINK' | 360 | | 'LINK' |
| 366 | | 'unlink' | ||
| 367 | | 'UNLINK'; | 361 | | 'UNLINK'; |
| 368 | 362 | ||
| 363 | type Method = (UppercaseMethod | Lowercase<UppercaseMethod>) & {}; | ||
| 364 | |||
| 369 | type ResponseType = 'arraybuffer' | 'blob' | 'document' | 'json' | 'text' | 'stream' | 'formdata'; | 365 | type ResponseType = 'arraybuffer' | 'blob' | 'document' | 'json' | 'text' | 'stream' | 'formdata'; |
| 370 | 366 | ||
| 371 | type responseEncoding = | ||
| 372 | | 'ascii' | 367 | type UppercaseResponseEncoding = |
| 373 | | 'ASCII' | 368 | | 'ASCII' |
| 374 | | 'ansi' | ||
| 375 | | 'ANSI' | 369 | | 'ANSI' |
| 376 | | 'binary' | ||
| 377 | | 'BINARY' | 370 | | 'BINARY' |
| 378 | | 'base64' | ||
| 379 | | 'BASE64' | 371 | | 'BASE64' |
| 380 | | 'base64url' | ||
| 381 | | 'BASE64URL' | 372 | | 'BASE64URL' |
| 382 | | 'hex' | ||
| 383 | | 'HEX' | 373 | | 'HEX' |
| 384 | | 'latin1' | ||
| 385 | | 'LATIN1' | 374 | | 'LATIN1' |
| 386 | | 'ucs-2' | ||
| 387 | | 'UCS-2' | 375 | | 'UCS-2' |
| 388 | | 'ucs2' | ||
| 389 | | 'UCS2' | 376 | | 'UCS2' |
| 390 | | 'utf-8' | ||
| 391 | | 'UTF-8' | 377 | | 'UTF-8' |
| 392 | | 'utf8' | ||
| 393 | | 'UTF8' | 378 | | 'UTF8' |
| 394 | | 'utf16le' | ||
| 395 | | 'UTF16LE'; | 379 | | 'UTF16LE'; |
| 396 | 380 | ||
| 381 | type responseEncoding = (UppercaseResponseEncoding | Lowercase<UppercaseResponseEncoding>) & {}; | ||
| 382 | |||
| 397 | interface TransitionalOptions { | 383 | interface TransitionalOptions { |
| 398 | silentJSONParsing?: boolean; | 384 | silentJSONParsing?: boolean; |
| 399 | forcedJSONParsing?: boolean; | 385 | forcedJSONParsing?: boolean; |
@@ -628,7 +614,7 @@ | |||
| 628 | 614 | ||
| 629 | interface AxiosInterceptorOptions { | 615 | interface AxiosInterceptorOptions { |
| 630 | synchronous?: boolean; | 616 | synchronous?: boolean; |
| 631 | runWhen?: (config: InternalAxiosRequestConfig) => boolean; | 617 | runWhen?: ((config: InternalAxiosRequestConfig) => boolean) | null; |
| 632 | } | 618 | } |
| 633 | 619 | ||
| 634 | type AxiosInterceptorFulfilled<T> = (value: T) => T | Promise<T>; | 620 | type AxiosInterceptorFulfilled<T> = (value: T) => T | Promise<T>; |
@@ -649,7 +635,7 @@ | |||
| 649 | fulfilled: AxiosInterceptorFulfilled<T>; | 635 | fulfilled: AxiosInterceptorFulfilled<T>; |
| 650 | rejected?: AxiosInterceptorRejected; | 636 | rejected?: AxiosInterceptorRejected; |
| 651 | synchronous: boolean; | 637 | synchronous: boolean; |
| 652 | runWhen?: (config: AxiosRequestConfig) => boolean; | 638 | runWhen?: ((config: InternalAxiosRequestConfig) => boolean) | null; |
| 653 | } | 639 | } |
| 654 | 640 | ||
| 655 | interface AxiosInterceptorManager<V> { | 641 | interface AxiosInterceptorManager<V> { |
@@ -17,40 +17,40 @@ | |||
| 17 | return axiosError; | 17 | return axiosError; |
| 18 | } | 18 | } |
| 19 | 19 | ||
| 20 | /** | ||
| 21 | * Create an Error with the specified message, config, error code, request and response. | ||
| 22 | * | ||
| 23 | * @param {string} message The error message. | ||
| 24 | * @param {string} [code] The error code (for example, 'ECONNABORTED'). | ||
| 25 | * @param {Object} [config] The config. | ||
| 26 | * @param {Object} [request] The request. | ||
| 27 | * @param {Object} [response] The response. | ||
| 28 | * | ||
| 29 | * @returns {Error} The created error. | ||
| 30 | */ | ||
| 31 | constructor(message, code, config, request, response) { | ||
| 32 | super(message); | ||
| 33 | |||
| 34 | // Make message enumerable to maintain backward compatibility | ||
| 35 | // The native Error constructor sets message as non-enumerable, | ||
| 36 | // but axios < v1.13.3 had it as enumerable | ||
| 37 | Object.defineProperty(this, 'message', { | ||
| 38 | value: message, | ||
| 39 | enumerable: true, | ||
| 40 | writable: true, | ||
| 41 | configurable: true | ||
| 42 | }); | ||
| 43 | |||
| 44 | this.name = 'AxiosError'; | ||
| 45 | this.isAxiosError = true; | ||
| 46 | code && (this.code = code); | ||
| 47 | config && (this.config = config); | ||
| 48 | request && (this.request = request); | ||
| 49 | if (response) { | ||
| 50 | this.response = response; | ||
| 51 | this.status = response.status; | ||
| 52 | } | 20 | /** |
| 21 | * Create an Error with the specified message, config, error code, request and response. | ||
| 22 | * | ||
| 23 | * @param {string} message The error message. | ||
| 24 | * @param {string} [code] The error code (for example, 'ECONNABORTED'). | ||
| 25 | * @param {Object} [config] The config. | ||
| 26 | * @param {Object} [request] The request. | ||
| 27 | * @param {Object} [response] The response. | ||
| 28 | * | ||
| 29 | * @returns {Error} The created error. | ||
| 30 | */ | ||
| 31 | constructor(message, code, config, request, response) { | ||
| 32 | super(message); | ||
| 33 | |||
| 34 | // Make message enumerable to maintain backward compatibility | ||
| 35 | // The native Error constructor sets message as non-enumerable, | ||
| 36 | // but axios < v1.13.3 had it as enumerable | ||
| 37 | Object.defineProperty(this, 'message', { | ||
| 38 | value: message, | ||
| 39 | enumerable: true, | ||
| 40 | writable: true, | ||
| 41 | configurable: true, | ||
| 42 | }); | ||
| 43 | |||
| 44 | this.name = 'AxiosError'; | ||
| 45 | this.isAxiosError = true; | ||
| 46 | code && (this.code = code); | ||
| 47 | config && (this.config = config); | ||
| 48 | request && (this.request = request); | ||
| 49 | if (response) { | ||
| 50 | this.response = response; | ||
| 51 | this.status = response.status; | ||
| 53 | } | 52 | } |
| 53 | } | ||
| 54 | 54 | ||
| 55 | toJSON() { | 55 | toJSON() { |
| 56 | return { | 56 | return { |
@@ -86,5 +86,6 @@ | |||
| 86 | AxiosError.ERR_CANCELED = 'ERR_CANCELED'; | 86 | AxiosError.ERR_CANCELED = 'ERR_CANCELED'; |
| 87 | AxiosError.ERR_NOT_SUPPORT = 'ERR_NOT_SUPPORT'; | 87 | AxiosError.ERR_NOT_SUPPORT = 'ERR_NOT_SUPPORT'; |
| 88 | AxiosError.ERR_INVALID_URL = 'ERR_INVALID_URL'; | 88 | AxiosError.ERR_INVALID_URL = 'ERR_INVALID_URL'; |
| 89 | AxiosError.ERR_FORM_DATA_DEPTH_EXCEEDED = 'ERR_FORM_DATA_DEPTH_EXCEEDED'; | ||
| 89 | 90 | ||
| 90 | export default AxiosError; | 91 | export default AxiosError; |
@@ -5,49 +5,49 @@ | |||
| 5 | 5 | ||
| 6 | const $internals = Symbol('internals'); | 6 | const $internals = Symbol('internals'); |
| 7 | 7 | ||
| 8 | const isValidHeaderValue = (value) => !/[\r\n]/.test(value); | 8 | const INVALID_HEADER_VALUE_CHARS_RE = /[^\x09\x20-\x7E\x80-\xFF]/g; |
| 9 | 9 | ||
| 10 | function assertValidHeaderValue(value, header) { | ||
| 11 | if (value === false || value == null) { | ||
| 12 | return; | ||
| 13 | } | 10 | function trimSPorHTAB(str) { |
| 11 | let start = 0; | ||
| 12 | let end = str.length; | ||
| 14 | 13 | ||
| 15 | if (utils.isArray(value)) { | ||
| 16 | value.forEach((v) => assertValidHeaderValue(v, header)); | ||
| 17 | return; | ||
| 18 | } | 14 | while (start < end) { |
| 15 | const code = str.charCodeAt(start); | ||
| 19 | 16 | ||
| 20 | if (!isValidHeaderValue(String(value))) { | ||
| 21 | throw new Error(`Invalid character in header content ["${header}"]`); | 17 | if (code !== 0x09 && code !== 0x20) { |
| 18 | break; | ||
| 19 | } | ||
| 20 | |||
| 21 | start += 1; | ||
| 22 | } | 22 | } |
| 23 | } | ||
| 24 | 23 | ||
| 25 | function normalizeHeader(header) { | ||
| 26 | return header && String(header).trim().toLowerCase(); | ||
| 27 | } | 24 | while (end > start) { |
| 25 | const code = str.charCodeAt(end - 1); | ||
| 28 | 26 | ||
| 29 | function stripTrailingCRLF(str) { | ||
| 30 | let end = str.length; | ||
| 31 | |||
| 32 | while (end > 0) { | ||
| 33 | const charCode = str.charCodeAt(end - 1); | ||
| 34 | |||
| 35 | if (charCode !== 10 && charCode !== 13) { | 27 | if (code !== 0x09 && code !== 0x20) { |
| 36 | break; | 28 | break; |
| 37 | } | 29 | } |
| 38 | 30 | ||
| 39 | end -= 1; | 31 | end -= 1; |
| 40 | } | 32 | } |
| 41 | 33 | ||
| 42 | return end === str.length ? str : str.slice(0, end); | 34 | return start === 0 && end === str.length ? str : str.slice(start, end); |
| 43 | } | 35 | } |
| 44 | 36 | ||
| 37 | function normalizeHeader(header) { | ||
| 38 | return header && String(header).trim().toLowerCase(); | ||
| 39 | } | ||
| 40 | |||
| 41 | function sanitizeHeaderValue(str) { | ||
| 42 | return trimSPorHTAB(str.replace(INVALID_HEADER_VALUE_CHARS_RE, '')); | ||
| 43 | } | ||
| 44 | |||
| 45 | function normalizeValue(value) { | 45 | function normalizeValue(value) { |
| 46 | if (value === false || value == null) { | 46 | if (value === false || value == null) { |
| 47 | return value; | 47 | return value; |
| 48 | } | 48 | } |
| 49 | 49 | ||
| 50 | return utils.isArray(value) ? value.map(normalizeValue) : stripTrailingCRLF(String(value)); | 50 | return utils.isArray(value) ? value.map(normalizeValue) : sanitizeHeaderValue(String(value)); |
| 51 | } | 51 | } |
| 52 | 52 | ||
| 53 | function parseTokens(str) { | 53 | function parseTokens(str) { |
@@ -129,7 +129,6 @@ | |||
| 129 | _rewrite === true || | 129 | _rewrite === true || |
| 130 | (_rewrite === undefined && self[key] !== false) | 130 | (_rewrite === undefined && self[key] !== false) |
| 131 | ) { | 131 | ) { |
| 132 | assertValidHeaderValue(_value, _header); | ||
| 133 | self[key || _header] = normalizeValue(_value); | 132 | self[key || _header] = normalizeValue(_value); |
| 134 | } | 133 | } |
| 135 | } | 134 | } |
@@ -18,9 +18,8 @@ | |||
| 18 | ')': '%29', | 18 | ')': '%29', |
| 19 | '~': '%7E', | 19 | '~': '%7E', |
| 20 | '%20': '+', | 20 | '%20': '+', |
| 21 | '%00': '\x00', | ||
| 22 | }; | 21 | }; |
| 23 | return encodeURIComponent(str).replace(/[!'()~]|%20|%00/g, function replacer(match) { | 22 | return encodeURIComponent(str).replace(/[!'()~]|%20/g, function replacer(match) { |
| 24 | return charMap[match]; | 23 | return charMap[match]; |
| 25 | }); | 24 | }); |
| 26 | } | 25 | } |
@@ -15,7 +15,7 @@ | |||
| 15 | */ | 15 | */ |
| 16 | export default function buildFullPath(baseURL, requestedURL, allowAbsoluteUrls) { | 16 | export default function buildFullPath(baseURL, requestedURL, allowAbsoluteUrls) { |
| 17 | let isRelativeUrl = !isAbsoluteURL(requestedURL); | 17 | let isRelativeUrl = !isAbsoluteURL(requestedURL); |
| 18 | if (baseURL && (isRelativeUrl || allowAbsoluteUrls == false)) { | 18 | if (baseURL && (isRelativeUrl || allowAbsoluteUrls === false)) { |
| 19 | return combineURLs(baseURL, requestedURL); | 19 | return combineURLs(baseURL, requestedURL); |
| 20 | } | 20 | } |
| 21 | return requestedURL; | 21 | return requestedURL; |
@@ -66,19 +66,21 @@ | |||
| 66 | test(() => { | 66 | test(() => { |
| 67 | let duplexAccessed = false; | 67 | let duplexAccessed = false; |
| 68 | 68 | ||
| 69 | const body = new ReadableStream(); | ||
| 70 | |||
| 71 | const hasContentType = new Request(platform.origin, { | ||
| 72 | body, | 69 | const request = new Request(platform.origin, { |
| 70 | body: new ReadableStream(), | ||
| 73 | method: 'POST', | 71 | method: 'POST', |
| 74 | get duplex() { | 72 | get duplex() { |
| 75 | duplexAccessed = true; | 73 | duplexAccessed = true; |
| 76 | return 'half'; | 74 | return 'half'; |
| 77 | }, | 75 | }, |
| 78 | }).headers.has('Content-Type'); | 76 | }); |
| 79 | 77 | ||
| 80 | body.cancel(); | 78 | const hasContentType = request.headers.has('Content-Type'); |
| 81 | 79 | ||
| 80 | if (request.body != null) { | ||
| 81 | request.body.cancel(); | ||
| 82 | } | ||
| 83 | |||
| 82 | return duplexAccessed && !hasContentType; | 84 | return duplexAccessed && !hasContentType; |
| 83 | }); | 85 | }); |
| 84 | 86 | ||
@@ -221,6 +223,19 @@ | |||
| 221 | // see https://github.com/cloudflare/workerd/issues/902 | 223 | // see https://github.com/cloudflare/workerd/issues/902 |
| 222 | const isCredentialsSupported = isRequestSupported && 'credentials' in Request.prototype; | 224 | const isCredentialsSupported = isRequestSupported && 'credentials' in Request.prototype; |
| 223 | 225 | ||
| 226 | // If data is FormData and Content-Type is multipart/form-data without boundary, | ||
| 227 | // delete it so fetch can set it correctly with the boundary | ||
| 228 | if (utils.isFormData(data)) { | ||
| 229 | const contentType = headers.getContentType(); | ||
| 230 | if ( | ||
| 231 | contentType && | ||
| 232 | /^multipart\/form-data/i.test(contentType) && | ||
| 233 | !/boundary=/i.test(contentType) | ||
| 234 | ) { | ||
| 235 | headers.delete('content-type'); | ||
| 236 | } | ||
| 237 | } | ||
| 238 | |||
| 224 | const resolvedOptions = { | 239 | const resolvedOptions = { |
| 225 | ...fetchOptions, | 240 | ...fetchOptions, |
| 226 | signal: composedSignal, | 241 | signal: composedSignal, |
@@ -58,7 +58,9 @@ | |||
| 58 | 58 | ||
| 59 | if (isLast) { | 59 | if (isLast) { |
| 60 | if (utils.hasOwnProp(target, name)) { | 60 | if (utils.hasOwnProp(target, name)) { |
| 61 | target[name] = [target[name], value]; | 61 | target[name] = utils.isArray(target[name]) |
| 62 | ? target[name].concat(value) | ||
| 63 | : [target[name], value]; | ||
| 62 | } else { | 64 | } else { |
| 63 | target[name] = value; | 65 | target[name] = value; |
| 64 | } | 66 | } |
@@ -24,7 +24,8 @@ | |||
| 24 | if (isStringValue) { | 24 | if (isStringValue) { |
| 25 | value = textEncoder.encode(String(value).replace(/\r?\n|\r\n?/g, CRLF)); | 25 | value = textEncoder.encode(String(value).replace(/\r?\n|\r\n?/g, CRLF)); |
| 26 | } else { | 26 | } else { |
| 27 | headers += `Content-Type: ${value.type || 'application/octet-stream'}${CRLF}`; | 27 | const safeType = String(value.type || 'application/octet-stream').replace(/[\r\n]/g, ''); |
| 28 | headers += `Content-Type: ${safeType}${CRLF}`; | ||
| 28 | } | 29 | } |
| 29 | 30 | ||
| 30 | this.headers = textEncoder.encode(headers + CRLF); | 31 | this.headers = textEncoder.encode(headers + CRLF); |
@@ -8,6 +8,8 @@ | |||
| 8 | import platform from '../platform/index.js'; | 8 | import platform from '../platform/index.js'; |
| 9 | import formDataToJSON from '../helpers/formDataToJSON.js'; | 9 | import formDataToJSON from '../helpers/formDataToJSON.js'; |
| 10 | 10 | ||
| 11 | const own = (obj, key) => (obj != null && utils.hasOwnProp(obj, key) ? obj[key] : undefined); | ||
| 12 | |||
| 11 | /** | 13 | /** |
| 12 | * It takes a string, tries to parse it, and if it fails, it returns the stringified version | 14 | * It takes a string, tries to parse it, and if it fails, it returns the stringified version |
| 13 | * of the input | 15 | * of the input |
@@ -75,20 +77,22 @@ | |||
| 75 | let isFileList; | 77 | let isFileList; |
| 76 | 78 | ||
| 77 | if (isObjectPayload) { | 79 | if (isObjectPayload) { |
| 80 | const formSerializer = own(this, 'formSerializer'); | ||
| 78 | if (contentType.indexOf('application/x-www-form-urlencoded') > -1) { | 81 | if (contentType.indexOf('application/x-www-form-urlencoded') > -1) { |
| 79 | return toURLEncodedForm(data, this.formSerializer).toString(); | 82 | return toURLEncodedForm(data, formSerializer).toString(); |
| 80 | } | 83 | } |
| 81 | 84 | ||
| 82 | if ( | 85 | if ( |
| 83 | (isFileList = utils.isFileList(data)) || | 86 | (isFileList = utils.isFileList(data)) || |
| 84 | contentType.indexOf('multipart/form-data') > -1 | 87 | contentType.indexOf('multipart/form-data') > -1 |
| 85 | ) { | 88 | ) { |
| 86 | const _FormData = this.env && this.env.FormData; | 89 | const env = own(this, 'env'); |
| 90 | const _FormData = env && env.FormData; | ||
| 87 | 91 | ||
| 88 | return toFormData( | 92 | return toFormData( |
| 89 | isFileList ? { 'files[]': data } : data, | 93 | isFileList ? { 'files[]': data } : data, |
| 90 | _FormData && new _FormData(), | 94 | _FormData && new _FormData(), |
| 91 | this.formSerializer | 95 | formSerializer |
| 92 | ); | 96 | ); |
| 93 | } | 97 | } |
| 94 | } | 98 | } |
@@ -104,9 +108,10 @@ | |||
| 104 | 108 | ||
| 105 | transformResponse: [ | 109 | transformResponse: [ |
| 106 | function transformResponse(data) { | 110 | function transformResponse(data) { |
| 107 | const transitional = this.transitional || defaults.transitional; | 111 | const transitional = own(this, 'transitional') || defaults.transitional; |
| 108 | const forcedJSONParsing = transitional && transitional.forcedJSONParsing; | 112 | const forcedJSONParsing = transitional && transitional.forcedJSONParsing; |
| 109 | const JSONRequested = this.responseType === 'json'; | 113 | const responseType = own(this, 'responseType'); |
| 114 | const JSONRequested = responseType === 'json'; | ||
| 110 | 115 | ||
| 111 | if (utils.isResponse(data) || utils.isReadableStream(data)) { | 116 | if (utils.isResponse(data) || utils.isReadableStream(data)) { |
| 112 | return data; | 117 | return data; |
@@ -115,17 +120,17 @@ | |||
| 115 | if ( | 120 | if ( |
| 116 | data && | 121 | data && |
| 117 | utils.isString(data) && | 122 | utils.isString(data) && |
| 118 | ((forcedJSONParsing && !this.responseType) || JSONRequested) | 123 | ((forcedJSONParsing && !responseType) || JSONRequested) |
| 119 | ) { | 124 | ) { |
| 120 | const silentJSONParsing = transitional && transitional.silentJSONParsing; | 125 | const silentJSONParsing = transitional && transitional.silentJSONParsing; |
| 121 | const strictJSONParsing = !silentJSONParsing && JSONRequested; | 126 | const strictJSONParsing = !silentJSONParsing && JSONRequested; |
| 122 | 127 | ||
| 123 | try { | 128 | try { |
| 124 | return JSON.parse(data, this.parseReviver); | 129 | return JSON.parse(data, own(this, 'parseReviver')); |
| 125 | } catch (e) { | 130 | } catch (e) { |
| 126 | if (strictJSONParsing) { | 131 | if (strictJSONParsing) { |
| 127 | if (e.name === 'SyntaxError') { | 132 | if (e.name === 'SyntaxError') { |
| 128 | throw AxiosError.from(e, AxiosError.ERR_BAD_RESPONSE, this, null, this.response); | 133 | throw AxiosError.from(e, AxiosError.ERR_BAD_RESPONSE, this, null, own(this, 'response')); |
| 129 | } | 134 | } |
| 130 | throw e; | 135 | throw e; |
| 131 | } | 136 | } |
@@ -56,9 +56,9 @@ | |||
| 56 | 56 | ||
| 57 | // eslint-disable-next-line consistent-return | 57 | // eslint-disable-next-line consistent-return |
| 58 | function mergeDirectKeys(a, b, prop) { | 58 | function mergeDirectKeys(a, b, prop) { |
| 59 | if (prop in config2) { | 59 | if (utils.hasOwnProp(config2, prop)) { |
| 60 | return getMergedValue(a, b); | 60 | return getMergedValue(a, b); |
| 61 | } else if (prop in config1) { | 61 | } else if (utils.hasOwnProp(config1, prop)) { |
| 62 | return getMergedValue(undefined, a); | 62 | return getMergedValue(undefined, a); |
| 63 | } | 63 | } |
| 64 | } | 64 | } |
@@ -99,7 +99,9 @@ | |||
| 99 | utils.forEach(Object.keys({ ...config1, ...config2 }), function computeConfigValue(prop) { | 99 | utils.forEach(Object.keys({ ...config1, ...config2 }), function computeConfigValue(prop) { |
| 100 | if (prop === '__proto__' || prop === 'constructor' || prop === 'prototype') return; | 100 | if (prop === '__proto__' || prop === 'constructor' || prop === 'prototype') return; |
| 101 | const merge = utils.hasOwnProp(mergeMap, prop) ? mergeMap[prop] : mergeDeepProperties; | 101 | const merge = utils.hasOwnProp(mergeMap, prop) ? mergeMap[prop] : mergeDeepProperties; |
| 102 | const configValue = merge(config1[prop], config2[prop], prop); | 102 | const a = utils.hasOwnProp(config1, prop) ? config1[prop] : undefined; |
| 103 | const b = utils.hasOwnProp(config2, prop) ? config2[prop] : undefined; | ||
| 104 | const configValue = merge(a, b, prop); | ||
| 103 | (utils.isUndefined(configValue) && merge !== mergeDirectKeys) || (config[prop] = configValue); | 105 | (utils.isUndefined(configValue) && merge !== mergeDirectKeys) || (config[prop] = configValue); |
| 104 | }); | 106 | }); |
| 105 | 107 | ||
@@ -7,13 +7,13 @@ | |||
| 7 | const _speedometer = speedometer(50, 250); | 7 | const _speedometer = speedometer(50, 250); |
| 8 | 8 | ||
| 9 | return throttle((e) => { | 9 | return throttle((e) => { |
| 10 | const loaded = e.loaded; | 10 | const rawLoaded = e.loaded; |
| 11 | const total = e.lengthComputable ? e.total : undefined; | 11 | const total = e.lengthComputable ? e.total : undefined; |
| 12 | const progressBytes = loaded - bytesNotified; | 12 | const loaded = total != null ? Math.min(rawLoaded, total) : rawLoaded; |
| 13 | const progressBytes = Math.max(0, loaded - bytesNotified); | ||
| 13 | const rate = _speedometer(progressBytes); | 14 | const rate = _speedometer(progressBytes); |
| 14 | const inRange = loaded <= total; | ||
| 15 | 15 | ||
| 16 | bytesNotified = loaded; | 16 | bytesNotified = Math.max(bytesNotified, loaded); |
| 17 | 17 | ||
| 18 | const data = { | 18 | const data = { |
| 19 | loaded, | 19 | loaded, |
@@ -21,7 +21,7 @@ | |||
| 21 | progress: total ? loaded / total : undefined, | 21 | progress: total ? loaded / total : undefined, |
| 22 | bytes: progressBytes, | 22 | bytes: progressBytes, |
| 23 | rate: rate ? rate : undefined, | 23 | rate: rate ? rate : undefined, |
| 24 | estimated: rate && total && inRange ? (total - loaded) / rate : undefined, | 24 | estimated: rate && total ? (total - loaded) / rate : undefined, |
| 25 | event: e, | 25 | event: e, |
| 26 | lengthComputable: total != null, | 26 | lengthComputable: total != null, |
| 27 | [isDownloadStream ? 'download' : 'upload']: true, | 27 | [isDownloadStream ? 'download' : 'upload']: true, |
@@ -54,10 +54,18 @@ | |||
| 54 | // Specifically not if we're in a web worker, or react-native. | 54 | // Specifically not if we're in a web worker, or react-native. |
| 55 | 55 | ||
| 56 | if (platform.hasStandardBrowserEnv) { | 56 | if (platform.hasStandardBrowserEnv) { |
| 57 | withXSRFToken && utils.isFunction(withXSRFToken) && (withXSRFToken = withXSRFToken(newConfig)); | 57 | if (utils.isFunction(withXSRFToken)) { |
| 58 | withXSRFToken = withXSRFToken(newConfig); | ||
| 59 | } | ||
| 58 | 60 | ||
| 59 | if (withXSRFToken || (withXSRFToken !== false && isURLSameOrigin(newConfig.url))) { | ||
| 60 | // Add xsrf header | 61 | // Strict boolean check — prevents proto-pollution gadgets (e.g. Object.prototype.withXSRFToken = 1) |
| 62 | // and misconfigurations (e.g. "false") from short-circuiting the same-origin check and leaking | ||
| 63 | // the XSRF token cross-origin. See GHSA-xx6v-rp6x-q39c. | ||
| 64 | const shouldSendXSRF = | ||
| 65 | withXSRFToken === true || | ||
| 66 | (withXSRFToken == null && isURLSameOrigin(newConfig.url)); | ||
| 67 | |||
| 68 | if (shouldSendXSRF) { | ||
| 61 | const xsrfValue = xsrfHeaderName && xsrfCookieName && cookies.read(xsrfCookieName); | 69 | const xsrfValue = xsrfHeaderName && xsrfCookieName && cookies.read(xsrfCookieName); |
| 62 | 70 | ||
| 63 | if (xsrfValue) { | 71 | if (xsrfValue) { |
@@ -1,3 +1,50 @@ | |||
| 1 | const LOOPBACK_HOSTNAMES = new Set(['localhost']); | ||
| 2 | |||
| 3 | const isIPv4Loopback = (host) => { | ||
| 4 | const parts = host.split('.'); | ||
| 5 | if (parts.length !== 4) return false; | ||
| 6 | if (parts[0] !== '127') return false; | ||
| 7 | return parts.every((p) => /^\d+$/.test(p) && Number(p) >= 0 && Number(p) <= 255); | ||
| 8 | }; | ||
| 9 | |||
| 10 | const isIPv6Loopback = (host) => { | ||
| 11 | // Collapse all-zero groups: any form of ::1 / 0:0:...:0:1 | ||
| 12 | // First, strip any leading "::" by normalising with Set lookup of common forms, | ||
| 13 | // then fall back to structural check. | ||
| 14 | if (host === '::1') return true; | ||
| 15 | |||
| 16 | // Check IPv4-mapped IPv6 loopback: ::ffff:<v4-loopback> or ::ffff:<hex-v4-loopback> | ||
| 17 | // Node's URL parser normalises ::ffff:127.0.0.1 → ::ffff:7f00:1 | ||
| 18 | const v4MappedDotted = host.match(/^::ffff:(\d+\.\d+\.\d+\.\d+)$/i); | ||
| 19 | if (v4MappedDotted) return isIPv4Loopback(v4MappedDotted[1]); | ||
| 20 | |||
| 21 | const v4MappedHex = host.match(/^::ffff:([0-9a-f]{1,4}):([0-9a-f]{1,4})$/i); | ||
| 22 | if (v4MappedHex) { | ||
| 23 | const high = parseInt(v4MappedHex[1], 16); | ||
| 24 | // High 16 bits must start with 127 (0x7f) — i.e. 0x7f00..0x7fff | ||
| 25 | return high >= 0x7f00 && high <= 0x7fff; | ||
| 26 | } | ||
| 27 | |||
| 28 | // Full-form ::1 variants: any number of zero groups followed by trailing 1 | ||
| 29 | // e.g. 0:0:0:0:0:0:0:1, 0000:...:0001 | ||
| 30 | const groups = host.split(':'); | ||
| 31 | if (groups.length === 8) { | ||
| 32 | for (let i = 0; i < 7; i++) { | ||
| 33 | if (!/^0+$/.test(groups[i])) return false; | ||
| 34 | } | ||
| 35 | return /^0*1$/.test(groups[7]); | ||
| 36 | } | ||
| 37 | |||
| 38 | return false; | ||
| 39 | }; | ||
| 40 | |||
| 41 | const isLoopback = (host) => { | ||
| 42 | if (!host) return false; | ||
| 43 | if (LOOPBACK_HOSTNAMES.has(host)) return true; | ||
| 44 | if (isIPv4Loopback(host)) return true; | ||
| 45 | return isIPv6Loopback(host); | ||
| 46 | }; | ||
| 47 | |||
| 1 | const DEFAULT_PORTS = { | 48 | const DEFAULT_PORTS = { |
| 2 | http: 80, | 49 | http: 80, |
| 3 | https: 443, | 50 | https: 443, |
@@ -101,6 +148,6 @@ | |||
| 101 | return hostname.endsWith(entryHost); | 148 | return hostname.endsWith(entryHost); |
| 102 | } | 149 | } |
| 103 | 150 | ||
| 104 | return hostname === entryHost; | 151 | return hostname === entryHost || (isLoopback(hostname) && isLoopback(entryHost)); |
| 105 | }); | 152 | }); |
| 106 | } | 153 | } |
@@ -115,6 +115,7 @@ | |||
| 115 | const dots = options.dots; | 115 | const dots = options.dots; |
| 116 | const indexes = options.indexes; | 116 | const indexes = options.indexes; |
| 117 | const _Blob = options.Blob || (typeof Blob !== 'undefined' && Blob); | 117 | const _Blob = options.Blob || (typeof Blob !== 'undefined' && Blob); |
| 118 | const maxDepth = options.maxDepth === undefined ? 100 : options.maxDepth; | ||
| 118 | const useBlob = _Blob && utils.isSpecCompliantForm(formData); | 119 | const useBlob = _Blob && utils.isSpecCompliantForm(formData); |
| 119 | 120 | ||
| 120 | if (!utils.isFunction(visitor)) { | 121 | if (!utils.isFunction(visitor)) { |
@@ -207,9 +208,16 @@ | |||
| 207 | isVisitable, | 208 | isVisitable, |
| 208 | }); | 209 | }); |
| 209 | 210 | ||
| 210 | function build(value, path) { | 211 | function build(value, path, depth = 0) { |
| 211 | if (utils.isUndefined(value)) return; | 212 | if (utils.isUndefined(value)) return; |
| 212 | 213 | ||
| 214 | if (depth > maxDepth) { | ||
| 215 | throw new AxiosError( | ||
| 216 | 'Object is too deeply nested (' + depth + ' levels). Max depth: ' + maxDepth, | ||
| 217 | AxiosError.ERR_FORM_DATA_DEPTH_EXCEEDED | ||
| 218 | ); | ||
| 219 | } | ||
| 220 | |||
| 213 | if (stack.indexOf(value) !== -1) { | 221 | if (stack.indexOf(value) !== -1) { |
| 214 | throw Error('Circular reference detected in ' + path.join('.')); | 222 | throw Error('Circular reference detected in ' + path.join('.')); |
| 215 | } | 223 | } |
@@ -222,7 +230,7 @@ | |||
| 222 | visitor.call(formData, el, utils.isString(key) ? key.trim() : key, path, exposedHelpers); | 230 | visitor.call(formData, el, utils.isString(key) ? key.trim() : key, path, exposedHelpers); |
| 223 | 231 | ||
| 224 | if (result === true) { | 232 | if (result === true) { |
| 225 | build(el, path ? path.concat(key) : [key]); | 233 | build(el, path ? path.concat(key) : [key], depth + 1); |
| 226 | } | 234 | } |
| 227 | }); | 235 | }); |
| 228 | 236 | ||
@@ -257,16 +257,16 @@ | |||
| 257 | const FormDataCtor = typeof G.FormData !== 'undefined' ? G.FormData : undefined; | 257 | const FormDataCtor = typeof G.FormData !== 'undefined' ? G.FormData : undefined; |
| 258 | 258 | ||
| 259 | const isFormData = (thing) => { | 259 | const isFormData = (thing) => { |
| 260 | let kind; | ||
| 261 | return thing && ( | ||
| 262 | (FormDataCtor && thing instanceof FormDataCtor) || ( | ||
| 263 | isFunction(thing.append) && ( | ||
| 264 | (kind = kindOf(thing)) === 'formdata' || | ||
| 265 | // detect form-data instance | ||
| 266 | (kind === 'object' && isFunction(thing.toString) && thing.toString() === '[object FormData]') | ||
| 267 | ) | ||
| 268 | ) | ||
| 269 | ); | 260 | if (!thing) return false; |
| 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). | ||
| 263 | const proto = getPrototypeOf(thing); | ||
| 264 | if (!proto || proto === Object.prototype) return false; | ||
| 265 | if (!isFunction(thing.append)) return false; | ||
| 266 | const kind = kindOf(thing); | ||
| 267 | return kind === 'formdata' || | ||
| 268 | // detect form-data instance | ||
| 269 | (kind === 'object' && isFunction(thing.toString) && thing.toString() === '[object FormData]'); | ||
| 270 | }; | 270 | }; |
| 271 | 271 | ||
| 272 | /** | 272 | /** |
@@ -1,6 +1,6 @@ | |||
| 1 | { | 1 | { |
| 2 | "name": "axios", | 2 | "name": "axios", |
| 3 | "version": "1.15.0", | 3 | "version": "1.15.1", |
| 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,14 +82,14 @@ | |||
| 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 | "Justin Beckwith (https://github.com/JustinBeckwith)", | ||
| 85 | "Rubén Norte (https://github.com/rubennorte)", | 86 | "Rubén Norte (https://github.com/rubennorte)", |
| 86 | "Justin Beckwith (https://github.com/JustinBeckwith)", | ||
| 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 | "Remco Haszing (https://github.com/remcohaszing)", | 89 | "Remco Haszing (https://github.com/remcohaszing)", |
| 90 | "Shaan Majid (https://github.com/shaanmajid)", | ||
| 90 | "Willian Agostini (https://github.com/WillianAgostini)", | 91 | "Willian Agostini (https://github.com/WillianAgostini)", |
| 91 | "Rikki Gibson (https://github.com/RikkiGibson)", | ||
| 92 | "Ben Carp (https://github.com/carpben)" | 92 | "Rikki Gibson (https://github.com/RikkiGibson)" |
| 93 | ], | 93 | ], |
| 94 | "sideEffects": false, | 94 | "sideEffects": false, |
| 95 | "license": "MIT", | 95 | "license": "MIT", |