diff --git a/dist/index.js b/dist/index.js index 3ec17df..5bb5942 100644 --- a/dist/index.js +++ b/dist/index.js @@ -3443,6 +3443,30 @@ var Writable = (__nccwpck_require__(2781).Writable); var assert = __nccwpck_require__(9491); var debug = __nccwpck_require__(1133); +// Whether to use the native URL object or the legacy url module +var useNativeURL = false; +try { + assert(new URL()); +} +catch (error) { + useNativeURL = error.code === "ERR_INVALID_URL"; +} + +// URL fields to preserve in copy operations +var preservedUrlFields = [ + "auth", + "host", + "hostname", + "href", + "path", + "pathname", + "port", + "protocol", + "query", + "search", + "hash", +]; + // Create handlers that pass events from native requests var events = ["abort", "aborted", "connect", "error", "socket", "timeout"]; var eventHandlers = Object.create(null); @@ -3452,19 +3476,20 @@ events.forEach(function (event) { }; }); +// Error types with codes var InvalidUrlError = createErrorType( "ERR_INVALID_URL", "Invalid URL", TypeError ); -// Error types with codes var RedirectionError = createErrorType( "ERR_FR_REDIRECTION_FAILURE", "Redirected request failed" ); var TooManyRedirectsError = createErrorType( "ERR_FR_TOO_MANY_REDIRECTS", - "Maximum number of redirects exceeded" + "Maximum number of redirects exceeded", + RedirectionError ); var MaxBodyLengthExceededError = createErrorType( "ERR_FR_MAX_BODY_LENGTH_EXCEEDED", @@ -3475,6 +3500,9 @@ var WriteAfterEndError = createErrorType( "write after end" ); +// istanbul ignore next +var destroy = Writable.prototype.destroy || noop; + // An HTTP(S) request that can be redirected function RedirectableRequest(options, responseCallback) { // Initialize the request @@ -3496,7 +3524,13 @@ function RedirectableRequest(options, responseCallback) { // React to responses of native requests var self = this; this._onNativeResponse = function (response) { - self._processResponse(response); + try { + self._processResponse(response); + } + catch (cause) { + self.emit("error", cause instanceof RedirectionError ? + cause : new RedirectionError({ cause: cause })); + } }; // Perform the first request @@ -3505,10 +3539,17 @@ function RedirectableRequest(options, responseCallback) { RedirectableRequest.prototype = Object.create(Writable.prototype); RedirectableRequest.prototype.abort = function () { - abortRequest(this._currentRequest); + destroyRequest(this._currentRequest); + this._currentRequest.abort(); this.emit("abort"); }; +RedirectableRequest.prototype.destroy = function (error) { + destroyRequest(this._currentRequest, error); + destroy.call(this, error); + return this; +}; + // Writes buffered data to the current native request RedirectableRequest.prototype.write = function (data, encoding, callback) { // Writing is not allowed if end has been called @@ -3621,6 +3662,7 @@ RedirectableRequest.prototype.setTimeout = function (msecs, callback) { self.removeListener("abort", clearTimer); self.removeListener("error", clearTimer); self.removeListener("response", clearTimer); + self.removeListener("close", clearTimer); if (callback) { self.removeListener("timeout", callback); } @@ -3647,6 +3689,7 @@ RedirectableRequest.prototype.setTimeout = function (msecs, callback) { this.on("abort", clearTimer); this.on("error", clearTimer); this.on("response", clearTimer); + this.on("close", clearTimer); return this; }; @@ -3705,8 +3748,7 @@ RedirectableRequest.prototype._performRequest = function () { var protocol = this._options.protocol; var nativeProtocol = this._options.nativeProtocols[protocol]; if (!nativeProtocol) { - this.emit("error", new TypeError("Unsupported protocol " + protocol)); - return; + throw new TypeError("Unsupported protocol " + protocol); } // If specified, use the agent corresponding to the protocol @@ -3798,15 +3840,14 @@ RedirectableRequest.prototype._processResponse = function (response) { } // The response is a redirect, so abort the current request - abortRequest(this._currentRequest); + destroyRequest(this._currentRequest); // Discard the remainder of the response to avoid waiting for data response.destroy(); // RFC7231ยง6.4: A client SHOULD detect and intervene // in cyclical redirections (i.e., "infinite" redirection loops). if (++this._redirectCount > this._options.maxRedirects) { - this.emit("error", new TooManyRedirectsError()); - return; + throw new TooManyRedirectsError(); } // Store the request headers if applicable @@ -3840,34 +3881,24 @@ RedirectableRequest.prototype._processResponse = function (response) { var currentHostHeader = removeMatchingHeaders(/^host$/i, this._options.headers); // If the redirect is relative, carry over the host of the last request - var currentUrlParts = url.parse(this._currentUrl); + var currentUrlParts = parseUrl(this._currentUrl); var currentHost = currentHostHeader || currentUrlParts.host; var currentUrl = /^\w+:/.test(location) ? this._currentUrl : url.format(Object.assign(currentUrlParts, { host: currentHost })); - // Determine the URL of the redirection - var redirectUrl; - try { - redirectUrl = url.resolve(currentUrl, location); - } - catch (cause) { - this.emit("error", new RedirectionError({ cause: cause })); - return; - } - // Create the redirected request - debug("redirecting to", redirectUrl); + var redirectUrl = resolveUrl(location, currentUrl); + debug("redirecting to", redirectUrl.href); this._isRedirect = true; - var redirectUrlParts = url.parse(redirectUrl); - Object.assign(this._options, redirectUrlParts); + spreadUrlObject(redirectUrl, this._options); // Drop confidential headers when redirecting to a less secure protocol // or to a different domain that is not a superdomain - if (redirectUrlParts.protocol !== currentUrlParts.protocol && - redirectUrlParts.protocol !== "https:" || - redirectUrlParts.host !== currentHost && - !isSubdomain(redirectUrlParts.host, currentHost)) { - removeMatchingHeaders(/^(?:authorization|cookie)$/i, this._options.headers); + if (redirectUrl.protocol !== currentUrlParts.protocol && + redirectUrl.protocol !== "https:" || + redirectUrl.host !== currentHost && + !isSubdomain(redirectUrl.host, currentHost)) { + removeMatchingHeaders(/^(?:(?:proxy-)?authorization|cookie)$/i, this._options.headers); } // Evaluate the beforeRedirect callback @@ -3881,23 +3912,12 @@ RedirectableRequest.prototype._processResponse = function (response) { method: method, headers: requestHeaders, }; - try { - beforeRedirect(this._options, responseDetails, requestDetails); - } - catch (err) { - this.emit("error", err); - return; - } + beforeRedirect(this._options, responseDetails, requestDetails); this._sanitizeOptions(this._options); } // Perform the redirected request - try { - this._performRequest(); - } - catch (cause) { - this.emit("error", new RedirectionError({ cause: cause })); - } + this._performRequest(); }; // Wraps the key/value object of protocols with redirect functionality @@ -3917,27 +3937,16 @@ function wrap(protocols) { // Executes a request, following redirects function request(input, options, callback) { - // Parse parameters - if (isString(input)) { - var parsed; - try { - parsed = urlToOptions(new URL(input)); - } - catch (err) { - /* istanbul ignore next */ - parsed = url.parse(input); - } - if (!isString(parsed.protocol)) { - throw new InvalidUrlError({ input }); - } - input = parsed; + // Parse parameters, ensuring that input is an object + if (isURL(input)) { + input = spreadUrlObject(input); } - else if (URL && (input instanceof URL)) { - input = urlToOptions(input); + else if (isString(input)) { + input = spreadUrlObject(parseUrl(input)); } else { callback = options; - options = input; + options = validateUrl(input); input = { protocol: protocol }; } if (isFunction(options)) { @@ -3976,27 +3985,57 @@ function wrap(protocols) { return exports; } -/* istanbul ignore next */ function noop() { /* empty */ } -// from https://github.com/nodejs/node/blob/master/lib/internal/url.js -function urlToOptions(urlObject) { - var options = { - protocol: urlObject.protocol, - hostname: urlObject.hostname.startsWith("[") ? - /* istanbul ignore next */ - urlObject.hostname.slice(1, -1) : - urlObject.hostname, - hash: urlObject.hash, - search: urlObject.search, - pathname: urlObject.pathname, - path: urlObject.pathname + urlObject.search, - href: urlObject.href, - }; - if (urlObject.port !== "") { - options.port = Number(urlObject.port); +function parseUrl(input) { + var parsed; + /* istanbul ignore else */ + if (useNativeURL) { + parsed = new URL(input); } - return options; + else { + // Ensure the URL is valid and absolute + parsed = validateUrl(url.parse(input)); + if (!isString(parsed.protocol)) { + throw new InvalidUrlError({ input }); + } + } + return parsed; +} + +function resolveUrl(relative, base) { + /* istanbul ignore next */ + return useNativeURL ? new URL(relative, base) : parseUrl(url.resolve(base, relative)); +} + +function validateUrl(input) { + if (/^\[/.test(input.hostname) && !/^\[[:0-9a-f]+\]$/i.test(input.hostname)) { + throw new InvalidUrlError({ input: input.href || input }); + } + if (/^\[/.test(input.host) && !/^\[[:0-9a-f]+\](:\d+)?$/i.test(input.host)) { + throw new InvalidUrlError({ input: input.href || input }); + } + return input; +} + +function spreadUrlObject(urlObject, target) { + var spread = target || {}; + for (var key of preservedUrlFields) { + spread[key] = urlObject[key]; + } + + // Fix IPv6 hostname + if (spread.hostname.startsWith("[")) { + spread.hostname = spread.hostname.slice(1, -1); + } + // Ensure port is a number + if (spread.port !== "") { + spread.port = Number(spread.port); + } + // Concatenate path + spread.path = spread.search ? spread.pathname + spread.search : spread.pathname; + + return spread; } function removeMatchingHeaders(regex, headers) { @@ -4022,17 +4061,25 @@ function createErrorType(code, message, baseClass) { // Attach constructor and set default properties CustomError.prototype = new (baseClass || Error)(); - CustomError.prototype.constructor = CustomError; - CustomError.prototype.name = "Error [" + code + "]"; + Object.defineProperties(CustomError.prototype, { + constructor: { + value: CustomError, + enumerable: false, + }, + name: { + value: "Error [" + code + "]", + enumerable: false, + }, + }); return CustomError; } -function abortRequest(request) { +function destroyRequest(request, error) { for (var event of events) { request.removeListener(event, eventHandlers[event]); } request.on("error", noop); - request.abort(); + request.destroy(error); } function isSubdomain(subdomain, domain) { @@ -4053,6 +4100,10 @@ function isBuffer(value) { return typeof value === "object" && ("length" in value); } +function isURL(value) { + return URL && value instanceof URL; +} + // Exports module.exports = wrap({ http: http, https: https }); module.exports.wrap = wrap; @@ -6294,7 +6345,7 @@ module.exports = require("zlib"); /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; -// Axios v1.5.0 Copyright (c) 2023 Matt Zabriskie and contributors +// Axios v1.7.4 Copyright (c) 2024 Matt Zabriskie and contributors const FormData$1 = __nccwpck_require__(4334); @@ -6306,7 +6357,7 @@ const util = __nccwpck_require__(3837); const followRedirects = __nccwpck_require__(7707); const zlib = __nccwpck_require__(9796); const stream = __nccwpck_require__(2781); -const EventEmitter = __nccwpck_require__(2361); +const events = __nccwpck_require__(2361); function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } @@ -6318,7 +6369,6 @@ const util__default = /*#__PURE__*/_interopDefaultLegacy(util); const followRedirects__default = /*#__PURE__*/_interopDefaultLegacy(followRedirects); const zlib__default = /*#__PURE__*/_interopDefaultLegacy(zlib); const stream__default = /*#__PURE__*/_interopDefaultLegacy(stream); -const EventEmitter__default = /*#__PURE__*/_interopDefaultLegacy(EventEmitter); function bind(fn, thisArg) { return function wrap() { @@ -6533,6 +6583,8 @@ const isFormData = (thing) => { */ const isURLSearchParams = kindOfTest('URLSearchParams'); +const [isReadableStream, isRequest, isResponse, isHeaders] = ['ReadableStream', 'Request', 'Response', 'Headers'].map(kindOfTest); + /** * Trim excess whitespace off the beginning and end of a string * @@ -6921,8 +6973,7 @@ const toObjectSet = (arrayOrString, delimiter) => { const noop = () => {}; const toFiniteNumber = (value, defaultValue) => { - value = +value; - return Number.isFinite(value) ? value : defaultValue; + return value != null && Number.isFinite(value = +value) ? value : defaultValue; }; const ALPHA = 'abcdefghijklmnopqrstuvwxyz'; @@ -6992,7 +7043,37 @@ const isAsyncFn = kindOfTest('AsyncFunction'); const isThenable = (thing) => thing && (isObject(thing) || isFunction(thing)) && isFunction(thing.then) && isFunction(thing.catch); -const utils = { +// original code +// https://github.com/DigitalBrainJS/AxiosPromise/blob/16deab13710ec09779922131f3fa5954320f83ab/lib/utils.js#L11-L34 + +const _setImmediate = ((setImmediateSupported, postMessageSupported) => { + if (setImmediateSupported) { + return setImmediate; + } + + return postMessageSupported ? ((token, callbacks) => { + _global.addEventListener("message", ({source, data}) => { + if (source === _global && data === token) { + callbacks.length && callbacks.shift()(); + } + }, false); + + return (cb) => { + callbacks.push(cb); + _global.postMessage(token, "*"); + } + })(`axios@${Math.random()}`, []) : (cb) => setTimeout(cb); +})( + typeof setImmediate === 'function', + isFunction(_global.postMessage) +); + +const asap = typeof queueMicrotask !== 'undefined' ? + queueMicrotask.bind(_global) : ( typeof process !== 'undefined' && process.nextTick || _setImmediate); + +// ********************* + +const utils$1 = { isArray, isArrayBuffer, isBuffer, @@ -7003,6 +7084,10 @@ const utils = { isBoolean, isObject, isPlainObject, + isReadableStream, + isRequest, + isResponse, + isHeaders, isUndefined, isDate, isFile, @@ -7043,7 +7128,9 @@ const utils = { isSpecCompliantForm, toJSONObject, isAsyncFn, - isThenable + isThenable, + setImmediate: _setImmediate, + asap }; /** @@ -7074,7 +7161,7 @@ function AxiosError(message, code, config, request, response) { response && (this.response = response); } -utils.inherits(AxiosError, Error, { +utils$1.inherits(AxiosError, Error, { toJSON: function toJSON() { return { // Standard @@ -7089,7 +7176,7 @@ utils.inherits(AxiosError, Error, { columnNumber: this.columnNumber, stack: this.stack, // Axios - config: utils.toJSONObject(this.config), + config: utils$1.toJSONObject(this.config), code: this.code, status: this.response && this.response.status ? this.response.status : null }; @@ -7124,7 +7211,7 @@ Object.defineProperty(prototype$1, 'isAxiosError', {value: true}); AxiosError.from = (error, code, config, request, response, customProps) => { const axiosError = Object.create(prototype$1); - utils.toFlatObject(error, axiosError, function filter(obj) { + utils$1.toFlatObject(error, axiosError, function filter(obj) { return obj !== Error.prototype; }, prop => { return prop !== 'isAxiosError'; @@ -7149,7 +7236,7 @@ AxiosError.from = (error, code, config, request, response, customProps) => { * @returns {boolean} */ function isVisitable(thing) { - return utils.isPlainObject(thing) || utils.isArray(thing); + return utils$1.isPlainObject(thing) || utils$1.isArray(thing); } /** @@ -7160,7 +7247,7 @@ function isVisitable(thing) { * @returns {string} the key without the brackets. */ function removeBrackets(key) { - return utils.endsWith(key, '[]') ? key.slice(0, -2) : key; + return utils$1.endsWith(key, '[]') ? key.slice(0, -2) : key; } /** @@ -7189,10 +7276,10 @@ function renderKey(path, key, dots) { * @returns {boolean} */ function isFlatArray(arr) { - return utils.isArray(arr) && !arr.some(isVisitable); + return utils$1.isArray(arr) && !arr.some(isVisitable); } -const predicates = utils.toFlatObject(utils, {}, null, function filter(prop) { +const predicates = utils$1.toFlatObject(utils$1, {}, null, function filter(prop) { return /^is[A-Z]/.test(prop); }); @@ -7220,7 +7307,7 @@ const predicates = utils.toFlatObject(utils, {}, null, function filter(prop) { * @returns */ function toFormData(obj, formData, options) { - if (!utils.isObject(obj)) { + if (!utils$1.isObject(obj)) { throw new TypeError('target must be an object'); } @@ -7228,13 +7315,13 @@ function toFormData(obj, formData, options) { formData = formData || new (FormData__default["default"] || FormData)(); // eslint-disable-next-line no-param-reassign - options = utils.toFlatObject(options, { + options = utils$1.toFlatObject(options, { metaTokens: true, dots: false, indexes: false }, false, function defined(option, source) { // eslint-disable-next-line no-eq-null,eqeqeq - return !utils.isUndefined(source[option]); + return !utils$1.isUndefined(source[option]); }); const metaTokens = options.metaTokens; @@ -7243,24 +7330,24 @@ function toFormData(obj, formData, options) { const dots = options.dots; const indexes = options.indexes; const _Blob = options.Blob || typeof Blob !== 'undefined' && Blob; - const useBlob = _Blob && utils.isSpecCompliantForm(formData); + const useBlob = _Blob && utils$1.isSpecCompliantForm(formData); - if (!utils.isFunction(visitor)) { + if (!utils$1.isFunction(visitor)) { throw new TypeError('visitor must be a function'); } function convertValue(value) { if (value === null) return ''; - if (utils.isDate(value)) { + if (utils$1.isDate(value)) { return value.toISOString(); } - if (!useBlob && utils.isBlob(value)) { + if (!useBlob && utils$1.isBlob(value)) { throw new AxiosError('Blob is not supported. Use a Buffer instead.'); } - if (utils.isArrayBuffer(value) || utils.isTypedArray(value)) { + if (utils$1.isArrayBuffer(value) || utils$1.isTypedArray(value)) { return useBlob && typeof Blob === 'function' ? new Blob([value]) : Buffer.from(value); } @@ -7281,20 +7368,20 @@ function toFormData(obj, formData, options) { let arr = value; if (value && !path && typeof value === 'object') { - if (utils.endsWith(key, '{}')) { + if (utils$1.endsWith(key, '{}')) { // eslint-disable-next-line no-param-reassign key = metaTokens ? key : key.slice(0, -2); // eslint-disable-next-line no-param-reassign value = JSON.stringify(value); } else if ( - (utils.isArray(value) && isFlatArray(value)) || - ((utils.isFileList(value) || utils.endsWith(key, '[]')) && (arr = utils.toArray(value)) + (utils$1.isArray(value) && isFlatArray(value)) || + ((utils$1.isFileList(value) || utils$1.endsWith(key, '[]')) && (arr = utils$1.toArray(value)) )) { // eslint-disable-next-line no-param-reassign key = removeBrackets(key); arr.forEach(function each(el, index) { - !(utils.isUndefined(el) || el === null) && formData.append( + !(utils$1.isUndefined(el) || el === null) && formData.append( // eslint-disable-next-line no-nested-ternary indexes === true ? renderKey([key], index, dots) : (indexes === null ? key : key + '[]'), convertValue(el) @@ -7322,7 +7409,7 @@ function toFormData(obj, formData, options) { }); function build(value, path) { - if (utils.isUndefined(value)) return; + if (utils$1.isUndefined(value)) return; if (stack.indexOf(value) !== -1) { throw Error('Circular reference detected in ' + path.join('.')); @@ -7330,9 +7417,9 @@ function toFormData(obj, formData, options) { stack.push(value); - utils.forEach(value, function each(el, key) { - const result = !(utils.isUndefined(el) || el === null) && visitor.call( - formData, el, utils.isString(key) ? key.trim() : key, path, exposedHelpers + utils$1.forEach(value, function each(el, key) { + const result = !(utils$1.isUndefined(el) || el === null) && visitor.call( + formData, el, utils$1.isString(key) ? key.trim() : key, path, exposedHelpers ); if (result === true) { @@ -7343,7 +7430,7 @@ function toFormData(obj, formData, options) { stack.pop(); } - if (!utils.isObject(obj)) { + if (!utils$1.isObject(obj)) { throw new TypeError('data must be an object'); } @@ -7447,7 +7534,7 @@ function buildURL(url, params, options) { if (serializeFn) { serializedParams = serializeFn(params, options); } else { - serializedParams = utils.isURLSearchParams(params) ? + serializedParams = utils$1.isURLSearchParams(params) ? params.toString() : new AxiosURLSearchParams(params, options).toString(_encode); } @@ -7522,7 +7609,7 @@ class InterceptorManager { * @returns {void} */ forEach(fn) { - utils.forEach(this.handlers, function forEachHandler(h) { + utils$1.forEach(this.handlers, function forEachHandler(h) { if (h !== null) { fn(h); } @@ -7540,7 +7627,7 @@ const transitionalDefaults = { const URLSearchParams = url__default["default"].URLSearchParams; -const platform = { +const platform$1 = { isNode: true, classes: { URLSearchParams, @@ -7550,10 +7637,67 @@ const platform = { protocols: [ 'http', 'https', 'file', 'data' ] }; +const hasBrowserEnv = typeof window !== 'undefined' && typeof document !== 'undefined'; + +/** + * Determine if we're running in a standard browser environment + * + * This allows axios to run in a web worker, and react-native. + * Both environments support XMLHttpRequest, but not fully standard globals. + * + * web workers: + * typeof window -> undefined + * typeof document -> undefined + * + * react-native: + * navigator.product -> 'ReactNative' + * nativescript + * navigator.product -> 'NativeScript' or 'NS' + * + * @returns {boolean} + */ +const hasStandardBrowserEnv = ( + (product) => { + return hasBrowserEnv && ['ReactNative', 'NativeScript', 'NS'].indexOf(product) < 0 + })(typeof navigator !== 'undefined' && navigator.product); + +/** + * Determine if we're running in a standard browser webWorker environment + * + * Although the `isStandardBrowserEnv` method indicates that + * `allows axios to run in a web worker`, the WebWorker will still be + * filtered out due to its judgment standard + * `typeof window !== 'undefined' && typeof document !== 'undefined'`. + * This leads to a problem when axios post `FormData` in webWorker + */ +const hasStandardBrowserWebWorkerEnv = (() => { + return ( + typeof WorkerGlobalScope !== 'undefined' && + // eslint-disable-next-line no-undef + self instanceof WorkerGlobalScope && + typeof self.importScripts === 'function' + ); +})(); + +const origin = hasBrowserEnv && window.location.href || 'http://localhost'; + +const utils = /*#__PURE__*/Object.freeze({ + __proto__: null, + hasBrowserEnv: hasBrowserEnv, + hasStandardBrowserWebWorkerEnv: hasStandardBrowserWebWorkerEnv, + hasStandardBrowserEnv: hasStandardBrowserEnv, + origin: origin +}); + +const platform = { + ...utils, + ...platform$1 +}; + function toURLEncodedForm(data, options) { return toFormData(data, new platform.classes.URLSearchParams(), Object.assign({ visitor: function(value, key, path, helpers) { - if (utils.isBuffer(value)) { + if (platform.isNode && utils$1.isBuffer(value)) { this.append(key, value.toString('base64')); return false; } @@ -7575,7 +7719,7 @@ function parsePropPath(name) { // foo.x.y.z // foo-x-y-z // foo x y z - return utils.matchAll(/\w+|\[(\w*)]/g, name).map(match => { + return utils$1.matchAll(/\w+|\[(\w*)]/g, name).map(match => { return match[0] === '[]' ? '' : match[1] || match[0]; }); } @@ -7610,12 +7754,15 @@ function arrayToObject(arr) { function formDataToJSON(formData) { function buildPath(path, value, target, index) { let name = path[index++]; + + if (name === '__proto__') return true; + const isNumericKey = Number.isFinite(+name); const isLast = index >= path.length; - name = !name && utils.isArray(target) ? target.length : name; + name = !name && utils$1.isArray(target) ? target.length : name; if (isLast) { - if (utils.hasOwnProp(target, name)) { + if (utils$1.hasOwnProp(target, name)) { target[name] = [target[name], value]; } else { target[name] = value; @@ -7624,23 +7771,23 @@ function formDataToJSON(formData) { return !isNumericKey; } - if (!target[name] || !utils.isObject(target[name])) { + if (!target[name] || !utils$1.isObject(target[name])) { target[name] = []; } const result = buildPath(path, value, target[name], index); - if (result && utils.isArray(target[name])) { + if (result && utils$1.isArray(target[name])) { target[name] = arrayToObject(target[name]); } return !isNumericKey; } - if (utils.isFormData(formData) && utils.isFunction(formData.entries)) { + if (utils$1.isFormData(formData) && utils$1.isFunction(formData.entries)) { const obj = {}; - utils.forEachEntry(formData, (name, value) => { + utils$1.forEachEntry(formData, (name, value) => { buildPath(parsePropPath(name), value, obj, 0); }); @@ -7661,10 +7808,10 @@ function formDataToJSON(formData) { * @returns {string} A stringified version of the rawValue. */ function stringifySafely(rawValue, parser, encoder) { - if (utils.isString(rawValue)) { + if (utils$1.isString(rawValue)) { try { (parser || JSON.parse)(rawValue); - return utils.trim(rawValue); + return utils$1.trim(rawValue); } catch (e) { if (e.name !== 'SyntaxError') { throw e; @@ -7679,38 +7826,36 @@ const defaults = { transitional: transitionalDefaults, - adapter: 'http' , + adapter: ['xhr', 'http', 'fetch'], transformRequest: [function transformRequest(data, headers) { const contentType = headers.getContentType() || ''; const hasJSONContentType = contentType.indexOf('application/json') > -1; - const isObjectPayload = utils.isObject(data); + const isObjectPayload = utils$1.isObject(data); - if (isObjectPayload && utils.isHTMLForm(data)) { + if (isObjectPayload && utils$1.isHTMLForm(data)) { data = new FormData(data); } - const isFormData = utils.isFormData(data); + const isFormData = utils$1.isFormData(data); if (isFormData) { - if (!hasJSONContentType) { - return data; - } return hasJSONContentType ? JSON.stringify(formDataToJSON(data)) : data; } - if (utils.isArrayBuffer(data) || - utils.isBuffer(data) || - utils.isStream(data) || - utils.isFile(data) || - utils.isBlob(data) + if (utils$1.isArrayBuffer(data) || + utils$1.isBuffer(data) || + utils$1.isStream(data) || + utils$1.isFile(data) || + utils$1.isBlob(data) || + utils$1.isReadableStream(data) ) { return data; } - if (utils.isArrayBufferView(data)) { + if (utils$1.isArrayBufferView(data)) { return data.buffer; } - if (utils.isURLSearchParams(data)) { + if (utils$1.isURLSearchParams(data)) { headers.setContentType('application/x-www-form-urlencoded;charset=utf-8', false); return data.toString(); } @@ -7722,7 +7867,7 @@ const defaults = { return toURLEncodedForm(data, this.formSerializer).toString(); } - if ((isFileList = utils.isFileList(data)) || contentType.indexOf('multipart/form-data') > -1) { + if ((isFileList = utils$1.isFileList(data)) || contentType.indexOf('multipart/form-data') > -1) { const _FormData = this.env && this.env.FormData; return toFormData( @@ -7746,7 +7891,11 @@ const defaults = { const forcedJSONParsing = transitional && transitional.forcedJSONParsing; const JSONRequested = this.responseType === 'json'; - if (data && utils.isString(data) && ((forcedJSONParsing && !this.responseType) || JSONRequested)) { + if (utils$1.isResponse(data) || utils$1.isReadableStream(data)) { + return data; + } + + if (data && utils$1.isString(data) && ((forcedJSONParsing && !this.responseType) || JSONRequested)) { const silentJSONParsing = transitional && transitional.silentJSONParsing; const strictJSONParsing = !silentJSONParsing && JSONRequested; @@ -7794,7 +7943,7 @@ const defaults = { } }; -utils.forEach(['delete', 'get', 'head', 'post', 'put', 'patch'], (method) => { +utils$1.forEach(['delete', 'get', 'head', 'post', 'put', 'patch'], (method) => { defaults.headers[method] = {}; }); @@ -7802,7 +7951,7 @@ const defaults$1 = defaults; // RawAxiosHeaders whose duplicates are ignored by node // c.f. https://nodejs.org/api/http.html#http_message_headers -const ignoreDuplicateOf = utils.toObjectSet([ +const ignoreDuplicateOf = utils$1.toObjectSet([ 'age', 'authorization', 'content-length', 'content-type', 'etag', 'expires', 'from', 'host', 'if-modified-since', 'if-unmodified-since', 'last-modified', 'location', 'max-forwards', 'proxy-authorization', @@ -7863,7 +8012,7 @@ function normalizeValue(value) { return value; } - return utils.isArray(value) ? value.map(normalizeValue) : String(value); + return utils$1.isArray(value) ? value.map(normalizeValue) : String(value); } function parseTokens(str) { @@ -7881,7 +8030,7 @@ function parseTokens(str) { const isValidHeaderName = (str) => /^[-_a-zA-Z0-9^`|~,!#$%&'*+.]+$/.test(str.trim()); function matchHeaderValue(context, value, header, filter, isHeaderNameFilter) { - if (utils.isFunction(filter)) { + if (utils$1.isFunction(filter)) { return filter.call(this, value, header); } @@ -7889,13 +8038,13 @@ function matchHeaderValue(context, value, header, filter, isHeaderNameFilter) { value = header; } - if (!utils.isString(value)) return; + if (!utils$1.isString(value)) return; - if (utils.isString(filter)) { + if (utils$1.isString(filter)) { return value.indexOf(filter) !== -1; } - if (utils.isRegExp(filter)) { + if (utils$1.isRegExp(filter)) { return filter.test(value); } } @@ -7908,7 +8057,7 @@ function formatHeader(header) { } function buildAccessors(obj, header) { - const accessorName = utils.toCamelCase(' ' + header); + const accessorName = utils$1.toCamelCase(' ' + header); ['get', 'set', 'has'].forEach(methodName => { Object.defineProperty(obj, methodName + accessorName, { @@ -7935,7 +8084,7 @@ class AxiosHeaders { throw new Error('header name must be a non-empty string'); } - const key = utils.findKey(self, lHeader); + const key = utils$1.findKey(self, lHeader); if(!key || self[key] === undefined || _rewrite === true || (_rewrite === undefined && self[key] !== false)) { self[key || _header] = normalizeValue(_value); @@ -7943,12 +8092,16 @@ class AxiosHeaders { } const setHeaders = (headers, _rewrite) => - utils.forEach(headers, (_value, _header) => setHeader(_value, _header, _rewrite)); + utils$1.forEach(headers, (_value, _header) => setHeader(_value, _header, _rewrite)); - if (utils.isPlainObject(header) || header instanceof this.constructor) { + if (utils$1.isPlainObject(header) || header instanceof this.constructor) { setHeaders(header, valueOrRewrite); - } else if(utils.isString(header) && (header = header.trim()) && !isValidHeaderName(header)) { + } else if(utils$1.isString(header) && (header = header.trim()) && !isValidHeaderName(header)) { setHeaders(parseHeaders(header), valueOrRewrite); + } else if (utils$1.isHeaders(header)) { + for (const [key, value] of header.entries()) { + setHeader(value, key, rewrite); + } } else { header != null && setHeader(valueOrRewrite, header, rewrite); } @@ -7960,7 +8113,7 @@ class AxiosHeaders { header = normalizeHeader(header); if (header) { - const key = utils.findKey(this, header); + const key = utils$1.findKey(this, header); if (key) { const value = this[key]; @@ -7973,11 +8126,11 @@ class AxiosHeaders { return parseTokens(value); } - if (utils.isFunction(parser)) { + if (utils$1.isFunction(parser)) { return parser.call(this, value, key); } - if (utils.isRegExp(parser)) { + if (utils$1.isRegExp(parser)) { return parser.exec(value); } @@ -7990,7 +8143,7 @@ class AxiosHeaders { header = normalizeHeader(header); if (header) { - const key = utils.findKey(this, header); + const key = utils$1.findKey(this, header); return !!(key && this[key] !== undefined && (!matcher || matchHeaderValue(this, this[key], key, matcher))); } @@ -8006,7 +8159,7 @@ class AxiosHeaders { _header = normalizeHeader(_header); if (_header) { - const key = utils.findKey(self, _header); + const key = utils$1.findKey(self, _header); if (key && (!matcher || matchHeaderValue(self, self[key], key, matcher))) { delete self[key]; @@ -8016,7 +8169,7 @@ class AxiosHeaders { } } - if (utils.isArray(header)) { + if (utils$1.isArray(header)) { header.forEach(deleteHeader); } else { deleteHeader(header); @@ -8045,8 +8198,8 @@ class AxiosHeaders { const self = this; const headers = {}; - utils.forEach(this, (value, header) => { - const key = utils.findKey(headers, header); + utils$1.forEach(this, (value, header) => { + const key = utils$1.findKey(headers, header); if (key) { self[key] = normalizeValue(value); @@ -8075,8 +8228,8 @@ class AxiosHeaders { toJSON(asStrings) { const obj = Object.create(null); - utils.forEach(this, (value, header) => { - value != null && value !== false && (obj[header] = asStrings && utils.isArray(value) ? value.join(', ') : value); + utils$1.forEach(this, (value, header) => { + value != null && value !== false && (obj[header] = asStrings && utils$1.isArray(value) ? value.join(', ') : value); }); return obj; @@ -8123,7 +8276,7 @@ class AxiosHeaders { } } - utils.isArray(header) ? header.forEach(defineAccessor) : defineAccessor(header); + utils$1.isArray(header) ? header.forEach(defineAccessor) : defineAccessor(header); return this; } @@ -8132,7 +8285,7 @@ class AxiosHeaders { AxiosHeaders.accessor(['Content-Type', 'Content-Length', 'Accept', 'Accept-Encoding', 'User-Agent', 'Authorization']); // reserved names hotfix -utils.reduceDescriptors(AxiosHeaders.prototype, ({value}, key) => { +utils$1.reduceDescriptors(AxiosHeaders.prototype, ({value}, key) => { let mapped = key[0].toUpperCase() + key.slice(1); // map `set` => `Set` return { get: () => value, @@ -8142,7 +8295,7 @@ utils.reduceDescriptors(AxiosHeaders.prototype, ({value}, key) => { } }); -utils.freezeMethods(AxiosHeaders); +utils$1.freezeMethods(AxiosHeaders); const AxiosHeaders$1 = AxiosHeaders; @@ -8160,7 +8313,7 @@ function transformData(fns, response) { const headers = AxiosHeaders$1.from(context.headers); let data = context.data; - utils.forEach(fns, function transform(fn) { + utils$1.forEach(fns, function transform(fn) { data = fn.call(config, data, headers.normalize(), response ? response.status : undefined); }); @@ -8188,7 +8341,7 @@ function CanceledError(message, config, request) { this.name = 'CanceledError'; } -utils.inherits(CanceledError, AxiosError, { +utils$1.inherits(CanceledError, AxiosError, { __CANCEL__: true }); @@ -8240,7 +8393,7 @@ function isAbsoluteURL(url) { */ function combineURLs(baseURL, relativeURL) { return relativeURL - ? baseURL.replace(/\/+$/, '') + '/' + relativeURL.replace(/^\/+/, '') + ? baseURL.replace(/\/?\/$/, '') + '/' + relativeURL.replace(/^\/+/, '') : baseURL; } @@ -8261,7 +8414,7 @@ function buildFullPath(baseURL, requestedURL) { return requestedURL; } -const VERSION = "1.5.0"; +const VERSION = "1.7.4"; function parseProtocol(url) { const match = /^([-+\w]{1,25})(:?\/\/|:)/.exec(url); @@ -8316,93 +8469,11 @@ function fromDataURI(uri, asBlob, options) { throw new AxiosError('Unsupported protocol ' + protocol, AxiosError.ERR_NOT_SUPPORT); } -/** - * Throttle decorator - * @param {Function} fn - * @param {Number} freq - * @return {Function} - */ -function throttle(fn, freq) { - let timestamp = 0; - const threshold = 1000 / freq; - let timer = null; - return function throttled(force, args) { - const now = Date.now(); - if (force || now - timestamp > threshold) { - if (timer) { - clearTimeout(timer); - timer = null; - } - timestamp = now; - return fn.apply(null, args); - } - if (!timer) { - timer = setTimeout(() => { - timer = null; - timestamp = Date.now(); - return fn.apply(null, args); - }, threshold - (now - timestamp)); - } - }; -} - -/** - * Calculate data maxRate - * @param {Number} [samplesCount= 10] - * @param {Number} [min= 1000] - * @returns {Function} - */ -function speedometer(samplesCount, min) { - samplesCount = samplesCount || 10; - const bytes = new Array(samplesCount); - const timestamps = new Array(samplesCount); - let head = 0; - let tail = 0; - let firstSampleTS; - - min = min !== undefined ? min : 1000; - - return function push(chunkLength) { - const now = Date.now(); - - const startedAt = timestamps[tail]; - - if (!firstSampleTS) { - firstSampleTS = now; - } - - bytes[head] = chunkLength; - timestamps[head] = now; - - let i = tail; - let bytesCount = 0; - - while (i !== head) { - bytesCount += bytes[i++]; - i = i % samplesCount; - } - - head = (head + 1) % samplesCount; - - if (head === tail) { - tail = (tail + 1) % samplesCount; - } - - if (now - firstSampleTS < min) { - return; - } - - const passed = startedAt && now - startedAt; - - return passed ? Math.round(bytesCount * 1000 / passed) : undefined; - }; -} - const kInternals = Symbol('internals'); class AxiosTransformStream extends stream__default["default"].Transform{ constructor(options) { - options = utils.toFlatObject(options, { + options = utils$1.toFlatObject(options, { maxRate: 0, chunkSize: 64 * 1024, minChunkSize: 100, @@ -8410,19 +8481,15 @@ class AxiosTransformStream extends stream__default["default"].Transform{ ticksRate: 2, samplesCount: 15 }, null, (prop, source) => { - return !utils.isUndefined(source[prop]); + return !utils$1.isUndefined(source[prop]); }); super({ readableHighWaterMark: options.chunkSize }); - const self = this; - const internals = this[kInternals] = { - length: options.length, timeWindow: options.timeWindow, - ticksRate: options.ticksRate, chunkSize: options.chunkSize, maxRate: options.maxRate, minChunkSize: options.minChunkSize, @@ -8434,8 +8501,6 @@ class AxiosTransformStream extends stream__default["default"].Transform{ onReadCallback: null }; - const _speedometer = speedometer(internals.ticksRate * options.samplesCount, internals.timeWindow); - this.on('newListener', event => { if (event === 'progress') { if (!internals.isCaptured) { @@ -8443,38 +8508,6 @@ class AxiosTransformStream extends stream__default["default"].Transform{ } } }); - - let bytesNotified = 0; - - internals.updateProgress = throttle(function throttledHandler() { - const totalBytes = internals.length; - const bytesTransferred = internals.bytesSeen; - const progressBytes = bytesTransferred - bytesNotified; - if (!progressBytes || self.destroyed) return; - - const rate = _speedometer(progressBytes); - - bytesNotified = bytesTransferred; - - process.nextTick(() => { - self.emit('progress', { - 'loaded': bytesTransferred, - 'total': totalBytes, - 'progress': totalBytes ? (bytesTransferred / totalBytes) : undefined, - 'bytes': progressBytes, - 'rate': rate ? rate : undefined, - 'estimated': rate && totalBytes && bytesTransferred <= totalBytes ? - (totalBytes - bytesTransferred) / rate : undefined - }); - }); - }, internals.ticksRate); - - const onFinish = () => { - internals.updateProgress(true); - }; - - this.once('end', onFinish); - this.once('error', onFinish); } _read(size) { @@ -8488,7 +8521,6 @@ class AxiosTransformStream extends stream__default["default"].Transform{ } _transform(chunk, encoding, callback) { - const self = this; const internals = this[kInternals]; const maxRate = internals.maxRate; @@ -8500,16 +8532,14 @@ class AxiosTransformStream extends stream__default["default"].Transform{ const bytesThreshold = (maxRate / divider); const minChunkSize = internals.minChunkSize !== false ? Math.max(internals.minChunkSize, bytesThreshold * 0.01) : 0; - function pushChunk(_chunk, _callback) { + const pushChunk = (_chunk, _callback) => { const bytes = Buffer.byteLength(_chunk); internals.bytesSeen += bytes; internals.bytes += bytes; - if (internals.isCaptured) { - internals.updateProgress(); - } + internals.isCaptured && this.emit('progress', internals.bytesSeen); - if (self.push(_chunk)) { + if (this.push(_chunk)) { process.nextTick(_callback); } else { internals.onReadCallback = () => { @@ -8517,7 +8547,7 @@ class AxiosTransformStream extends stream__default["default"].Transform{ process.nextTick(_callback); }; } - } + }; const transformChunk = (_chunk, _callback) => { const chunkSize = Buffer.byteLength(_chunk); @@ -8574,11 +8604,6 @@ class AxiosTransformStream extends stream__default["default"].Transform{ } }); } - - setLength(length) { - this[kInternals].length = +length; - return this; - } } const AxiosTransformStream$1 = AxiosTransformStream; @@ -8599,7 +8624,7 @@ const readBlob = async function* (blob) { const readBlob$1 = readBlob; -const BOUNDARY_ALPHABET = utils.ALPHABET.ALPHA_DIGIT + '-_'; +const BOUNDARY_ALPHABET = utils$1.ALPHABET.ALPHA_DIGIT + '-_'; const textEncoder = new util.TextEncoder(); @@ -8610,7 +8635,7 @@ const CRLF_BYTES_COUNT = 2; class FormDataPart { constructor(name, value) { const {escapeName} = this.constructor; - const isStringValue = utils.isString(value); + const isStringValue = utils$1.isString(value); let headers = `Content-Disposition: form-data; name="${escapeName(name)}"${ !isStringValue && value.name ? `; filename="${escapeName(value.name)}"` : '' @@ -8637,7 +8662,7 @@ class FormDataPart { const {value} = this; - if(utils.isTypedArray(value)) { + if(utils$1.isTypedArray(value)) { yield value; } else { yield* readBlob$1(value); @@ -8659,10 +8684,10 @@ const formDataToStream = (form, headersHandler, options) => { const { tag = 'form-data-boundary', size = 25, - boundary = tag + '-' + utils.generateString(size, BOUNDARY_ALPHABET) + boundary = tag + '-' + utils$1.generateString(size, BOUNDARY_ALPHABET) } = options || {}; - if(!utils.isFormData(form)) { + if(!utils$1.isFormData(form)) { throw TypeError('FormData instance required'); } @@ -8682,7 +8707,7 @@ const formDataToStream = (form, headersHandler, options) => { contentLength += boundaryBytes.byteLength * parts.length; - contentLength = utils.toFiniteNumber(contentLength); + contentLength = utils$1.toFiniteNumber(contentLength); const computedHeaders = { 'Content-Type': `multipart/form-data; boundary=${boundary}` @@ -8732,7 +8757,7 @@ class ZlibHeaderTransformStream extends stream__default["default"].Transform { const ZlibHeaderTransformStream$1 = ZlibHeaderTransformStream; const callbackify = (fn, reducer) => { - return utils.isAsyncFn(fn) ? function (...args) { + return utils$1.isAsyncFn(fn) ? function (...args) { const cb = args.pop(); fn.apply(this, args).then((value) => { try { @@ -8746,68 +8771,212 @@ const callbackify = (fn, reducer) => { const callbackify$1 = callbackify; -const zlibOptions = { - flush: zlib__default["default"].constants.Z_SYNC_FLUSH, - finishFlush: zlib__default["default"].constants.Z_SYNC_FLUSH -}; +/** + * Calculate data maxRate + * @param {Number} [samplesCount= 10] + * @param {Number} [min= 1000] + * @returns {Function} + */ +function speedometer(samplesCount, min) { + samplesCount = samplesCount || 10; + const bytes = new Array(samplesCount); + const timestamps = new Array(samplesCount); + let head = 0; + let tail = 0; + let firstSampleTS; -const brotliOptions = { - flush: zlib__default["default"].constants.BROTLI_OPERATION_FLUSH, - finishFlush: zlib__default["default"].constants.BROTLI_OPERATION_FLUSH -}; + min = min !== undefined ? min : 1000; -const isBrotliSupported = utils.isFunction(zlib__default["default"].createBrotliDecompress); + return function push(chunkLength) { + const now = Date.now(); -const {http: httpFollow, https: httpsFollow} = followRedirects__default["default"]; + const startedAt = timestamps[tail]; -const isHttps = /https:?/; + if (!firstSampleTS) { + firstSampleTS = now; + } -const supportedProtocols = platform.protocols.map(protocol => { - return protocol + ':'; -}); + bytes[head] = chunkLength; + timestamps[head] = now; -/** - * If the proxy or config beforeRedirects functions are defined, call them with the options - * object. - * - * @param {Object} options - The options object that was passed to the request. - * - * @returns {Object} - */ -function dispatchBeforeRedirect(options) { - if (options.beforeRedirects.proxy) { - options.beforeRedirects.proxy(options); - } - if (options.beforeRedirects.config) { - options.beforeRedirects.config(options); - } -} + let i = tail; + let bytesCount = 0; -/** - * If the proxy or config afterRedirects functions are defined, call them with the options - * - * @param {http.ClientRequestArgs} options - * @param {AxiosProxyConfig} configProxy configuration from Axios options object - * @param {string} location - * - * @returns {http.ClientRequestArgs} - */ -function setProxy(options, configProxy, location) { - let proxy = configProxy; - if (!proxy && proxy !== false) { - const proxyUrl = proxyFromEnv.getProxyForUrl(location); - if (proxyUrl) { - proxy = new URL(proxyUrl); - } - } - if (proxy) { - // Basic proxy authorization - if (proxy.username) { - proxy.auth = (proxy.username || '') + ':' + (proxy.password || ''); + while (i !== head) { + bytesCount += bytes[i++]; + i = i % samplesCount; } - if (proxy.auth) { - // Support proxy auth object form + head = (head + 1) % samplesCount; + + if (head === tail) { + tail = (tail + 1) % samplesCount; + } + + if (now - firstSampleTS < min) { + return; + } + + const passed = startedAt && now - startedAt; + + return passed ? Math.round(bytesCount * 1000 / passed) : undefined; + }; +} + +/** + * Throttle decorator + * @param {Function} fn + * @param {Number} freq + * @return {Function} + */ +function throttle(fn, freq) { + let timestamp = 0; + let threshold = 1000 / freq; + let lastArgs; + let timer; + + const invoke = (args, now = Date.now()) => { + timestamp = now; + lastArgs = null; + if (timer) { + clearTimeout(timer); + timer = null; + } + fn.apply(null, args); + }; + + const throttled = (...args) => { + const now = Date.now(); + const passed = now - timestamp; + if ( passed >= threshold) { + invoke(args, now); + } else { + lastArgs = args; + if (!timer) { + timer = setTimeout(() => { + timer = null; + invoke(lastArgs); + }, threshold - passed); + } + } + }; + + const flush = () => lastArgs && invoke(lastArgs); + + return [throttled, flush]; +} + +const progressEventReducer = (listener, isDownloadStream, freq = 3) => { + let bytesNotified = 0; + const _speedometer = speedometer(50, 250); + + return throttle(e => { + const loaded = e.loaded; + const total = e.lengthComputable ? e.total : undefined; + const progressBytes = loaded - bytesNotified; + const rate = _speedometer(progressBytes); + const inRange = loaded <= total; + + bytesNotified = loaded; + + const data = { + loaded, + total, + progress: total ? (loaded / total) : undefined, + bytes: progressBytes, + rate: rate ? rate : undefined, + estimated: rate && total && inRange ? (total - loaded) / rate : undefined, + event: e, + lengthComputable: total != null, + [isDownloadStream ? 'download' : 'upload']: true + }; + + listener(data); + }, freq); +}; + +const progressEventDecorator = (total, throttled) => { + const lengthComputable = total != null; + + return [(loaded) => throttled[0]({ + lengthComputable, + total, + loaded + }), throttled[1]]; +}; + +const asyncDecorator = (fn) => (...args) => utils$1.asap(() => fn(...args)); + +const zlibOptions = { + flush: zlib__default["default"].constants.Z_SYNC_FLUSH, + finishFlush: zlib__default["default"].constants.Z_SYNC_FLUSH +}; + +const brotliOptions = { + flush: zlib__default["default"].constants.BROTLI_OPERATION_FLUSH, + finishFlush: zlib__default["default"].constants.BROTLI_OPERATION_FLUSH +}; + +const isBrotliSupported = utils$1.isFunction(zlib__default["default"].createBrotliDecompress); + +const {http: httpFollow, https: httpsFollow} = followRedirects__default["default"]; + +const isHttps = /https:?/; + +const supportedProtocols = platform.protocols.map(protocol => { + return protocol + ':'; +}); + +const flushOnFinish = (stream, [throttled, flush]) => { + stream + .on('end', flush) + .on('error', flush); + + return throttled; +}; + +/** + * If the proxy or config beforeRedirects functions are defined, call them with the options + * object. + * + * @param {Object} options - The options object that was passed to the request. + * + * @returns {Object} + */ +function dispatchBeforeRedirect(options, responseDetails) { + if (options.beforeRedirects.proxy) { + options.beforeRedirects.proxy(options); + } + if (options.beforeRedirects.config) { + options.beforeRedirects.config(options, responseDetails); + } +} + +/** + * If the proxy or config afterRedirects functions are defined, call them with the options + * + * @param {http.ClientRequestArgs} options + * @param {AxiosProxyConfig} configProxy configuration from Axios options object + * @param {string} location + * + * @returns {http.ClientRequestArgs} + */ +function setProxy(options, configProxy, location) { + let proxy = configProxy; + if (!proxy && proxy !== false) { + const proxyUrl = proxyFromEnv.getProxyForUrl(location); + if (proxyUrl) { + proxy = new URL(proxyUrl); + } + } + if (proxy) { + // Basic proxy authorization + if (proxy.username) { + proxy.auth = (proxy.username || '') + ':' + (proxy.password || ''); + } + + if (proxy.auth) { + // Support proxy auth object form if (proxy.auth.username || proxy.auth.password) { proxy.auth = (proxy.auth.username || '') + ':' + (proxy.auth.password || ''); } @@ -8836,7 +9005,7 @@ function setProxy(options, configProxy, location) { }; } -const isHttpAdapterSupported = typeof process !== 'undefined' && utils.kindOf(process) === 'process'; +const isHttpAdapterSupported = typeof process !== 'undefined' && utils$1.kindOf(process) === 'process'; // temporary hotfix @@ -8865,6 +9034,18 @@ const wrapAsync = (asyncExecutor) => { }) }; +const resolveFamily = ({address, family}) => { + if (!utils$1.isString(address)) { + throw TypeError('address must be a string'); + } + return ({ + address, + family: family || (address.indexOf('.') < 0 ? 6 : 4) + }); +}; + +const buildAddressEntry = (address, family) => resolveFamily(utils$1.isObject(address) ? address : {address, family}); + /*eslint consistent-return:0*/ const httpAdapter = isHttpAdapterSupported && function httpAdapter(config) { return wrapAsync(async function dispatchHttpRequest(resolve, reject, onDone) { @@ -8875,19 +9056,24 @@ const httpAdapter = isHttpAdapterSupported && function httpAdapter(config) { let rejected = false; let req; - if (lookup && utils.isAsyncFn(lookup)) { - lookup = callbackify$1(lookup, (entry) => { - if(utils.isString(entry)) { - entry = [entry, entry.indexOf('.') < 0 ? 6 : 4]; - } else if (!utils.isArray(entry)) { - throw new TypeError('lookup async function must return an array [ip: string, family: number]]') - } - return entry; - }); + if (lookup) { + const _lookup = callbackify$1(lookup, (value) => utils$1.isArray(value) ? value : [value]); + // hotfix to support opt.all option which is required for node 20.x + lookup = (hostname, opt, cb) => { + _lookup(hostname, opt, (err, arg0, arg1) => { + if (err) { + return cb(err); + } + + const addresses = utils$1.isArray(arg0) ? arg0.map(addr => buildAddressEntry(addr)) : [buildAddressEntry(arg0, arg1)]; + + opt.all ? cb(err, addresses) : cb(err, addresses[0].address, addresses[0].family); + }); + }; } // temporary internal emitter until the AxiosRequest class will be implemented - const emitter = new EventEmitter__default["default"](); + const emitter = new events.EventEmitter(); const onFinished = () => { if (config.cancelToken) { @@ -8924,7 +9110,7 @@ const httpAdapter = isHttpAdapterSupported && function httpAdapter(config) { // Parse url const fullPath = buildFullPath(config.baseURL, config.url); - const parsed = new URL(fullPath, 'http://localhost'); + const parsed = new URL(fullPath, utils$1.hasBrowserEnv ? platform.origin : undefined); const protocol = parsed.protocol || supportedProtocols[0]; if (protocol === 'data:') { @@ -8951,7 +9137,7 @@ const httpAdapter = isHttpAdapterSupported && function httpAdapter(config) { convertedData = convertedData.toString(responseEncoding); if (!responseEncoding || responseEncoding === 'utf8') { - convertedData = utils.stripBOM(convertedData); + convertedData = utils$1.stripBOM(convertedData); } } else if (responseType === 'stream') { convertedData = stream__default["default"].Readable.from(convertedData); @@ -8982,14 +9168,13 @@ const httpAdapter = isHttpAdapterSupported && function httpAdapter(config) { // Only set header if it hasn't been set in config headers.set('User-Agent', 'axios/' + VERSION, false); - const onDownloadProgress = config.onDownloadProgress; - const onUploadProgress = config.onUploadProgress; + const {onUploadProgress, onDownloadProgress} = config; const maxRate = config.maxRate; let maxUploadRate = undefined; let maxDownloadRate = undefined; // support for spec compliant FormData objects - if (utils.isSpecCompliantForm(data)) { + if (utils$1.isSpecCompliantForm(data)) { const userBoundary = headers.getContentType(/boundary=([-_\w\d]{10,70})/i); data = formDataToStream$1(data, (formHeaders) => { @@ -8999,7 +9184,7 @@ const httpAdapter = isHttpAdapterSupported && function httpAdapter(config) { boundary: userBoundary && userBoundary[1] || undefined }); // support for https://www.npmjs.com/package/form-data api - } else if (utils.isFormData(data) && utils.isFunction(data.getHeaders)) { + } else if (utils$1.isFormData(data) && utils$1.isFunction(data.getHeaders)) { headers.set(data.getHeaders()); if (!headers.hasContentLength()) { @@ -9010,14 +9195,14 @@ const httpAdapter = isHttpAdapterSupported && function httpAdapter(config) { } catch (e) { } } - } else if (utils.isBlob(data)) { + } else if (utils$1.isBlob(data)) { data.size && headers.setContentType(data.type || 'application/octet-stream'); headers.setContentLength(data.size || 0); data = stream__default["default"].Readable.from(readBlob$1(data)); - } else if (data && !utils.isStream(data)) { - if (Buffer.isBuffer(data)) ; else if (utils.isArrayBuffer(data)) { + } else if (data && !utils$1.isStream(data)) { + if (Buffer.isBuffer(data)) ; else if (utils$1.isArrayBuffer(data)) { data = Buffer.from(new Uint8Array(data)); - } else if (utils.isString(data)) { + } else if (utils$1.isString(data)) { data = Buffer.from(data, 'utf-8'); } else { return reject(new AxiosError( @@ -9039,9 +9224,9 @@ const httpAdapter = isHttpAdapterSupported && function httpAdapter(config) { } } - const contentLength = utils.toFiniteNumber(headers.getContentLength()); + const contentLength = utils$1.toFiniteNumber(headers.getContentLength()); - if (utils.isArray(maxRate)) { + if (utils$1.isArray(maxRate)) { maxUploadRate = maxRate[0]; maxDownloadRate = maxRate[1]; } else { @@ -9049,20 +9234,21 @@ const httpAdapter = isHttpAdapterSupported && function httpAdapter(config) { } if (data && (onUploadProgress || maxUploadRate)) { - if (!utils.isStream(data)) { + if (!utils$1.isStream(data)) { data = stream__default["default"].Readable.from(data, {objectMode: false}); } data = stream__default["default"].pipeline([data, new AxiosTransformStream$1({ - length: contentLength, - maxRate: utils.toFiniteNumber(maxUploadRate) - })], utils.noop); - - onUploadProgress && data.on('progress', progress => { - onUploadProgress(Object.assign(progress, { - upload: true - })); - }); + maxRate: utils$1.toFiniteNumber(maxUploadRate) + })], utils$1.noop); + + onUploadProgress && data.on('progress', flushOnFinish( + data, + progressEventDecorator( + contentLength, + progressEventReducer(asyncDecorator(onUploadProgress), false, 3) + ) + )); } // HTTP basic authentication @@ -9115,7 +9301,7 @@ const httpAdapter = isHttpAdapterSupported && function httpAdapter(config) { }; // cacheable-lookup integration hotfix - !utils.isUndefined(lookup) && (options.lookup = lookup); + !utils$1.isUndefined(lookup) && (options.lookup = lookup); if (config.socketPath) { options.socketPath = config.socketPath; @@ -9161,17 +9347,18 @@ const httpAdapter = isHttpAdapterSupported && function httpAdapter(config) { const responseLength = +res.headers['content-length']; - if (onDownloadProgress) { + if (onDownloadProgress || maxDownloadRate) { const transformStream = new AxiosTransformStream$1({ - length: utils.toFiniteNumber(responseLength), - maxRate: utils.toFiniteNumber(maxDownloadRate) + maxRate: utils$1.toFiniteNumber(maxDownloadRate) }); - onDownloadProgress && transformStream.on('progress', progress => { - onDownloadProgress(Object.assign(progress, { - download: true - })); - }); + onDownloadProgress && transformStream.on('progress', flushOnFinish( + transformStream, + progressEventDecorator( + responseLength, + progressEventReducer(asyncDecorator(onDownloadProgress), true, 3) + ) + )); streams.push(transformStream); } @@ -9190,7 +9377,7 @@ const httpAdapter = isHttpAdapterSupported && function httpAdapter(config) { delete res.headers['content-encoding']; } - switch (res.headers['content-encoding']) { + switch ((res.headers['content-encoding'] || '').toLowerCase()) { /*eslint default-case:0*/ case 'gzip': case 'x-gzip': @@ -9219,7 +9406,7 @@ const httpAdapter = isHttpAdapterSupported && function httpAdapter(config) { } } - responseStream = streams.length > 1 ? stream__default["default"].pipeline(streams, utils.noop) : streams[0]; + responseStream = streams.length > 1 ? stream__default["default"].pipeline(streams, utils$1.noop) : streams[0]; const offListeners = stream__default["default"].finished(responseStream, () => { offListeners(); @@ -9281,12 +9468,12 @@ const httpAdapter = isHttpAdapterSupported && function httpAdapter(config) { if (responseType !== 'arraybuffer') { responseData = responseData.toString(responseEncoding); if (!responseEncoding || responseEncoding === 'utf8') { - responseData = utils.stripBOM(responseData); + responseData = utils$1.stripBOM(responseData); } } response.data = responseData; } catch (err) { - reject(AxiosError.from(err, null, config, response.request, response)); + return reject(AxiosError.from(err, null, config, response.request, response)); } settle(resolve, reject, response); }); @@ -9323,7 +9510,7 @@ const httpAdapter = isHttpAdapterSupported && function httpAdapter(config) { // This is forcing a int timeout to avoid problems if the `req` interface doesn't handle other types. const timeout = parseInt(config.timeout, 10); - if (isNaN(timeout)) { + if (Number.isNaN(timeout)) { reject(new AxiosError( 'error trying to parse `config.timeout` to int', AxiosError.ERR_BAD_OPTION_VALUE, @@ -9358,7 +9545,7 @@ const httpAdapter = isHttpAdapterSupported && function httpAdapter(config) { // Send the request - if (utils.isStream(data)) { + if (utils$1.isStream(data)) { let ended = false; let errored = false; @@ -9384,55 +9571,7 @@ const httpAdapter = isHttpAdapterSupported && function httpAdapter(config) { }); }; -const cookies = platform.isStandardBrowserEnv ? - -// Standard browser envs support document.cookie - (function standardBrowserEnv() { - return { - write: function write(name, value, expires, path, domain, secure) { - const cookie = []; - cookie.push(name + '=' + encodeURIComponent(value)); - - if (utils.isNumber(expires)) { - cookie.push('expires=' + new Date(expires).toGMTString()); - } - - if (utils.isString(path)) { - cookie.push('path=' + path); - } - - if (utils.isString(domain)) { - cookie.push('domain=' + domain); - } - - if (secure === true) { - cookie.push('secure'); - } - - document.cookie = cookie.join('; '); - }, - - read: function read(name) { - const match = document.cookie.match(new RegExp('(^|;\\s*)(' + name + ')=([^;]*)')); - return (match ? decodeURIComponent(match[3]) : null); - }, - - remove: function remove(name) { - this.write(name, '', Date.now() - 86400000); - } - }; - })() : - -// Non standard browser env (web workers, react-native) lack needed support. - (function nonStandardBrowserEnv() { - return { - write: function write() {}, - read: function read() { return null; }, - remove: function remove() {} - }; - })(); - -const isURLSameOrigin = platform.isStandardBrowserEnv ? +const isURLSameOrigin = platform.hasStandardBrowserEnv ? // Standard browser envs have full support of the APIs needed to test // whether the request URL is of the same origin as current location. @@ -9442,7 +9581,7 @@ const isURLSameOrigin = platform.isStandardBrowserEnv ? let originURL; /** - * Parse a URL to discover it's components + * Parse a URL to discover its components * * @param {String} url The URL to be parsed * @returns {Object} @@ -9482,7 +9621,7 @@ const isURLSameOrigin = platform.isStandardBrowserEnv ? * @returns {boolean} True if URL shares the same origin, otherwise false */ return function isURLSameOrigin(requestURL) { - const parsed = (utils.isString(requestURL)) ? resolveURL(requestURL) : requestURL; + const parsed = (utils$1.isString(requestURL)) ? resolveURL(requestURL) : requestURL; return (parsed.protocol === originURL.protocol && parsed.host === originURL.host); }; @@ -9495,97 +9634,243 @@ const isURLSameOrigin = platform.isStandardBrowserEnv ? }; })(); -function progressEventReducer(listener, isDownloadStream) { - let bytesNotified = 0; - const _speedometer = speedometer(50, 250); +const cookies = platform.hasStandardBrowserEnv ? - return e => { - const loaded = e.loaded; - const total = e.lengthComputable ? e.total : undefined; - const progressBytes = loaded - bytesNotified; - const rate = _speedometer(progressBytes); - const inRange = loaded <= total; + // Standard browser envs support document.cookie + { + write(name, value, expires, path, domain, secure) { + const cookie = [name + '=' + encodeURIComponent(value)]; - bytesNotified = loaded; + utils$1.isNumber(expires) && cookie.push('expires=' + new Date(expires).toGMTString()); - const data = { - loaded, - total, - progress: total ? (loaded / total) : undefined, - bytes: progressBytes, - rate: rate ? rate : undefined, - estimated: rate && total && inRange ? (total - loaded) / rate : undefined, - event: e - }; + utils$1.isString(path) && cookie.push('path=' + path); - data[isDownloadStream ? 'download' : 'upload'] = true; + utils$1.isString(domain) && cookie.push('domain=' + domain); - listener(data); - }; -} + secure === true && cookie.push('secure'); -const isXHRAdapterSupported = typeof XMLHttpRequest !== 'undefined'; + document.cookie = cookie.join('; '); + }, -const xhrAdapter = isXHRAdapterSupported && function (config) { - return new Promise(function dispatchXhrRequest(resolve, reject) { - let requestData = config.data; - const requestHeaders = AxiosHeaders$1.from(config.headers).normalize(); - const responseType = config.responseType; - let onCanceled; - function done() { - if (config.cancelToken) { - config.cancelToken.unsubscribe(onCanceled); - } + read(name) { + const match = document.cookie.match(new RegExp('(^|;\\s*)(' + name + ')=([^;]*)')); + return (match ? decodeURIComponent(match[3]) : null); + }, - if (config.signal) { - config.signal.removeEventListener('abort', onCanceled); - } + remove(name) { + this.write(name, '', Date.now() - 86400000); } + } - if (utils.isFormData(requestData)) { - if (platform.isStandardBrowserEnv || platform.isStandardBrowserWebWorkerEnv) { - requestHeaders.setContentType(false); // Let the browser set it - } else { - requestHeaders.setContentType('multipart/form-data;', false); // mobile/desktop app frameworks - } - } + : - let request = new XMLHttpRequest(); + // Non-standard browser env (web workers, react-native) lack needed support. + { + write() {}, + read() { + return null; + }, + remove() {} + }; - // HTTP basic authentication - if (config.auth) { - const username = config.auth.username || ''; - const password = config.auth.password ? unescape(encodeURIComponent(config.auth.password)) : ''; - requestHeaders.set('Authorization', 'Basic ' + btoa(username + ':' + password)); - } +const headersToObject = (thing) => thing instanceof AxiosHeaders$1 ? { ...thing } : thing; - const fullPath = buildFullPath(config.baseURL, config.url); +/** + * Config-specific merge-function which creates a new config-object + * by merging two configuration objects together. + * + * @param {Object} config1 + * @param {Object} config2 + * + * @returns {Object} New object resulting from merging config2 to config1 + */ +function mergeConfig(config1, config2) { + // eslint-disable-next-line no-param-reassign + config2 = config2 || {}; + const config = {}; - request.open(config.method.toUpperCase(), buildURL(fullPath, config.params, config.paramsSerializer), true); + function getMergedValue(target, source, caseless) { + if (utils$1.isPlainObject(target) && utils$1.isPlainObject(source)) { + return utils$1.merge.call({caseless}, target, source); + } else if (utils$1.isPlainObject(source)) { + return utils$1.merge({}, source); + } else if (utils$1.isArray(source)) { + return source.slice(); + } + return source; + } - // Set the request timeout in MS - request.timeout = config.timeout; + // eslint-disable-next-line consistent-return + function mergeDeepProperties(a, b, caseless) { + if (!utils$1.isUndefined(b)) { + return getMergedValue(a, b, caseless); + } else if (!utils$1.isUndefined(a)) { + return getMergedValue(undefined, a, caseless); + } + } - function onloadend() { - if (!request) { - return; - } - // Prepare the response - const responseHeaders = AxiosHeaders$1.from( - 'getAllResponseHeaders' in request && request.getAllResponseHeaders() - ); - const responseData = !responseType || responseType === 'text' || responseType === 'json' ? - request.responseText : request.response; - const response = { - data: responseData, - status: request.status, - statusText: request.statusText, - headers: responseHeaders, - config, - request - }; + // eslint-disable-next-line consistent-return + function valueFromConfig2(a, b) { + if (!utils$1.isUndefined(b)) { + return getMergedValue(undefined, b); + } + } - settle(function _resolve(value) { + // eslint-disable-next-line consistent-return + function defaultToConfig2(a, b) { + if (!utils$1.isUndefined(b)) { + return getMergedValue(undefined, b); + } else if (!utils$1.isUndefined(a)) { + return getMergedValue(undefined, a); + } + } + + // eslint-disable-next-line consistent-return + function mergeDirectKeys(a, b, prop) { + if (prop in config2) { + return getMergedValue(a, b); + } else if (prop in config1) { + return getMergedValue(undefined, a); + } + } + + const mergeMap = { + url: valueFromConfig2, + method: valueFromConfig2, + data: valueFromConfig2, + baseURL: defaultToConfig2, + transformRequest: defaultToConfig2, + transformResponse: defaultToConfig2, + paramsSerializer: defaultToConfig2, + timeout: defaultToConfig2, + timeoutMessage: defaultToConfig2, + withCredentials: defaultToConfig2, + withXSRFToken: defaultToConfig2, + adapter: defaultToConfig2, + responseType: defaultToConfig2, + xsrfCookieName: defaultToConfig2, + xsrfHeaderName: defaultToConfig2, + onUploadProgress: defaultToConfig2, + onDownloadProgress: defaultToConfig2, + decompress: defaultToConfig2, + maxContentLength: defaultToConfig2, + maxBodyLength: defaultToConfig2, + beforeRedirect: defaultToConfig2, + transport: defaultToConfig2, + httpAgent: defaultToConfig2, + httpsAgent: defaultToConfig2, + cancelToken: defaultToConfig2, + socketPath: defaultToConfig2, + responseEncoding: defaultToConfig2, + validateStatus: mergeDirectKeys, + headers: (a, b) => mergeDeepProperties(headersToObject(a), headersToObject(b), true) + }; + + utils$1.forEach(Object.keys(Object.assign({}, config1, config2)), function computeConfigValue(prop) { + const merge = mergeMap[prop] || mergeDeepProperties; + const configValue = merge(config1[prop], config2[prop], prop); + (utils$1.isUndefined(configValue) && merge !== mergeDirectKeys) || (config[prop] = configValue); + }); + + return config; +} + +const resolveConfig = (config) => { + const newConfig = mergeConfig({}, config); + + let {data, withXSRFToken, xsrfHeaderName, xsrfCookieName, headers, auth} = newConfig; + + newConfig.headers = headers = AxiosHeaders$1.from(headers); + + newConfig.url = buildURL(buildFullPath(newConfig.baseURL, newConfig.url), config.params, config.paramsSerializer); + + // HTTP basic authentication + if (auth) { + headers.set('Authorization', 'Basic ' + + btoa((auth.username || '') + ':' + (auth.password ? unescape(encodeURIComponent(auth.password)) : '')) + ); + } + + let contentType; + + if (utils$1.isFormData(data)) { + if (platform.hasStandardBrowserEnv || platform.hasStandardBrowserWebWorkerEnv) { + headers.setContentType(undefined); // Let the browser set it + } else if ((contentType = headers.getContentType()) !== false) { + // fix semicolon duplication issue for ReactNative FormData implementation + const [type, ...tokens] = contentType ? contentType.split(';').map(token => token.trim()).filter(Boolean) : []; + headers.setContentType([type || 'multipart/form-data', ...tokens].join('; ')); + } + } + + // Add xsrf header + // This is only done if running in a standard browser environment. + // Specifically not if we're in a web worker, or react-native. + + if (platform.hasStandardBrowserEnv) { + withXSRFToken && utils$1.isFunction(withXSRFToken) && (withXSRFToken = withXSRFToken(newConfig)); + + if (withXSRFToken || (withXSRFToken !== false && isURLSameOrigin(newConfig.url))) { + // Add xsrf header + const xsrfValue = xsrfHeaderName && xsrfCookieName && cookies.read(xsrfCookieName); + + if (xsrfValue) { + headers.set(xsrfHeaderName, xsrfValue); + } + } + } + + return newConfig; +}; + +const isXHRAdapterSupported = typeof XMLHttpRequest !== 'undefined'; + +const xhrAdapter = isXHRAdapterSupported && function (config) { + return new Promise(function dispatchXhrRequest(resolve, reject) { + const _config = resolveConfig(config); + let requestData = _config.data; + const requestHeaders = AxiosHeaders$1.from(_config.headers).normalize(); + let {responseType, onUploadProgress, onDownloadProgress} = _config; + let onCanceled; + let uploadThrottled, downloadThrottled; + let flushUpload, flushDownload; + + function done() { + flushUpload && flushUpload(); // flush events + flushDownload && flushDownload(); // flush events + + _config.cancelToken && _config.cancelToken.unsubscribe(onCanceled); + + _config.signal && _config.signal.removeEventListener('abort', onCanceled); + } + + let request = new XMLHttpRequest(); + + request.open(_config.method.toUpperCase(), _config.url, true); + + // Set the request timeout in MS + request.timeout = _config.timeout; + + function onloadend() { + if (!request) { + return; + } + // Prepare the response + const responseHeaders = AxiosHeaders$1.from( + 'getAllResponseHeaders' in request && request.getAllResponseHeaders() + ); + const responseData = !responseType || responseType === 'text' || responseType === 'json' ? + request.responseText : request.response; + const response = { + data: responseData, + status: request.status, + statusText: request.statusText, + headers: responseHeaders, + config, + request + }; + + settle(function _resolve(value) { resolve(value); done(); }, function _reject(err) { @@ -9644,10 +9929,10 @@ const xhrAdapter = isXHRAdapterSupported && function (config) { // Handle timeout request.ontimeout = function handleTimeout() { - let timeoutErrorMessage = config.timeout ? 'timeout of ' + config.timeout + 'ms exceeded' : 'timeout exceeded'; - const transitional = config.transitional || transitionalDefaults; - if (config.timeoutErrorMessage) { - timeoutErrorMessage = config.timeoutErrorMessage; + let timeoutErrorMessage = _config.timeout ? 'timeout of ' + _config.timeout + 'ms exceeded' : 'timeout exceeded'; + const transitional = _config.transitional || transitionalDefaults; + if (_config.timeoutErrorMessage) { + timeoutErrorMessage = _config.timeoutErrorMessage; } reject(new AxiosError( timeoutErrorMessage, @@ -9659,50 +9944,42 @@ const xhrAdapter = isXHRAdapterSupported && function (config) { request = null; }; - // Add xsrf header - // This is only done if running in a standard browser environment. - // Specifically not if we're in a web worker, or react-native. - if (platform.isStandardBrowserEnv) { - // Add xsrf header - const xsrfValue = (config.withCredentials || isURLSameOrigin(fullPath)) - && config.xsrfCookieName && cookies.read(config.xsrfCookieName); - - if (xsrfValue) { - requestHeaders.set(config.xsrfHeaderName, xsrfValue); - } - } - // Remove Content-Type if data is undefined requestData === undefined && requestHeaders.setContentType(null); // Add headers to the request if ('setRequestHeader' in request) { - utils.forEach(requestHeaders.toJSON(), function setRequestHeader(val, key) { + utils$1.forEach(requestHeaders.toJSON(), function setRequestHeader(val, key) { request.setRequestHeader(key, val); }); } // Add withCredentials to request if needed - if (!utils.isUndefined(config.withCredentials)) { - request.withCredentials = !!config.withCredentials; + if (!utils$1.isUndefined(_config.withCredentials)) { + request.withCredentials = !!_config.withCredentials; } // Add responseType to request if needed if (responseType && responseType !== 'json') { - request.responseType = config.responseType; + request.responseType = _config.responseType; } // Handle progress if needed - if (typeof config.onDownloadProgress === 'function') { - request.addEventListener('progress', progressEventReducer(config.onDownloadProgress, true)); + if (onDownloadProgress) { + ([downloadThrottled, flushDownload] = progressEventReducer(onDownloadProgress, true)); + request.addEventListener('progress', downloadThrottled); } // Not all browsers support upload events - if (typeof config.onUploadProgress === 'function' && request.upload) { - request.upload.addEventListener('progress', progressEventReducer(config.onUploadProgress)); + if (onUploadProgress && request.upload) { + ([uploadThrottled, flushUpload] = progressEventReducer(onUploadProgress)); + + request.upload.addEventListener('progress', uploadThrottled); + + request.upload.addEventListener('loadend', flushUpload); } - if (config.cancelToken || config.signal) { + if (_config.cancelToken || _config.signal) { // Handle cancellation // eslint-disable-next-line func-names onCanceled = cancel => { @@ -9714,13 +9991,13 @@ const xhrAdapter = isXHRAdapterSupported && function (config) { request = null; }; - config.cancelToken && config.cancelToken.subscribe(onCanceled); - if (config.signal) { - config.signal.aborted ? onCanceled() : config.signal.addEventListener('abort', onCanceled); + _config.cancelToken && _config.cancelToken.subscribe(onCanceled); + if (_config.signal) { + _config.signal.aborted ? onCanceled() : _config.signal.addEventListener('abort', onCanceled); } } - const protocol = parseProtocol(fullPath); + const protocol = parseProtocol(_config.url); if (protocol && platform.protocols.indexOf(protocol) === -1) { reject(new AxiosError('Unsupported protocol ' + protocol + ':', AxiosError.ERR_BAD_REQUEST, config)); @@ -9733,13 +10010,343 @@ const xhrAdapter = isXHRAdapterSupported && function (config) { }); }; +const composeSignals = (signals, timeout) => { + let controller = new AbortController(); + + let aborted; + + const onabort = function (cancel) { + if (!aborted) { + aborted = true; + unsubscribe(); + const err = cancel instanceof Error ? cancel : this.reason; + controller.abort(err instanceof AxiosError ? err : new CanceledError(err instanceof Error ? err.message : err)); + } + }; + + let timer = timeout && setTimeout(() => { + onabort(new AxiosError(`timeout ${timeout} of ms exceeded`, AxiosError.ETIMEDOUT)); + }, timeout); + + const unsubscribe = () => { + if (signals) { + timer && clearTimeout(timer); + timer = null; + signals.forEach(signal => { + signal && + (signal.removeEventListener ? signal.removeEventListener('abort', onabort) : signal.unsubscribe(onabort)); + }); + signals = null; + } + }; + + signals.forEach((signal) => signal && signal.addEventListener && signal.addEventListener('abort', onabort)); + + const {signal} = controller; + + signal.unsubscribe = unsubscribe; + + return [signal, () => { + timer && clearTimeout(timer); + timer = null; + }]; +}; + +const composeSignals$1 = composeSignals; + +const streamChunk = function* (chunk, chunkSize) { + let len = chunk.byteLength; + + if (!chunkSize || len < chunkSize) { + yield chunk; + return; + } + + let pos = 0; + let end; + + while (pos < len) { + end = pos + chunkSize; + yield chunk.slice(pos, end); + pos = end; + } +}; + +const readBytes = async function* (iterable, chunkSize, encode) { + for await (const chunk of iterable) { + yield* streamChunk(ArrayBuffer.isView(chunk) ? chunk : (await encode(String(chunk))), chunkSize); + } +}; + +const trackStream = (stream, chunkSize, onProgress, onFinish, encode) => { + const iterator = readBytes(stream, chunkSize, encode); + + let bytes = 0; + let done; + let _onFinish = (e) => { + if (!done) { + done = true; + onFinish && onFinish(e); + } + }; + + return new ReadableStream({ + async pull(controller) { + try { + const {done, value} = await iterator.next(); + + if (done) { + _onFinish(); + controller.close(); + return; + } + + let len = value.byteLength; + if (onProgress) { + let loadedBytes = bytes += len; + onProgress(loadedBytes); + } + controller.enqueue(new Uint8Array(value)); + } catch (err) { + _onFinish(err); + throw err; + } + }, + cancel(reason) { + _onFinish(reason); + return iterator.return(); + } + }, { + highWaterMark: 2 + }) +}; + +const isFetchSupported = typeof fetch === 'function' && typeof Request === 'function' && typeof Response === 'function'; +const isReadableStreamSupported = isFetchSupported && typeof ReadableStream === 'function'; + +// used only inside the fetch adapter +const encodeText = isFetchSupported && (typeof TextEncoder === 'function' ? + ((encoder) => (str) => encoder.encode(str))(new TextEncoder()) : + async (str) => new Uint8Array(await new Response(str).arrayBuffer()) +); + +const test = (fn, ...args) => { + try { + return !!fn(...args); + } catch (e) { + return false + } +}; + +const supportsRequestStream = isReadableStreamSupported && test(() => { + let duplexAccessed = false; + + const hasContentType = new Request(platform.origin, { + body: new ReadableStream(), + method: 'POST', + get duplex() { + duplexAccessed = true; + return 'half'; + }, + }).headers.has('Content-Type'); + + return duplexAccessed && !hasContentType; +}); + +const DEFAULT_CHUNK_SIZE = 64 * 1024; + +const supportsResponseStream = isReadableStreamSupported && + test(() => utils$1.isReadableStream(new Response('').body)); + + +const resolvers = { + stream: supportsResponseStream && ((res) => res.body) +}; + +isFetchSupported && (((res) => { + ['text', 'arrayBuffer', 'blob', 'formData', 'stream'].forEach(type => { + !resolvers[type] && (resolvers[type] = utils$1.isFunction(res[type]) ? (res) => res[type]() : + (_, config) => { + throw new AxiosError(`Response type '${type}' is not supported`, AxiosError.ERR_NOT_SUPPORT, config); + }); + }); +})(new Response)); + +const getBodyLength = async (body) => { + if (body == null) { + return 0; + } + + if(utils$1.isBlob(body)) { + return body.size; + } + + if(utils$1.isSpecCompliantForm(body)) { + return (await new Request(body).arrayBuffer()).byteLength; + } + + if(utils$1.isArrayBufferView(body) || utils$1.isArrayBuffer(body)) { + return body.byteLength; + } + + if(utils$1.isURLSearchParams(body)) { + body = body + ''; + } + + if(utils$1.isString(body)) { + return (await encodeText(body)).byteLength; + } +}; + +const resolveBodyLength = async (headers, body) => { + const length = utils$1.toFiniteNumber(headers.getContentLength()); + + return length == null ? getBodyLength(body) : length; +}; + +const fetchAdapter = isFetchSupported && (async (config) => { + let { + url, + method, + data, + signal, + cancelToken, + timeout, + onDownloadProgress, + onUploadProgress, + responseType, + headers, + withCredentials = 'same-origin', + fetchOptions + } = resolveConfig(config); + + responseType = responseType ? (responseType + '').toLowerCase() : 'text'; + + let [composedSignal, stopTimeout] = (signal || cancelToken || timeout) ? + composeSignals$1([signal, cancelToken], timeout) : []; + + let finished, request; + + const onFinish = () => { + !finished && setTimeout(() => { + composedSignal && composedSignal.unsubscribe(); + }); + + finished = true; + }; + + let requestContentLength; + + try { + if ( + onUploadProgress && supportsRequestStream && method !== 'get' && method !== 'head' && + (requestContentLength = await resolveBodyLength(headers, data)) !== 0 + ) { + let _request = new Request(url, { + method: 'POST', + body: data, + duplex: "half" + }); + + let contentTypeHeader; + + if (utils$1.isFormData(data) && (contentTypeHeader = _request.headers.get('content-type'))) { + headers.setContentType(contentTypeHeader); + } + + if (_request.body) { + const [onProgress, flush] = progressEventDecorator( + requestContentLength, + progressEventReducer(asyncDecorator(onUploadProgress)) + ); + + data = trackStream(_request.body, DEFAULT_CHUNK_SIZE, onProgress, flush, encodeText); + } + } + + if (!utils$1.isString(withCredentials)) { + withCredentials = withCredentials ? 'include' : 'omit'; + } + + request = new Request(url, { + ...fetchOptions, + signal: composedSignal, + method: method.toUpperCase(), + headers: headers.normalize().toJSON(), + body: data, + duplex: "half", + credentials: withCredentials + }); + + let response = await fetch(request); + + const isStreamResponse = supportsResponseStream && (responseType === 'stream' || responseType === 'response'); + + if (supportsResponseStream && (onDownloadProgress || isStreamResponse)) { + const options = {}; + + ['status', 'statusText', 'headers'].forEach(prop => { + options[prop] = response[prop]; + }); + + const responseContentLength = utils$1.toFiniteNumber(response.headers.get('content-length')); + + const [onProgress, flush] = onDownloadProgress && progressEventDecorator( + responseContentLength, + progressEventReducer(asyncDecorator(onDownloadProgress), true) + ) || []; + + response = new Response( + trackStream(response.body, DEFAULT_CHUNK_SIZE, onProgress, () => { + flush && flush(); + isStreamResponse && onFinish(); + }, encodeText), + options + ); + } + + responseType = responseType || 'text'; + + let responseData = await resolvers[utils$1.findKey(resolvers, responseType) || 'text'](response, config); + + !isStreamResponse && onFinish(); + + stopTimeout && stopTimeout(); + + return await new Promise((resolve, reject) => { + settle(resolve, reject, { + data: responseData, + headers: AxiosHeaders$1.from(response.headers), + status: response.status, + statusText: response.statusText, + config, + request + }); + }) + } catch (err) { + onFinish(); + + if (err && err.name === 'TypeError' && /fetch/i.test(err.message)) { + throw Object.assign( + new AxiosError('Network Error', AxiosError.ERR_NETWORK, config, request), + { + cause: err.cause || err + } + ) + } + + throw AxiosError.from(err, err && err.code, config, request); + } +}); + const knownAdapters = { http: httpAdapter, - xhr: xhrAdapter + xhr: xhrAdapter, + fetch: fetchAdapter }; -utils.forEach(knownAdapters, (fn, value) => { - if(fn) { +utils$1.forEach(knownAdapters, (fn, value) => { + if (fn) { try { Object.defineProperty(fn, 'name', {value}); } catch (e) { @@ -9749,38 +10356,56 @@ utils.forEach(knownAdapters, (fn, value) => { } }); +const renderReason = (reason) => `- ${reason}`; + +const isResolvedHandle = (adapter) => utils$1.isFunction(adapter) || adapter === null || adapter === false; + const adapters = { getAdapter: (adapters) => { - adapters = utils.isArray(adapters) ? adapters : [adapters]; + adapters = utils$1.isArray(adapters) ? adapters : [adapters]; const {length} = adapters; let nameOrAdapter; let adapter; + const rejectedReasons = {}; + for (let i = 0; i < length; i++) { nameOrAdapter = adapters[i]; - if((adapter = utils.isString(nameOrAdapter) ? knownAdapters[nameOrAdapter.toLowerCase()] : nameOrAdapter)) { + let id; + + adapter = nameOrAdapter; + + if (!isResolvedHandle(nameOrAdapter)) { + adapter = knownAdapters[(id = String(nameOrAdapter)).toLowerCase()]; + + if (adapter === undefined) { + throw new AxiosError(`Unknown adapter '${id}'`); + } + } + + if (adapter) { break; } + + rejectedReasons[id || '#' + i] = adapter; } if (!adapter) { - if (adapter === false) { - throw new AxiosError( - `Adapter ${nameOrAdapter} is not supported by the environment`, - 'ERR_NOT_SUPPORT' + + const reasons = Object.entries(rejectedReasons) + .map(([id, state]) => `adapter ${id} ` + + (state === false ? 'is not supported by the environment' : 'is not available in the build') ); - } - throw new Error( - utils.hasOwnProp(knownAdapters, nameOrAdapter) ? - `Adapter '${nameOrAdapter}' is not available in the build` : - `Unknown adapter '${nameOrAdapter}'` - ); - } + let s = length ? + (reasons.length > 1 ? 'since :\n' + reasons.map(renderReason).join('\n') : ' ' + renderReason(reasons[0])) : + 'as no adapter specified'; - if (!utils.isFunction(adapter)) { - throw new TypeError('adapter is not a function'); + throw new AxiosError( + `There is no suitable adapter to dispatch the request ` + s, + 'ERR_NOT_SUPPORT' + ); } return adapter; @@ -9861,107 +10486,6 @@ function dispatchRequest(config) { }); } -const headersToObject = (thing) => thing instanceof AxiosHeaders$1 ? thing.toJSON() : thing; - -/** - * Config-specific merge-function which creates a new config-object - * by merging two configuration objects together. - * - * @param {Object} config1 - * @param {Object} config2 - * - * @returns {Object} New object resulting from merging config2 to config1 - */ -function mergeConfig(config1, config2) { - // eslint-disable-next-line no-param-reassign - config2 = config2 || {}; - const config = {}; - - function getMergedValue(target, source, caseless) { - if (utils.isPlainObject(target) && utils.isPlainObject(source)) { - return utils.merge.call({caseless}, target, source); - } else if (utils.isPlainObject(source)) { - return utils.merge({}, source); - } else if (utils.isArray(source)) { - return source.slice(); - } - return source; - } - - // eslint-disable-next-line consistent-return - function mergeDeepProperties(a, b, caseless) { - if (!utils.isUndefined(b)) { - return getMergedValue(a, b, caseless); - } else if (!utils.isUndefined(a)) { - return getMergedValue(undefined, a, caseless); - } - } - - // eslint-disable-next-line consistent-return - function valueFromConfig2(a, b) { - if (!utils.isUndefined(b)) { - return getMergedValue(undefined, b); - } - } - - // eslint-disable-next-line consistent-return - function defaultToConfig2(a, b) { - if (!utils.isUndefined(b)) { - return getMergedValue(undefined, b); - } else if (!utils.isUndefined(a)) { - return getMergedValue(undefined, a); - } - } - - // eslint-disable-next-line consistent-return - function mergeDirectKeys(a, b, prop) { - if (prop in config2) { - return getMergedValue(a, b); - } else if (prop in config1) { - return getMergedValue(undefined, a); - } - } - - const mergeMap = { - url: valueFromConfig2, - method: valueFromConfig2, - data: valueFromConfig2, - baseURL: defaultToConfig2, - transformRequest: defaultToConfig2, - transformResponse: defaultToConfig2, - paramsSerializer: defaultToConfig2, - timeout: defaultToConfig2, - timeoutMessage: defaultToConfig2, - withCredentials: defaultToConfig2, - adapter: defaultToConfig2, - responseType: defaultToConfig2, - xsrfCookieName: defaultToConfig2, - xsrfHeaderName: defaultToConfig2, - onUploadProgress: defaultToConfig2, - onDownloadProgress: defaultToConfig2, - decompress: defaultToConfig2, - maxContentLength: defaultToConfig2, - maxBodyLength: defaultToConfig2, - beforeRedirect: defaultToConfig2, - transport: defaultToConfig2, - httpAgent: defaultToConfig2, - httpsAgent: defaultToConfig2, - cancelToken: defaultToConfig2, - socketPath: defaultToConfig2, - responseEncoding: defaultToConfig2, - validateStatus: mergeDirectKeys, - headers: (a, b) => mergeDeepProperties(headersToObject(a), headersToObject(b), true) - }; - - utils.forEach(Object.keys(Object.assign({}, config1, config2)), function computeConfigValue(prop) { - const merge = mergeMap[prop] || mergeDeepProperties; - const configValue = merge(config1[prop], config2[prop], prop); - (utils.isUndefined(configValue) && merge !== mergeDirectKeys) || (config[prop] = configValue); - }); - - return config; -} - const validators$1 = {}; // eslint-disable-next-line func-names @@ -10075,7 +10599,34 @@ class Axios { * * @returns {Promise} The Promise to be fulfilled */ - request(configOrUrl, config) { + async request(configOrUrl, config) { + try { + return await this._request(configOrUrl, config); + } catch (err) { + if (err instanceof Error) { + let dummy; + + Error.captureStackTrace ? Error.captureStackTrace(dummy = {}) : (dummy = new Error()); + + // slice off the Error: ... line + const stack = dummy.stack ? dummy.stack.replace(/^.+\n/, '') : ''; + try { + if (!err.stack) { + err.stack = stack; + // match without the 2 top stack lines + } else if (stack && !String(err.stack).endsWith(stack.replace(/^.+\n.+\n/, ''))) { + err.stack += '\n' + stack; + } + } catch (e) { + // ignore the case where "stack" is an un-writable property + } + } + + throw err; + } + } + + _request(configOrUrl, config) { /*eslint no-param-reassign:0*/ // Allow for axios('example/url'[, config]) a la fetch API if (typeof configOrUrl === 'string') { @@ -10098,7 +10649,7 @@ class Axios { } if (paramsSerializer != null) { - if (utils.isFunction(paramsSerializer)) { + if (utils$1.isFunction(paramsSerializer)) { config.paramsSerializer = { serialize: paramsSerializer }; @@ -10114,12 +10665,12 @@ class Axios { config.method = (config.method || this.defaults.method || 'get').toLowerCase(); // Flatten headers - let contextHeaders = headers && utils.merge( + let contextHeaders = headers && utils$1.merge( headers.common, headers[config.method] ); - headers && utils.forEach( + headers && utils$1.forEach( ['delete', 'get', 'head', 'post', 'put', 'patch', 'common'], (method) => { delete headers[method]; @@ -10206,7 +10757,7 @@ class Axios { } // Provide aliases for supported request methods -utils.forEach(['delete', 'get', 'head', 'options'], function forEachMethodNoData(method) { +utils$1.forEach(['delete', 'get', 'head', 'options'], function forEachMethodNoData(method) { /*eslint func-names:0*/ Axios.prototype[method] = function(url, config) { return this.request(mergeConfig(config || {}, { @@ -10217,7 +10768,7 @@ utils.forEach(['delete', 'get', 'head', 'options'], function forEachMethodNoData }; }); -utils.forEach(['post', 'put', 'patch'], function forEachMethodWithData(method) { +utils$1.forEach(['post', 'put', 'patch'], function forEachMethodWithData(method) { /*eslint func-names:0*/ function generateHTTPMethod(isForm) { @@ -10393,7 +10944,7 @@ function spread(callback) { * @returns {boolean} True if the payload is an error thrown by Axios, otherwise false */ function isAxiosError(payload) { - return utils.isObject(payload) && (payload.isAxiosError === true); + return utils$1.isObject(payload) && (payload.isAxiosError === true); } const HttpStatusCode = { @@ -10480,10 +11031,10 @@ function createInstance(defaultConfig) { const instance = bind(Axios$1.prototype.request, context); // Copy axios.prototype to instance - utils.extend(instance, Axios$1.prototype, context, {allOwnKeys: true}); + utils$1.extend(instance, Axios$1.prototype, context, {allOwnKeys: true}); // Copy context to instance - utils.extend(instance, context, null, {allOwnKeys: true}); + utils$1.extend(instance, context, null, {allOwnKeys: true}); // Factory for creating new instances instance.create = function create(instanceConfig) { @@ -10527,7 +11078,7 @@ axios.mergeConfig = mergeConfig; axios.AxiosHeaders = AxiosHeaders$1; -axios.formToJSON = thing => formDataToJSON(utils.isHTMLForm(thing) ? new FormData(thing) : thing); +axios.formToJSON = thing => formDataToJSON(utils$1.isHTMLForm(thing) ? new FormData(thing) : thing); axios.getAdapter = adapters.getAdapter; diff --git a/package-lock.json b/package-lock.json index 7304d13..7a66147 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,7 @@ "license": "ISC", "dependencies": { "@actions/core": "1.10.1", - "axios": "1.6.2" + "axios": "1.7.4" }, "devDependencies": { "@vercel/ncc": "0.38.1", @@ -255,11 +255,12 @@ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" }, "node_modules/axios": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.2.tgz", - "integrity": "sha512-7i24Ri4pmDRfJTR7LDBhsOTtcm+9kjX5WiY1X3wIisx6G9So3pfMkEiU7emUBe46oceVImccTEM3k6C5dbVW8A==", + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.4.tgz", + "integrity": "sha512-DukmaFRnY6AzAALSH4J2M3k6PkaC+MfaAGdEERRWcC9q3/TWQwLpHR8ZRLKTdQ3aBDL64EdluRDjJqKw+BPZEw==", + "license": "MIT", "dependencies": { - "follow-redirects": "^1.15.0", + "follow-redirects": "^1.15.6", "form-data": "^4.0.0", "proxy-from-env": "^1.1.0" } @@ -627,15 +628,16 @@ "dev": true }, "node_modules/follow-redirects": { - "version": "1.15.2", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", - "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", "funding": [ { "type": "individual", "url": "https://github.com/sponsors/RubenVerborgh" } ], + "license": "MIT", "engines": { "node": ">=4.0" }, diff --git a/package.json b/package.json index ba736e1..74ca4e8 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "homepage": "https://github.com/clevyr/node-versions-action#readme", "dependencies": { "@actions/core": "1.10.1", - "axios": "1.6.2" + "axios": "1.7.4" }, "devDependencies": { "@vercel/ncc": "0.38.1",