diff --git a/dist/index.js b/dist/index.js index 44e5bea..da065a2 100644 --- a/dist/index.js +++ b/dist/index.js @@ -1747,6 +1747,241 @@ exports.checkBypass = checkBypass; /***/ }), +/***/ 8207: +/***/ (function(module, __unused_webpack_exports, __nccwpck_require__) { + +"use strict"; + +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +const events_1 = __nccwpck_require__(4434); +const debug_1 = __importDefault(__nccwpck_require__(2830)); +const promisify_1 = __importDefault(__nccwpck_require__(8067)); +const debug = debug_1.default('agent-base'); +function isAgent(v) { + return Boolean(v) && typeof v.addRequest === 'function'; +} +function isSecureEndpoint() { + const { stack } = new Error(); + if (typeof stack !== 'string') + return false; + return stack.split('\n').some(l => l.indexOf('(https.js:') !== -1 || l.indexOf('node:https:') !== -1); +} +function createAgent(callback, opts) { + return new createAgent.Agent(callback, opts); +} +(function (createAgent) { + /** + * Base `http.Agent` implementation. + * No pooling/keep-alive is implemented by default. + * + * @param {Function} callback + * @api public + */ + class Agent extends events_1.EventEmitter { + constructor(callback, _opts) { + super(); + let opts = _opts; + if (typeof callback === 'function') { + this.callback = callback; + } + else if (callback) { + opts = callback; + } + // Timeout for the socket to be returned from the callback + this.timeout = null; + if (opts && typeof opts.timeout === 'number') { + this.timeout = opts.timeout; + } + // These aren't actually used by `agent-base`, but are required + // for the TypeScript definition files in `@types/node` :/ + this.maxFreeSockets = 1; + this.maxSockets = 1; + this.maxTotalSockets = Infinity; + this.sockets = {}; + this.freeSockets = {}; + this.requests = {}; + this.options = {}; + } + get defaultPort() { + if (typeof this.explicitDefaultPort === 'number') { + return this.explicitDefaultPort; + } + return isSecureEndpoint() ? 443 : 80; + } + set defaultPort(v) { + this.explicitDefaultPort = v; + } + get protocol() { + if (typeof this.explicitProtocol === 'string') { + return this.explicitProtocol; + } + return isSecureEndpoint() ? 'https:' : 'http:'; + } + set protocol(v) { + this.explicitProtocol = v; + } + callback(req, opts, fn) { + throw new Error('"agent-base" has no default implementation, you must subclass and override `callback()`'); + } + /** + * Called by node-core's "_http_client.js" module when creating + * a new HTTP request with this Agent instance. + * + * @api public + */ + addRequest(req, _opts) { + const opts = Object.assign({}, _opts); + if (typeof opts.secureEndpoint !== 'boolean') { + opts.secureEndpoint = isSecureEndpoint(); + } + if (opts.host == null) { + opts.host = 'localhost'; + } + if (opts.port == null) { + opts.port = opts.secureEndpoint ? 443 : 80; + } + if (opts.protocol == null) { + opts.protocol = opts.secureEndpoint ? 'https:' : 'http:'; + } + if (opts.host && opts.path) { + // If both a `host` and `path` are specified then it's most + // likely the result of a `url.parse()` call... we need to + // remove the `path` portion so that `net.connect()` doesn't + // attempt to open that as a unix socket file. + delete opts.path; + } + delete opts.agent; + delete opts.hostname; + delete opts._defaultAgent; + delete opts.defaultPort; + delete opts.createConnection; + // Hint to use "Connection: close" + // XXX: non-documented `http` module API :( + req._last = true; + req.shouldKeepAlive = false; + let timedOut = false; + let timeoutId = null; + const timeoutMs = opts.timeout || this.timeout; + const onerror = (err) => { + if (req._hadError) + return; + req.emit('error', err); + // For Safety. Some additional errors might fire later on + // and we need to make sure we don't double-fire the error event. + req._hadError = true; + }; + const ontimeout = () => { + timeoutId = null; + timedOut = true; + const err = new Error(`A "socket" was not created for HTTP request before ${timeoutMs}ms`); + err.code = 'ETIMEOUT'; + onerror(err); + }; + const callbackError = (err) => { + if (timedOut) + return; + if (timeoutId !== null) { + clearTimeout(timeoutId); + timeoutId = null; + } + onerror(err); + }; + const onsocket = (socket) => { + if (timedOut) + return; + if (timeoutId != null) { + clearTimeout(timeoutId); + timeoutId = null; + } + if (isAgent(socket)) { + // `socket` is actually an `http.Agent` instance, so + // relinquish responsibility for this `req` to the Agent + // from here on + debug('Callback returned another Agent instance %o', socket.constructor.name); + socket.addRequest(req, opts); + return; + } + if (socket) { + socket.once('free', () => { + this.freeSocket(socket, opts); + }); + req.onSocket(socket); + return; + } + const err = new Error(`no Duplex stream was returned to agent-base for \`${req.method} ${req.path}\``); + onerror(err); + }; + if (typeof this.callback !== 'function') { + onerror(new Error('`callback` is not defined')); + return; + } + if (!this.promisifiedCallback) { + if (this.callback.length >= 3) { + debug('Converting legacy callback function to promise'); + this.promisifiedCallback = promisify_1.default(this.callback); + } + else { + this.promisifiedCallback = this.callback; + } + } + if (typeof timeoutMs === 'number' && timeoutMs > 0) { + timeoutId = setTimeout(ontimeout, timeoutMs); + } + if ('port' in opts && typeof opts.port !== 'number') { + opts.port = Number(opts.port); + } + try { + debug('Resolving socket for %o request: %o', opts.protocol, `${req.method} ${req.path}`); + Promise.resolve(this.promisifiedCallback(req, opts)).then(onsocket, callbackError); + } + catch (err) { + Promise.reject(err).catch(callbackError); + } + } + freeSocket(socket, opts) { + debug('Freeing socket %o %o', socket.constructor.name, opts); + socket.destroy(); + } + destroy() { + debug('Destroying agent %o', this.constructor.name); + } + } + createAgent.Agent = Agent; + // So that `instanceof` works correctly + createAgent.prototype = createAgent.Agent.prototype; +})(createAgent || (createAgent = {})); +module.exports = createAgent; +//# sourceMappingURL=index.js.map + +/***/ }), + +/***/ 8067: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +function promisify(fn) { + return function (req, opts) { + return new Promise((resolve, reject) => { + fn.call(this, req, opts, (err, rtn) => { + if (err) { + reject(err); + } + else { + resolve(rtn); + } + }); + }); + }; +} +exports["default"] = promisify; +//# sourceMappingURL=promisify.js.map + +/***/ }), + /***/ 1324: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { @@ -2478,6 +2713,871 @@ CombinedStream.prototype._emitError = function(err) { }; +/***/ }), + +/***/ 6110: +/***/ ((module, exports, __nccwpck_require__) => { + +/* eslint-env browser */ + +/** + * This is the web browser implementation of `debug()`. + */ + +exports.formatArgs = formatArgs; +exports.save = save; +exports.load = load; +exports.useColors = useColors; +exports.storage = localstorage(); +exports.destroy = (() => { + let warned = false; + + return () => { + if (!warned) { + warned = true; + console.warn('Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.'); + } + }; +})(); + +/** + * Colors. + */ + +exports.colors = [ + '#0000CC', + '#0000FF', + '#0033CC', + '#0033FF', + '#0066CC', + '#0066FF', + '#0099CC', + '#0099FF', + '#00CC00', + '#00CC33', + '#00CC66', + '#00CC99', + '#00CCCC', + '#00CCFF', + '#3300CC', + '#3300FF', + '#3333CC', + '#3333FF', + '#3366CC', + '#3366FF', + '#3399CC', + '#3399FF', + '#33CC00', + '#33CC33', + '#33CC66', + '#33CC99', + '#33CCCC', + '#33CCFF', + '#6600CC', + '#6600FF', + '#6633CC', + '#6633FF', + '#66CC00', + '#66CC33', + '#9900CC', + '#9900FF', + '#9933CC', + '#9933FF', + '#99CC00', + '#99CC33', + '#CC0000', + '#CC0033', + '#CC0066', + '#CC0099', + '#CC00CC', + '#CC00FF', + '#CC3300', + '#CC3333', + '#CC3366', + '#CC3399', + '#CC33CC', + '#CC33FF', + '#CC6600', + '#CC6633', + '#CC9900', + '#CC9933', + '#CCCC00', + '#CCCC33', + '#FF0000', + '#FF0033', + '#FF0066', + '#FF0099', + '#FF00CC', + '#FF00FF', + '#FF3300', + '#FF3333', + '#FF3366', + '#FF3399', + '#FF33CC', + '#FF33FF', + '#FF6600', + '#FF6633', + '#FF9900', + '#FF9933', + '#FFCC00', + '#FFCC33' +]; + +/** + * Currently only WebKit-based Web Inspectors, Firefox >= v31, + * and the Firebug extension (any Firefox version) are known + * to support "%c" CSS customizations. + * + * TODO: add a `localStorage` variable to explicitly enable/disable colors + */ + +// eslint-disable-next-line complexity +function useColors() { + // NB: In an Electron preload script, document will be defined but not fully + // initialized. Since we know we're in Chrome, we'll just detect this case + // explicitly + if (typeof window !== 'undefined' && window.process && (window.process.type === 'renderer' || window.process.__nwjs)) { + return true; + } + + // Internet Explorer and Edge do not support colors. + if (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/(edge|trident)\/(\d+)/)) { + return false; + } + + let m; + + // Is webkit? http://stackoverflow.com/a/16459606/376773 + // document is undefined in react-native: https://github.com/facebook/react-native/pull/1632 + // eslint-disable-next-line no-return-assign + return (typeof document !== 'undefined' && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance) || + // Is firebug? http://stackoverflow.com/a/398120/376773 + (typeof window !== 'undefined' && window.console && (window.console.firebug || (window.console.exception && window.console.table))) || + // Is firefox >= v31? + // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages + (typeof navigator !== 'undefined' && navigator.userAgent && (m = navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/)) && parseInt(m[1], 10) >= 31) || + // Double check webkit in userAgent just in case we are in a worker + (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/)); +} + +/** + * Colorize log arguments if enabled. + * + * @api public + */ + +function formatArgs(args) { + args[0] = (this.useColors ? '%c' : '') + + this.namespace + + (this.useColors ? ' %c' : ' ') + + args[0] + + (this.useColors ? '%c ' : ' ') + + '+' + module.exports.humanize(this.diff); + + if (!this.useColors) { + return; + } + + const c = 'color: ' + this.color; + args.splice(1, 0, c, 'color: inherit'); + + // The final "%c" is somewhat tricky, because there could be other + // arguments passed either before or after the %c, so we need to + // figure out the correct index to insert the CSS into + let index = 0; + let lastC = 0; + args[0].replace(/%[a-zA-Z%]/g, match => { + if (match === '%%') { + return; + } + index++; + if (match === '%c') { + // We only are interested in the *last* %c + // (the user may have provided their own) + lastC = index; + } + }); + + args.splice(lastC, 0, c); +} + +/** + * Invokes `console.debug()` when available. + * No-op when `console.debug` is not a "function". + * If `console.debug` is not available, falls back + * to `console.log`. + * + * @api public + */ +exports.log = console.debug || console.log || (() => {}); + +/** + * Save `namespaces`. + * + * @param {String} namespaces + * @api private + */ +function save(namespaces) { + try { + if (namespaces) { + exports.storage.setItem('debug', namespaces); + } else { + exports.storage.removeItem('debug'); + } + } catch (error) { + // Swallow + // XXX (@Qix-) should we be logging these? + } +} + +/** + * Load `namespaces`. + * + * @return {String} returns the previously persisted debug modes + * @api private + */ +function load() { + let r; + try { + r = exports.storage.getItem('debug') || exports.storage.getItem('DEBUG') ; + } catch (error) { + // Swallow + // XXX (@Qix-) should we be logging these? + } + + // If debug isn't set in LS, and we're in Electron, try to load $DEBUG + if (!r && typeof process !== 'undefined' && 'env' in process) { + r = process.env.DEBUG; + } + + return r; +} + +/** + * Localstorage attempts to return the localstorage. + * + * This is necessary because safari throws + * when a user disables cookies/localstorage + * and you attempt to access it. + * + * @return {LocalStorage} + * @api private + */ + +function localstorage() { + try { + // TVMLKit (Apple TV JS Runtime) does not have a window object, just localStorage in the global context + // The Browser also has localStorage in the global context. + return localStorage; + } catch (error) { + // Swallow + // XXX (@Qix-) should we be logging these? + } +} + +module.exports = __nccwpck_require__(897)(exports); + +const {formatters} = module.exports; + +/** + * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default. + */ + +formatters.j = function (v) { + try { + return JSON.stringify(v); + } catch (error) { + return '[UnexpectedJSONParseError]: ' + error.message; + } +}; + + +/***/ }), + +/***/ 897: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + + +/** + * This is the common logic for both the Node.js and web browser + * implementations of `debug()`. + */ + +function setup(env) { + createDebug.debug = createDebug; + createDebug.default = createDebug; + createDebug.coerce = coerce; + createDebug.disable = disable; + createDebug.enable = enable; + createDebug.enabled = enabled; + createDebug.humanize = __nccwpck_require__(744); + createDebug.destroy = destroy; + + Object.keys(env).forEach(key => { + createDebug[key] = env[key]; + }); + + /** + * The currently active debug mode names, and names to skip. + */ + + createDebug.names = []; + createDebug.skips = []; + + /** + * Map of special "%n" handling functions, for the debug "format" argument. + * + * Valid key names are a single, lower or upper-case letter, i.e. "n" and "N". + */ + createDebug.formatters = {}; + + /** + * Selects a color for a debug namespace + * @param {String} namespace The namespace string for the debug instance to be colored + * @return {Number|String} An ANSI color code for the given namespace + * @api private + */ + function selectColor(namespace) { + let hash = 0; + + for (let i = 0; i < namespace.length; i++) { + hash = ((hash << 5) - hash) + namespace.charCodeAt(i); + hash |= 0; // Convert to 32bit integer + } + + return createDebug.colors[Math.abs(hash) % createDebug.colors.length]; + } + createDebug.selectColor = selectColor; + + /** + * Create a debugger with the given `namespace`. + * + * @param {String} namespace + * @return {Function} + * @api public + */ + function createDebug(namespace) { + let prevTime; + let enableOverride = null; + let namespacesCache; + let enabledCache; + + function debug(...args) { + // Disabled? + if (!debug.enabled) { + return; + } + + const self = debug; + + // Set `diff` timestamp + const curr = Number(new Date()); + const ms = curr - (prevTime || curr); + self.diff = ms; + self.prev = prevTime; + self.curr = curr; + prevTime = curr; + + args[0] = createDebug.coerce(args[0]); + + if (typeof args[0] !== 'string') { + // Anything else let's inspect with %O + args.unshift('%O'); + } + + // Apply any `formatters` transformations + let index = 0; + args[0] = args[0].replace(/%([a-zA-Z%])/g, (match, format) => { + // If we encounter an escaped % then don't increase the array index + if (match === '%%') { + return '%'; + } + index++; + const formatter = createDebug.formatters[format]; + if (typeof formatter === 'function') { + const val = args[index]; + match = formatter.call(self, val); + + // Now we need to remove `args[index]` since it's inlined in the `format` + args.splice(index, 1); + index--; + } + return match; + }); + + // Apply env-specific formatting (colors, etc.) + createDebug.formatArgs.call(self, args); + + const logFn = self.log || createDebug.log; + logFn.apply(self, args); + } + + debug.namespace = namespace; + debug.useColors = createDebug.useColors(); + debug.color = createDebug.selectColor(namespace); + debug.extend = extend; + debug.destroy = createDebug.destroy; // XXX Temporary. Will be removed in the next major release. + + Object.defineProperty(debug, 'enabled', { + enumerable: true, + configurable: false, + get: () => { + if (enableOverride !== null) { + return enableOverride; + } + if (namespacesCache !== createDebug.namespaces) { + namespacesCache = createDebug.namespaces; + enabledCache = createDebug.enabled(namespace); + } + + return enabledCache; + }, + set: v => { + enableOverride = v; + } + }); + + // Env-specific initialization logic for debug instances + if (typeof createDebug.init === 'function') { + createDebug.init(debug); + } + + return debug; + } + + function extend(namespace, delimiter) { + const newDebug = createDebug(this.namespace + (typeof delimiter === 'undefined' ? ':' : delimiter) + namespace); + newDebug.log = this.log; + return newDebug; + } + + /** + * Enables a debug mode by namespaces. This can include modes + * separated by a colon and wildcards. + * + * @param {String} namespaces + * @api public + */ + function enable(namespaces) { + createDebug.save(namespaces); + createDebug.namespaces = namespaces; + + createDebug.names = []; + createDebug.skips = []; + + const split = (typeof namespaces === 'string' ? namespaces : '') + .trim() + .replace(/\s+/g, ',') + .split(',') + .filter(Boolean); + + for (const ns of split) { + if (ns[0] === '-') { + createDebug.skips.push(ns.slice(1)); + } else { + createDebug.names.push(ns); + } + } + } + + /** + * Checks if the given string matches a namespace template, honoring + * asterisks as wildcards. + * + * @param {String} search + * @param {String} template + * @return {Boolean} + */ + function matchesTemplate(search, template) { + let searchIndex = 0; + let templateIndex = 0; + let starIndex = -1; + let matchIndex = 0; + + while (searchIndex < search.length) { + if (templateIndex < template.length && (template[templateIndex] === search[searchIndex] || template[templateIndex] === '*')) { + // Match character or proceed with wildcard + if (template[templateIndex] === '*') { + starIndex = templateIndex; + matchIndex = searchIndex; + templateIndex++; // Skip the '*' + } else { + searchIndex++; + templateIndex++; + } + } else if (starIndex !== -1) { // eslint-disable-line no-negated-condition + // Backtrack to the last '*' and try to match more characters + templateIndex = starIndex + 1; + matchIndex++; + searchIndex = matchIndex; + } else { + return false; // No match + } + } + + // Handle trailing '*' in template + while (templateIndex < template.length && template[templateIndex] === '*') { + templateIndex++; + } + + return templateIndex === template.length; + } + + /** + * Disable debug output. + * + * @return {String} namespaces + * @api public + */ + function disable() { + const namespaces = [ + ...createDebug.names, + ...createDebug.skips.map(namespace => '-' + namespace) + ].join(','); + createDebug.enable(''); + return namespaces; + } + + /** + * Returns true if the given mode name is enabled, false otherwise. + * + * @param {String} name + * @return {Boolean} + * @api public + */ + function enabled(name) { + for (const skip of createDebug.skips) { + if (matchesTemplate(name, skip)) { + return false; + } + } + + for (const ns of createDebug.names) { + if (matchesTemplate(name, ns)) { + return true; + } + } + + return false; + } + + /** + * Coerce `val`. + * + * @param {Mixed} val + * @return {Mixed} + * @api private + */ + function coerce(val) { + if (val instanceof Error) { + return val.stack || val.message; + } + return val; + } + + /** + * XXX DO NOT USE. This is a temporary stub function. + * XXX It WILL be removed in the next major release. + */ + function destroy() { + console.warn('Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.'); + } + + createDebug.enable(createDebug.load()); + + return createDebug; +} + +module.exports = setup; + + +/***/ }), + +/***/ 2830: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +/** + * Detect Electron renderer / nwjs process, which is node, but we should + * treat as a browser. + */ + +if (typeof process === 'undefined' || process.type === 'renderer' || process.browser === true || process.__nwjs) { + module.exports = __nccwpck_require__(6110); +} else { + module.exports = __nccwpck_require__(5108); +} + + +/***/ }), + +/***/ 5108: +/***/ ((module, exports, __nccwpck_require__) => { + +/** + * Module dependencies. + */ + +const tty = __nccwpck_require__(2018); +const util = __nccwpck_require__(9023); + +/** + * This is the Node.js implementation of `debug()`. + */ + +exports.init = init; +exports.log = log; +exports.formatArgs = formatArgs; +exports.save = save; +exports.load = load; +exports.useColors = useColors; +exports.destroy = util.deprecate( + () => {}, + 'Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.' +); + +/** + * Colors. + */ + +exports.colors = [6, 2, 3, 4, 5, 1]; + +try { + // Optional dependency (as in, doesn't need to be installed, NOT like optionalDependencies in package.json) + // eslint-disable-next-line import/no-extraneous-dependencies + const supportsColor = __nccwpck_require__(75); + + if (supportsColor && (supportsColor.stderr || supportsColor).level >= 2) { + exports.colors = [ + 20, + 21, + 26, + 27, + 32, + 33, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 56, + 57, + 62, + 63, + 68, + 69, + 74, + 75, + 76, + 77, + 78, + 79, + 80, + 81, + 92, + 93, + 98, + 99, + 112, + 113, + 128, + 129, + 134, + 135, + 148, + 149, + 160, + 161, + 162, + 163, + 164, + 165, + 166, + 167, + 168, + 169, + 170, + 171, + 172, + 173, + 178, + 179, + 184, + 185, + 196, + 197, + 198, + 199, + 200, + 201, + 202, + 203, + 204, + 205, + 206, + 207, + 208, + 209, + 214, + 215, + 220, + 221 + ]; + } +} catch (error) { + // Swallow - we only care if `supports-color` is available; it doesn't have to be. +} + +/** + * Build up the default `inspectOpts` object from the environment variables. + * + * $ DEBUG_COLORS=no DEBUG_DEPTH=10 DEBUG_SHOW_HIDDEN=enabled node script.js + */ + +exports.inspectOpts = Object.keys(process.env).filter(key => { + return /^debug_/i.test(key); +}).reduce((obj, key) => { + // Camel-case + const prop = key + .substring(6) + .toLowerCase() + .replace(/_([a-z])/g, (_, k) => { + return k.toUpperCase(); + }); + + // Coerce string value into JS value + let val = process.env[key]; + if (/^(yes|on|true|enabled)$/i.test(val)) { + val = true; + } else if (/^(no|off|false|disabled)$/i.test(val)) { + val = false; + } else if (val === 'null') { + val = null; + } else { + val = Number(val); + } + + obj[prop] = val; + return obj; +}, {}); + +/** + * Is stdout a TTY? Colored output is enabled when `true`. + */ + +function useColors() { + return 'colors' in exports.inspectOpts ? + Boolean(exports.inspectOpts.colors) : + tty.isatty(process.stderr.fd); +} + +/** + * Adds ANSI color escape codes if enabled. + * + * @api public + */ + +function formatArgs(args) { + const {namespace: name, useColors} = this; + + if (useColors) { + const c = this.color; + const colorCode = '\u001B[3' + (c < 8 ? c : '8;5;' + c); + const prefix = ` ${colorCode};1m${name} \u001B[0m`; + + args[0] = prefix + args[0].split('\n').join('\n' + prefix); + args.push(colorCode + 'm+' + module.exports.humanize(this.diff) + '\u001B[0m'); + } else { + args[0] = getDate() + name + ' ' + args[0]; + } +} + +function getDate() { + if (exports.inspectOpts.hideDate) { + return ''; + } + return new Date().toISOString() + ' '; +} + +/** + * Invokes `util.formatWithOptions()` with the specified arguments and writes to stderr. + */ + +function log(...args) { + return process.stderr.write(util.formatWithOptions(exports.inspectOpts, ...args) + '\n'); +} + +/** + * Save `namespaces`. + * + * @param {String} namespaces + * @api private + */ +function save(namespaces) { + if (namespaces) { + process.env.DEBUG = namespaces; + } else { + // If you set a process.env field to null or undefined, it gets cast to the + // string 'null' or 'undefined'. Just delete instead. + delete process.env.DEBUG; + } +} + +/** + * Load `namespaces`. + * + * @return {String} returns the previously persisted debug modes + * @api private + */ + +function load() { + return process.env.DEBUG; +} + +/** + * Init logic for `debug` instances. + * + * Create a new `inspectOpts` object in case `useColors` is set + * differently for a particular `debug` instance. + */ + +function init(debug) { + debug.inspectOpts = {}; + + const keys = Object.keys(exports.inspectOpts); + for (let i = 0; i < keys.length; i++) { + debug.inspectOpts[keys[i]] = exports.inspectOpts[keys[i]]; + } +} + +module.exports = __nccwpck_require__(897)(exports); + +const {formatters} = module.exports; + +/** + * Map %o to `util.inspect()`, all on a single line. + */ + +formatters.o = function (v) { + this.inspectOpts.colors = this.useColors; + return util.inspect(v, this.inspectOpts) + .split('\n') + .map(str => str.trim()) + .join(' '); +}; + +/** + * Map %O to `util.inspect()`, allowing multiple lines if needed. + */ + +formatters.O = function (v) { + this.inspectOpts.colors = this.useColors; + return util.inspect(v, this.inspectOpts); +}; + + /***/ }), /***/ 2710: @@ -2802,7 +3902,7 @@ module.exports = function () { if (!debug) { try { /* eslint global-require: off */ - debug = __nccwpck_require__(8422)("follow-redirects"); + debug = __nccwpck_require__(2830)("follow-redirects"); } catch (error) { /* */ } if (typeof debug !== "function") { @@ -4741,35 +5841,313 @@ module.exports = function hasSymbols() { /***/ }), -/***/ 5479: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { +/***/ 5479: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +var hasSymbols = __nccwpck_require__(1114); + +/** @type {import('.')} */ +module.exports = function hasToStringTagShams() { + return hasSymbols() && !!Symbol.toStringTag; +}; + + +/***/ }), + +/***/ 4076: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +var call = Function.prototype.call; +var $hasOwn = Object.prototype.hasOwnProperty; +var bind = __nccwpck_require__(7564); + +/** @type {import('.')} */ +module.exports = bind.call(call, $hasOwn); + + +/***/ }), + +/***/ 6904: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +const net_1 = __importDefault(__nccwpck_require__(9278)); +const tls_1 = __importDefault(__nccwpck_require__(4756)); +const url_1 = __importDefault(__nccwpck_require__(7016)); +const assert_1 = __importDefault(__nccwpck_require__(2613)); +const debug_1 = __importDefault(__nccwpck_require__(2830)); +const agent_base_1 = __nccwpck_require__(8207); +const parse_proxy_response_1 = __importDefault(__nccwpck_require__(7943)); +const debug = debug_1.default('https-proxy-agent:agent'); +/** + * The `HttpsProxyAgent` implements an HTTP Agent subclass that connects to + * the specified "HTTP(s) proxy server" in order to proxy HTTPS requests. + * + * Outgoing HTTP requests are first tunneled through the proxy server using the + * `CONNECT` HTTP request method to establish a connection to the proxy server, + * and then the proxy server connects to the destination target and issues the + * HTTP request from the proxy server. + * + * `https:` requests have their socket connection upgraded to TLS once + * the connection to the proxy server has been established. + * + * @api public + */ +class HttpsProxyAgent extends agent_base_1.Agent { + constructor(_opts) { + let opts; + if (typeof _opts === 'string') { + opts = url_1.default.parse(_opts); + } + else { + opts = _opts; + } + if (!opts) { + throw new Error('an HTTP(S) proxy server `host` and `port` must be specified!'); + } + debug('creating new HttpsProxyAgent instance: %o', opts); + super(opts); + const proxy = Object.assign({}, opts); + // If `true`, then connect to the proxy server over TLS. + // Defaults to `false`. + this.secureProxy = opts.secureProxy || isHTTPS(proxy.protocol); + // Prefer `hostname` over `host`, and set the `port` if needed. + proxy.host = proxy.hostname || proxy.host; + if (typeof proxy.port === 'string') { + proxy.port = parseInt(proxy.port, 10); + } + if (!proxy.port && proxy.host) { + proxy.port = this.secureProxy ? 443 : 80; + } + // ALPN is supported by Node.js >= v5. + // attempt to negotiate http/1.1 for proxy servers that support http/2 + if (this.secureProxy && !('ALPNProtocols' in proxy)) { + proxy.ALPNProtocols = ['http 1.1']; + } + if (proxy.host && proxy.path) { + // If both a `host` and `path` are specified then it's most likely + // the result of a `url.parse()` call... we need to remove the + // `path` portion so that `net.connect()` doesn't attempt to open + // that as a Unix socket file. + delete proxy.path; + delete proxy.pathname; + } + this.proxy = proxy; + } + /** + * Called when the node-core HTTP client library is creating a + * new HTTP request. + * + * @api protected + */ + callback(req, opts) { + return __awaiter(this, void 0, void 0, function* () { + const { proxy, secureProxy } = this; + // Create a socket connection to the proxy server. + let socket; + if (secureProxy) { + debug('Creating `tls.Socket`: %o', proxy); + socket = tls_1.default.connect(proxy); + } + else { + debug('Creating `net.Socket`: %o', proxy); + socket = net_1.default.connect(proxy); + } + const headers = Object.assign({}, proxy.headers); + const hostname = `${opts.host}:${opts.port}`; + let payload = `CONNECT ${hostname} HTTP/1.1\r\n`; + // Inject the `Proxy-Authorization` header if necessary. + if (proxy.auth) { + headers['Proxy-Authorization'] = `Basic ${Buffer.from(proxy.auth).toString('base64')}`; + } + // The `Host` header should only include the port + // number when it is not the default port. + let { host, port, secureEndpoint } = opts; + if (!isDefaultPort(port, secureEndpoint)) { + host += `:${port}`; + } + headers.Host = host; + headers.Connection = 'close'; + for (const name of Object.keys(headers)) { + payload += `${name}: ${headers[name]}\r\n`; + } + const proxyResponsePromise = parse_proxy_response_1.default(socket); + socket.write(`${payload}\r\n`); + const { statusCode, buffered } = yield proxyResponsePromise; + if (statusCode === 200) { + req.once('socket', resume); + if (opts.secureEndpoint) { + // The proxy is connecting to a TLS server, so upgrade + // this socket connection to a TLS connection. + debug('Upgrading socket connection to TLS'); + const servername = opts.servername || opts.host; + return tls_1.default.connect(Object.assign(Object.assign({}, omit(opts, 'host', 'hostname', 'path', 'port')), { socket, + servername })); + } + return socket; + } + // Some other status code that's not 200... need to re-play the HTTP + // header "data" events onto the socket once the HTTP machinery is + // attached so that the node core `http` can parse and handle the + // error status code. + // Close the original socket, and a new "fake" socket is returned + // instead, so that the proxy doesn't get the HTTP request + // written to it (which may contain `Authorization` headers or other + // sensitive data). + // + // See: https://hackerone.com/reports/541502 + socket.destroy(); + const fakeSocket = new net_1.default.Socket({ writable: false }); + fakeSocket.readable = true; + // Need to wait for the "socket" event to re-play the "data" events. + req.once('socket', (s) => { + debug('replaying proxy buffer for failed request'); + assert_1.default(s.listenerCount('data') > 0); + // Replay the "buffered" Buffer onto the fake `socket`, since at + // this point the HTTP module machinery has been hooked up for + // the user. + s.push(buffered); + s.push(null); + }); + return fakeSocket; + }); + } +} +exports["default"] = HttpsProxyAgent; +function resume(socket) { + socket.resume(); +} +function isDefaultPort(port, secure) { + return Boolean((!secure && port === 80) || (secure && port === 443)); +} +function isHTTPS(protocol) { + return typeof protocol === 'string' ? /^https:?$/i.test(protocol) : false; +} +function omit(obj, ...keys) { + const ret = {}; + let key; + for (key in obj) { + if (!keys.includes(key)) { + ret[key] = obj[key]; + } + } + return ret; +} +//# sourceMappingURL=agent.js.map + +/***/ }), + +/***/ 3669: +/***/ (function(module, __unused_webpack_exports, __nccwpck_require__) { "use strict"; - -var hasSymbols = __nccwpck_require__(1114); - -/** @type {import('.')} */ -module.exports = function hasToStringTagShams() { - return hasSymbols() && !!Symbol.toStringTag; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; }; - +const agent_1 = __importDefault(__nccwpck_require__(6904)); +function createHttpsProxyAgent(opts) { + return new agent_1.default(opts); +} +(function (createHttpsProxyAgent) { + createHttpsProxyAgent.HttpsProxyAgent = agent_1.default; + createHttpsProxyAgent.prototype = agent_1.default.prototype; +})(createHttpsProxyAgent || (createHttpsProxyAgent = {})); +module.exports = createHttpsProxyAgent; +//# sourceMappingURL=index.js.map /***/ }), -/***/ 4076: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { +/***/ 7943: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { "use strict"; - -var call = Function.prototype.call; -var $hasOwn = Object.prototype.hasOwnProperty; -var bind = __nccwpck_require__(7564); - -/** @type {import('.')} */ -module.exports = bind.call(call, $hasOwn); - +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +const debug_1 = __importDefault(__nccwpck_require__(2830)); +const debug = debug_1.default('https-proxy-agent:parse-proxy-response'); +function parseProxyResponse(socket) { + return new Promise((resolve, reject) => { + // we need to buffer any HTTP traffic that happens with the proxy before we get + // the CONNECT response, so that if the response is anything other than an "200" + // response code, then we can re-play the "data" events on the socket once the + // HTTP parser is hooked up... + let buffersLength = 0; + const buffers = []; + function read() { + const b = socket.read(); + if (b) + ondata(b); + else + socket.once('readable', read); + } + function cleanup() { + socket.removeListener('end', onend); + socket.removeListener('error', onerror); + socket.removeListener('close', onclose); + socket.removeListener('readable', read); + } + function onclose(err) { + debug('onclose had error %o', err); + } + function onend() { + debug('onend'); + } + function onerror(err) { + cleanup(); + debug('onerror %o', err); + reject(err); + } + function ondata(b) { + buffers.push(b); + buffersLength += b.length; + const buffered = Buffer.concat(buffers, buffersLength); + const endOfHeaders = buffered.indexOf('\r\n\r\n'); + if (endOfHeaders === -1) { + // keep buffering + debug('have not received end of HTTP headers yet...'); + read(); + return; + } + const firstLine = buffered.toString('ascii', 0, buffered.indexOf('\r\n')); + const statusCode = +firstLine.split(' ')[1]; + debug('got proxy server response: %o', firstLine); + resolve({ + statusCode, + buffered + }); + } + socket.on('error', onerror); + socket.on('close', onclose); + socket.on('end', onend); + read(); + }); +} +exports["default"] = parseProxyResponse; +//# sourceMappingURL=parse-proxy-response.js.map /***/ }), @@ -5091,6 +6469,175 @@ function populateMaps (extensions, types) { } +/***/ }), + +/***/ 744: +/***/ ((module) => { + +/** + * Helpers. + */ + +var s = 1000; +var m = s * 60; +var h = m * 60; +var d = h * 24; +var w = d * 7; +var y = d * 365.25; + +/** + * Parse or format the given `val`. + * + * Options: + * + * - `long` verbose formatting [false] + * + * @param {String|Number} val + * @param {Object} [options] + * @throws {Error} throw an error if val is not a non-empty string or a number + * @return {String|Number} + * @api public + */ + +module.exports = function (val, options) { + options = options || {}; + var type = typeof val; + if (type === 'string' && val.length > 0) { + return parse(val); + } else if (type === 'number' && isFinite(val)) { + return options.long ? fmtLong(val) : fmtShort(val); + } + throw new Error( + 'val is not a non-empty string or a valid number. val=' + + JSON.stringify(val) + ); +}; + +/** + * Parse the given `str` and return milliseconds. + * + * @param {String} str + * @return {Number} + * @api private + */ + +function parse(str) { + str = String(str); + if (str.length > 100) { + return; + } + var match = /^(-?(?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec( + str + ); + if (!match) { + return; + } + var n = parseFloat(match[1]); + var type = (match[2] || 'ms').toLowerCase(); + switch (type) { + case 'years': + case 'year': + case 'yrs': + case 'yr': + case 'y': + return n * y; + case 'weeks': + case 'week': + case 'w': + return n * w; + case 'days': + case 'day': + case 'd': + return n * d; + case 'hours': + case 'hour': + case 'hrs': + case 'hr': + case 'h': + return n * h; + case 'minutes': + case 'minute': + case 'mins': + case 'min': + case 'm': + return n * m; + case 'seconds': + case 'second': + case 'secs': + case 'sec': + case 's': + return n * s; + case 'milliseconds': + case 'millisecond': + case 'msecs': + case 'msec': + case 'ms': + return n; + default: + return undefined; + } +} + +/** + * Short format for `ms`. + * + * @param {Number} ms + * @return {String} + * @api private + */ + +function fmtShort(ms) { + var msAbs = Math.abs(ms); + if (msAbs >= d) { + return Math.round(ms / d) + 'd'; + } + if (msAbs >= h) { + return Math.round(ms / h) + 'h'; + } + if (msAbs >= m) { + return Math.round(ms / m) + 'm'; + } + if (msAbs >= s) { + return Math.round(ms / s) + 's'; + } + return ms + 'ms'; +} + +/** + * Long format for `ms`. + * + * @param {Number} ms + * @return {String} + * @api private + */ + +function fmtLong(ms) { + var msAbs = Math.abs(ms); + if (msAbs >= d) { + return plural(ms, msAbs, d, 'day'); + } + if (msAbs >= h) { + return plural(ms, msAbs, h, 'hour'); + } + if (msAbs >= m) { + return plural(ms, msAbs, m, 'minute'); + } + if (msAbs >= s) { + return plural(ms, msAbs, s, 'second'); + } + return ms + ' ms'; +} + +/** + * Pluralization helper. + */ + +function plural(ms, msAbs, n, name) { + var isPlural = msAbs >= n * 1.5; + return Math.round(ms / n) + ' ' + name + (isPlural ? 's' : ''); +} + + /***/ }), /***/ 770: @@ -6055,10 +7602,10 @@ module.exports = { /***/ }), -/***/ 8422: +/***/ 75: /***/ ((module) => { -module.exports = eval("require")("debug"); +module.exports = eval("require")("supports-color"); /***/ }), @@ -6167,6 +7714,14 @@ module.exports = require("tls"); /***/ }), +/***/ 2018: +/***/ ((module) => { + +"use strict"; +module.exports = require("tty"); + +/***/ }), + /***/ 7016: /***/ ((module) => { @@ -6195,12 +7750,13 @@ module.exports = require("zlib"); /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; -/*! Axios v1.16.0 Copyright (c) 2026 Matt Zabriskie and contributors */ +/*! Axios v1.18.1 Copyright (c) 2026 Matt Zabriskie and contributors */ var FormData$1 = __nccwpck_require__(6454); var crypto = __nccwpck_require__(6982); var url = __nccwpck_require__(7016); +var HttpsProxyAgent = __nccwpck_require__(3669); var http = __nccwpck_require__(8611); var https = __nccwpck_require__(5692); var http2 = __nccwpck_require__(5675); @@ -6236,6 +7792,52 @@ const { iterator, toStringTag } = Symbol; + +/* Creating a function that will check if an object has a property. */ +const hasOwnProperty = (({ + hasOwnProperty +}) => (obj, prop) => hasOwnProperty.call(obj, prop))(Object.prototype); + +/** + * Walk the prototype chain (excluding the shared Object.prototype) looking for + * an own `prop`. This distinguishes genuine own/inherited members — including + * class accessors and template prototypes — from members injected via + * Object.prototype pollution (e.g. `Object.prototype.username = '...'`), which + * live on Object.prototype itself and are therefore never matched. + * + * @param {*} thing The value whose chain to inspect + * @param {string|symbol} prop The property key to look for + * + * @returns {boolean} True when `prop` is owned below Object.prototype + */ +const hasOwnInPrototypeChain = (thing, prop) => { + let obj = thing; + const seen = []; + while (obj != null && obj !== Object.prototype) { + if (seen.indexOf(obj) !== -1) { + return false; + } + seen.push(obj); + if (hasOwnProperty(obj, prop)) { + return true; + } + obj = getPrototypeOf(obj); + } + return false; +}; + +/** + * Read `obj[prop]` only when it is safe from Object.prototype pollution. Own + * properties and members inherited from a non-Object.prototype source (a class + * instance or template object) are honored; a value reachable only through a + * polluted Object.prototype is ignored and `undefined` is returned. + * + * @param {*} obj The source object + * @param {string|symbol} prop The property key to read + * + * @returns {*} The resolved value, or undefined when unsafe/absent + */ +const getSafeProp = (obj, prop) => obj != null && hasOwnInPrototypeChain(obj, prop) ? obj[prop] : undefined; const kindOf = (cache => thing => { const str = toString.call(thing); return cache[str] || (cache[str] = str.slice(8, -1).toLowerCase()); @@ -6354,11 +7956,15 @@ const isBoolean = thing => thing === true || thing === false; * @returns {boolean} True if value is a plain Object, otherwise false */ const isPlainObject = val => { - if (kindOf(val) !== 'object') { + if (!isObject(val)) { return false; } const prototype = getPrototypeOf(val); - return (prototype === null || prototype === Object.prototype || Object.getPrototypeOf(prototype) === null) && !(toStringTag in val) && !(iterator in val); + return (prototype === null || prototype === Object.prototype || getPrototypeOf(prototype) === null) && + // Treat any genuine (non-Object.prototype-polluted) Symbol.toStringTag or + // Symbol.iterator as evidence the value is a tagged/iterable type rather + // than a plain object, while ignoring keys injected onto Object.prototype. + !hasOwnInPrototypeChain(val, toStringTag) && !hasOwnInPrototypeChain(val, iterator); }; /** @@ -6613,7 +8219,10 @@ function merge(...objs) { if (key === '__proto__' || key === 'constructor' || key === 'prototype') { return; } - const targetKey = caseless && findKey(result, key) || key; + + // findKey lowercases the key, so caseless lookup only applies to strings — + // symbol keys are identity-matched. + const targetKey = caseless && typeof key === 'string' && findKey(result, key) || key; // Read via own-prop only — a bare `result[targetKey]` walks the prototype // chain, so a polluted Object.prototype value could surface here and get // copied into the merged result. @@ -6629,7 +8238,21 @@ function merge(...objs) { } }; for (let i = 0, l = objs.length; i < l; i++) { - objs[i] && forEach(objs[i], assignValue); + const source = objs[i]; + if (!source || isBuffer(source)) { + continue; + } + forEach(source, assignValue); + if (typeof source !== 'object' || isArray(source)) { + continue; + } + const symbols = Object.getOwnPropertySymbols(source); + for (let j = 0; j < symbols.length; j++) { + const symbol = symbols[j]; + if (propertyIsEnumerable.call(source, symbol)) { + assignValue(source[symbol], symbol); + } + } } return result; } @@ -6841,11 +8464,9 @@ const toCamelCase = str => { return p1.toUpperCase() + p2; }); }; - -/* Creating a function that will check if an object has a property. */ -const hasOwnProperty = (({ - hasOwnProperty -}) => (obj, prop) => hasOwnProperty.call(obj, prop))(Object.prototype); +const { + propertyIsEnumerable +} = Object.prototype; /** * Determine if a value is a RegExp object @@ -6934,10 +8555,10 @@ function isSpecCompliantForm(thing) { * @returns {Object} The JSON-compatible object. */ const toJSONObject = obj => { - const stack = new Array(10); - const visit = (source, i) => { + const visited = new WeakSet(); + const visit = source => { if (isObject(source)) { - if (stack.indexOf(source) >= 0) { + if (visited.has(source)) { return; } @@ -6946,19 +8567,20 @@ const toJSONObject = obj => { return source; } if (!('toJSON' in source)) { - stack[i] = source; + // add-on descent / delete-on-ascent: preserves path semantics, so DAG nodes serialise at every occurrence (see #7230). + visited.add(source); const target = isArray(source) ? [] : {}; forEach(source, (value, key) => { - const reducedValue = visit(value, i + 1); + const reducedValue = visit(value); !isUndefined(reducedValue) && (target[key] = reducedValue); }); - stack[i] = undefined; + visited.delete(source); return target; } } return source; }; - return visit(obj, 0); + return visit(obj); }; /** @@ -7019,6 +8641,19 @@ const asap = typeof queueMicrotask !== 'undefined' ? queueMicrotask.bind(_global // ********************* const isIterable = thing => thing != null && isFunction$1(thing[iterator]); + +/** + * Determine if a value is iterable via an iterator that is NOT sourced solely + * from a polluted Object.prototype. Use this instead of `isIterable` whenever + * the iterable comes from untrusted input (e.g. user-supplied header sources), + * so `Object.prototype[Symbol.iterator] = ...` cannot turn an ordinary object + * into an attacker-controlled entries iterator. + * + * @param {*} thing The value to test + * + * @returns {boolean} True if value has a non-polluted iterator + */ +const isSafeIterable = thing => thing != null && hasOwnInPrototypeChain(thing, iterator) && isIterable(thing); var utils$1 = { isArray, isArrayBuffer, @@ -7064,6 +8699,8 @@ var utils$1 = { hasOwnProperty, hasOwnProp: hasOwnProperty, // an alias to avoid ESLint no-prototype-builtins detection + hasOwnInPrototypeChain, + getSafeProp, reduceDescriptors, freezeMethods, toObjectSet, @@ -7079,7 +8716,8 @@ var utils$1 = { isThenable, setImmediate: _setImmediate, asap, - isIterable + isIterable, + isSafeIterable }; // RawAxiosHeaders whose duplicates are ignored by node @@ -7125,8 +8763,6 @@ var parseHeaders = rawHeaders => { return parsed; }; -const $internals = Symbol('internals'); -const INVALID_HEADER_VALUE_CHARS_RE = /[^\x09\x20-\x7E\x80-\xFF]/g; function trimSPorHTAB(str) { let start = 0; let end = str.length; @@ -7146,12 +8782,32 @@ function trimSPorHTAB(str) { } return start === 0 && end === str.length ? str : str.slice(start, end); } + +// The control-code ranges are intentional: header sanitization strips C0/DEL bytes. +// eslint-disable-next-line no-control-regex +const INVALID_UNICODE_HEADER_VALUE_CHARS = new RegExp('[\\u0000-\\u0008\\u000a-\\u001f\\u007f]+', 'g'); +// eslint-disable-next-line no-control-regex +const INVALID_BYTE_STRING_HEADER_VALUE_CHARS = new RegExp('[^\\u0009\\u0020-\\u007e\\u0080-\\u00ff]+', 'g'); +function sanitizeValue(value, invalidChars) { + if (utils$1.isArray(value)) { + return value.map(item => sanitizeValue(item, invalidChars)); + } + return trimSPorHTAB(String(value).replace(invalidChars, '')); +} +const sanitizeHeaderValue = value => sanitizeValue(value, INVALID_UNICODE_HEADER_VALUE_CHARS); +const sanitizeByteStringHeaderValue = value => sanitizeValue(value, INVALID_BYTE_STRING_HEADER_VALUE_CHARS); +function toByteStringHeaderObject(headers) { + const byteStringHeaders = Object.create(null); + utils$1.forEach(headers.toJSON(), (value, header) => { + byteStringHeaders[header] = sanitizeByteStringHeaderValue(value); + }); + return byteStringHeaders; +} + +const $internals = Symbol('internals'); function normalizeHeader(header) { return header && String(header).trim().toLowerCase(); } -function sanitizeHeaderValue(str) { - return trimSPorHTAB(str.replace(INVALID_HEADER_VALUE_CHARS_RE, '')); -} function normalizeValue(value) { if (value === false || value == null) { return value; @@ -7211,7 +8867,7 @@ class AxiosHeaders { function setHeader(_value, _header, _rewrite) { const lHeader = normalizeHeader(_header); if (!lHeader) { - throw new Error('header name must be a non-empty string'); + return; } const key = utils$1.findKey(self, lHeader); if (!key || self[key] === undefined || _rewrite === true || _rewrite === undefined && self[key] !== false) { @@ -7223,15 +8879,21 @@ class AxiosHeaders { setHeaders(header, valueOrRewrite); } else if (utils$1.isString(header) && (header = header.trim()) && !isValidHeaderName(header)) { setHeaders(parseHeaders(header), valueOrRewrite); - } else if (utils$1.isObject(header) && utils$1.isIterable(header)) { - let obj = {}, + } else if (utils$1.isObject(header) && utils$1.isSafeIterable(header)) { + let obj = Object.create(null), dest, key; for (const entry of header) { if (!utils$1.isArray(entry)) { - throw TypeError('Object iterator must return a key-value pair'); + throw new TypeError('Object iterator must return a key-value pair'); + } + key = entry[0]; + if (utils$1.hasOwnProp(obj, key)) { + dest = obj[key]; + obj[key] = utils$1.isArray(dest) ? [...dest, entry[1]] : [dest, entry[1]]; + } else { + obj[key] = entry[1]; } - obj[key = entry[0]] = (dest = obj[key]) ? utils$1.isArray(dest) ? [...dest, entry[1]] : [dest, entry[1]] : entry[1]; } setHeaders(obj, valueOrRewrite); } else { @@ -7443,7 +9105,19 @@ function redactConfig(config, redactKeys) { class AxiosError extends Error { static from(error, code, config, request, response, customProps) { const axiosError = new AxiosError(error.message, code || error.code, config, request, response); - axiosError.cause = error; + // Match native `Error` `cause` semantics: non-enumerable. The wrapped + // error often carries circular internals (sockets, requests, agents), so + // an enumerable `cause` makes structured loggers (pino/winston) and any + // own-property walk throw "Converting circular structure to JSON". + // Regression from #6982; see #7205. `__proto__: null` mirrors the + // `message` descriptor below (prototype-pollution-safe descriptor). + Object.defineProperty(axiosError, 'cause', { + __proto__: null, + value: error, + writable: true, + enumerable: false, + configurable: true + }); axiosError.name = error.name; // Preserve status from the original error if not already set from response @@ -7534,6 +9208,10 @@ AxiosError.ERR_NOT_SUPPORT = 'ERR_NOT_SUPPORT'; AxiosError.ERR_INVALID_URL = 'ERR_INVALID_URL'; AxiosError.ERR_FORM_DATA_DEPTH_EXCEEDED = 'ERR_FORM_DATA_DEPTH_EXCEEDED'; +// Default nesting limit shared with the inverse transform (formDataToJSON) so +// the FormData <-> JSON round-trip stays symmetric. +const DEFAULT_FORM_DATA_MAX_DEPTH = 100; + /** * Determines if the given thing is a array or js object. * @@ -7634,8 +9312,9 @@ function toFormData(obj, formData, options) { const dots = options.dots; const indexes = options.indexes; const _Blob = options.Blob || typeof Blob !== 'undefined' && Blob; - const maxDepth = options.maxDepth === undefined ? 100 : options.maxDepth; + const maxDepth = options.maxDepth === undefined ? DEFAULT_FORM_DATA_MAX_DEPTH : options.maxDepth; const useBlob = _Blob && utils$1.isSpecCompliantForm(formData); + const stack = []; if (!utils$1.isFunction(visitor)) { throw new TypeError('visitor must be a function'); } @@ -7651,10 +9330,38 @@ function toFormData(obj, formData, options) { throw new AxiosError('Blob is not supported. Use a Buffer instead.'); } if (utils$1.isArrayBuffer(value) || utils$1.isTypedArray(value)) { - return useBlob && typeof Blob === 'function' ? new Blob([value]) : Buffer.from(value); + if (useBlob && typeof _Blob === 'function') { + return new _Blob([value]); + } + if (typeof Buffer !== 'undefined') { + return Buffer.from(value); + } + throw new AxiosError('Blob is not supported. Use a Buffer instead.', AxiosError.ERR_NOT_SUPPORT); } return value; } + function throwIfMaxDepthExceeded(depth) { + if (depth > maxDepth) { + throw new AxiosError('Object is too deeply nested (' + depth + ' levels). Max depth: ' + maxDepth, AxiosError.ERR_FORM_DATA_DEPTH_EXCEEDED); + } + } + function stringifyWithDepthLimit(value, depth) { + if (maxDepth === Infinity) { + return JSON.stringify(value); + } + const ancestors = []; + return JSON.stringify(value, function limitDepth(_key, currentValue) { + if (!utils$1.isObject(currentValue)) { + return currentValue; + } + while (ancestors.length && ancestors[ancestors.length - 1] !== this) { + ancestors.pop(); + } + ancestors.push(currentValue); + throwIfMaxDepthExceeded(depth + ancestors.length - 1); + return currentValue; + }); + } /** * Default visitor. @@ -7677,7 +9384,7 @@ function toFormData(obj, formData, options) { // 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); + value = stringifyWithDepthLimit(value, 1); } else if (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); @@ -7695,7 +9402,6 @@ function toFormData(obj, formData, options) { formData.append(renderKey(path, key, dots), convertValue(value)); return false; } - const stack = []; const exposedHelpers = Object.assign(predicates, { defaultVisitor, convertValue, @@ -7703,11 +9409,9 @@ function toFormData(obj, formData, options) { }); function build(value, path, depth = 0) { if (utils$1.isUndefined(value)) return; - if (depth > maxDepth) { - throw new AxiosError('Object is too deeply nested (' + depth + ' levels). Max depth: ' + maxDepth, AxiosError.ERR_FORM_DATA_DEPTH_EXCEEDED); - } + throwIfMaxDepthExceeded(depth); if (stack.indexOf(value) !== -1) { - throw Error('Circular reference detected in ' + path.join('.')); + throw new Error('Circular reference detected in ' + path.join('.')); } stack.push(value); utils$1.forEach(value, function each(el, key) { @@ -7764,9 +9468,7 @@ prototype.append = function append(name, value) { this._pairs.push([name, value]); }; prototype.toString = function toString(encoder) { - const _encode = encoder ? function (value) { - return encoder.call(this, value, encode$1); - } : encode$1; + const _encode = encoder ? value => encoder.call(this, value, encode$1) : encode$1; return this._pairs.map(function each(pair) { return _encode(pair[0]) + '=' + _encode(pair[1]); }, '').join('&'); @@ -7797,11 +9499,16 @@ function buildURL(url, params, options) { if (!params) { return url; } - const _encode = options && options.encode || encode; + url = url || ''; const _options = utils$1.isFunction(options) ? { serialize: options } : options; - const serializeFn = _options && _options.serialize; + + // Read serializer options pollution-safely: own properties and methods on a + // class/template prototype are honored, but values injected onto a polluted + // Object.prototype are ignored. + const _encode = utils$1.getSafeProp(_options, 'encode') || encode; + const serializeFn = utils$1.getSafeProp(_options, 'serialize'); let serializedParams; if (serializeFn) { serializedParams = serializeFn(params, _options); @@ -7889,7 +9596,9 @@ var transitionalDefaults = { silentJSONParsing: true, forcedJSONParsing: true, clarifyTimeoutError: false, - legacyInterceptorReqResOrdering: true + legacyInterceptorReqResOrdering: true, + advertiseZstdAcceptEncoding: false, + validateStatusUndefinedResolves: true }; var URLSearchParams = url.URLSearchParams; @@ -7990,6 +9699,13 @@ function toURLEncodedForm(data, options) { }); } +const MAX_DEPTH = DEFAULT_FORM_DATA_MAX_DEPTH; +function throwIfDepthExceeded(index) { + if (index > MAX_DEPTH) { + throw new AxiosError('FormData field is too deeply nested (' + index + ' levels). Max depth: ' + MAX_DEPTH, AxiosError.ERR_FORM_DATA_DEPTH_EXCEEDED); + } +} + /** * It takes a string like `foo[x][y][z]` and returns an array like `['foo', 'x', 'y', 'z'] * @@ -8002,9 +9718,14 @@ function parsePropPath(name) { // foo.x.y.z // foo-x-y-z // foo x y z - return utils$1.matchAll(/\w+|\[(\w*)]/g, name).map(match => { - return match[0] === '[]' ? '' : match[1] || match[0]; - }); + const path = []; + const pattern = /\w+|\[(\w*)]/g; + let match; + while ((match = pattern.exec(name)) !== null) { + throwIfDepthExceeded(path.length); + path.push(match[0] === '[]' ? '' : match[1] || match[0]); + } + return path; } /** @@ -8036,6 +9757,7 @@ function arrayToObject(arr) { */ function formDataToJSON(formData) { function buildPath(path, value, target, index) { + throwIfDepthExceeded(index); let name = path[index++]; if (name === '__proto__') return true; const isNumericKey = Number.isFinite(+name); @@ -8049,7 +9771,7 @@ function formDataToJSON(formData) { } return !isNumericKey; } - if (!target[name] || !utils$1.isObject(target[name])) { + if (!utils$1.hasOwnProp(target, name) || !utils$1.isObject(target[name])) { target[name] = []; } const result = buildPath(path, value, target[name], index); @@ -8276,6 +9998,24 @@ function combineURLs(baseURL, relativeURL) { return relativeURL ? baseURL.replace(/\/?\/$/, '') + '/' + relativeURL.replace(/^\/+/, '') : baseURL; } +const malformedHttpProtocol = /^https?:(?!\/\/)/i; +const httpProtocolControlCharacters = /[\t\n\r]/g; +function stripLeadingC0ControlOrSpace(url) { + let i = 0; + while (i < url.length && url.charCodeAt(i) <= 0x20) { + i++; + } + return url.slice(i); +} +function normalizeURLForProtocolCheck(url) { + return stripLeadingC0ControlOrSpace(url).replace(httpProtocolControlCharacters, ''); +} +function assertValidHttpProtocolURL(url, config) { + if (typeof url === 'string' && malformedHttpProtocol.test(normalizeURLForProtocolCheck(url))) { + throw new AxiosError('Invalid URL: missing "//" after protocol', AxiosError.ERR_INVALID_URL, config); + } +} + /** * Creates a new URL by combining the baseURL with the requestedURL, * only when the requestedURL is not already an absolute URL. @@ -8286,9 +10026,11 @@ function combineURLs(baseURL, relativeURL) { * * @returns {string} The combined full path */ -function buildFullPath(baseURL, requestedURL, allowAbsoluteUrls) { +function buildFullPath(baseURL, requestedURL, allowAbsoluteUrls, config) { + assertValidHttpProtocolURL(requestedURL, config); let isRelativeUrl = !isAbsoluteURL(requestedURL); if (baseURL && (isRelativeUrl || allowAbsoluteUrls === false)) { + assertValidHttpProtocolURL(baseURL, config); return combineURLs(baseURL, requestedURL); } return requestedURL; @@ -8390,14 +10132,16 @@ function getEnv(key) { return process.env[key.toLowerCase()] || process.env[key.toUpperCase()] || ''; } -const VERSION = "1.16.0"; +const VERSION = "1.18.1"; function parseProtocol(url) { const match = /^([-+\w]{1,25}):(?:\/\/)?/.exec(url); return match && match[1] || ''; } -const DATA_URL_PATTERN = /^(?:([^;]+);)?(?:[^;]+;)?(base64|),([\s\S]*)$/; +// RFC 2397: data:[][;base64], +// mediatype = type/subtype followed by optional ;name=value parameters +const DATA_URL_PATTERN = /^([^,;]+\/[^,;]+)?((?:;[^,;=]+=[^,;]+)*)(;base64)?,([\s\S]*)$/; /** * Parse data uri to a Buffer or Blob @@ -8421,10 +10165,20 @@ function fromDataURI(uri, asBlob, options) { if (!match) { throw new AxiosError('Invalid URL', AxiosError.ERR_INVALID_URL); } - const mime = match[1]; - const isBase64 = match[2]; - const body = match[3]; - const buffer = Buffer.from(decodeURIComponent(body), isBase64 ? 'base64' : 'utf8'); + const type = match[1]; + const params = match[2]; + const encoding = match[3] ? 'base64' : 'utf8'; + const body = match[4]; + + // RFC 2397 section 3: default mediatype is text/plain;charset=US-ASCII + // Bare `data:,` leaves mime undefined; Blob normalises that to "" per spec. + let mime = ''; + if (type) { + mime = params ? type + params : type; + } else if (params) { + mime = 'text/plain' + params; + } + const buffer = encoding === 'base64' ? Buffer.from(body, 'base64') : Buffer.from(decodeURIComponent(body), encoding); if (asBlob) { if (!_Blob) { throw new AxiosError('Blob is not supported', AxiosError.ERR_NOT_SUPPORT); @@ -8617,10 +10371,10 @@ const formDataToStream = (form, headersHandler, options) => { boundary = tag + '-' + platform.generateString(size, BOUNDARY_ALPHABET) } = options || {}; if (!utils$1.isFormData(form)) { - throw TypeError('FormData instance required'); + throw new TypeError('FormData instance required'); } if (boundary.length < 1 || boundary.length > 70) { - throw Error('boundary must be 1-70 characters long'); + throw new Error('boundary must be 1-70 characters long'); } const boundaryBytes = textEncoder.encode('--' + boundary + CRLF); const footerBytes = textEncoder.encode('--' + boundary + '--' + CRLF); @@ -8666,7 +10420,85 @@ class ZlibHeaderTransformStream extends stream.Transform { this.push(header, encoding); } } - this.__transform(chunk, encoding, callback); + this.__transform(chunk, encoding, callback); + } +} + +class Http2Sessions { + constructor() { + this.sessions = Object.create(null); + } + getSession(authority, options) { + options = Object.assign({ + sessionTimeout: 1000 + }, options); + let authoritySessions = this.sessions[authority]; + if (authoritySessions) { + let len = authoritySessions.length; + for (let i = 0; i < len; i++) { + const [sessionHandle, sessionOptions] = authoritySessions[i]; + if (!sessionHandle.destroyed && !sessionHandle.closed && util.isDeepStrictEqual(sessionOptions, options)) { + return sessionHandle; + } + } + } + const session = http2.connect(authority, options); + let removed; + let timer; + const removeSession = () => { + if (removed) { + return; + } + removed = true; + if (timer) { + clearTimeout(timer); + timer = null; + } + let entries = authoritySessions, + len = entries.length, + i = len; + while (i--) { + if (entries[i][0] === session) { + if (len === 1) { + delete this.sessions[authority]; + } else { + entries.splice(i, 1); + } + if (!session.closed) { + session.close(); + } + return; + } + } + }; + const originalRequestFn = session.request; + const { + sessionTimeout + } = options; + if (sessionTimeout != null) { + let streamsCount = 0; + session.request = function () { + const stream = originalRequestFn.apply(this, arguments); + streamsCount++; + if (timer) { + clearTimeout(timer); + timer = null; + } + stream.once('close', () => { + if (! --streamsCount) { + timer = setTimeout(() => { + timer = null; + removeSession(); + }, sessionTimeout); + } + }); + return stream; + }; + } + session.once('close', removeSession); + let entry = [session, options]; + authoritySessions ? authoritySessions.push(entry) : authoritySessions = this.sessions[authority] = [entry]; + return session; } } @@ -8683,13 +10515,34 @@ const callbackify = (fn, reducer) => { } : fn; }; -const LOOPBACK_HOSTNAMES = new Set(['localhost']); +const LOOPBACK_HOSTNAMES = new Set(['localhost', '0.0.0.0']); const isIPv4Loopback = host => { const parts = host.split('.'); if (parts.length !== 4) return false; if (parts[0] !== '127') return false; return parts.every(p => /^\d+$/.test(p) && Number(p) >= 0 && Number(p) <= 255); }; +const isIPv6ZeroGroup = group => /^0{1,4}$/.test(group); + +// The unspecified address (IPv4 0.0.0.0 / IPv6 ::) resolves to the local host +// for outbound connections, so treat it as loopback-equivalent for NO_PROXY +// matching. 0.0.0.0 is covered by LOOPBACK_HOSTNAMES; this handles compressed +// and full IPv6 all-zero forms so both families bypass symmetrically. +const isIPv6Unspecified = host => { + if (host === '::') return true; + const compressionIndex = host.indexOf('::'); + if (compressionIndex !== -1) { + if (compressionIndex !== host.lastIndexOf('::')) return false; + const left = host.slice(0, compressionIndex); + const right = host.slice(compressionIndex + 2); + const leftGroups = left ? left.split(':') : []; + const rightGroups = right ? right.split(':') : []; + const explicitGroups = leftGroups.length + rightGroups.length; + return explicitGroups < 8 && leftGroups.every(isIPv6ZeroGroup) && rightGroups.every(isIPv6ZeroGroup); + } + const groups = host.split(':'); + return groups.length === 8 && groups.every(isIPv6ZeroGroup); +}; const isIPv6Loopback = host => { // Collapse all-zero groups: any form of ::1 / 0:0:...:0:1 // First, strip any leading "::" by normalising with Set lookup of common forms, @@ -8722,6 +10575,7 @@ const isLoopback = host => { if (!host) return false; if (LOOPBACK_HOSTNAMES.has(host)) return true; if (isIPv4Loopback(host)) return true; + if (isIPv6Unspecified(host)) return true; return isIPv6Loopback(host); }; const DEFAULT_PORTS = { @@ -8904,6 +10758,9 @@ const progressEventReducer = (listener, isDownloadStream, freq = 3) => { let bytesNotified = 0; const _speedometer = speedometer(50, 250); return throttle(e => { + if (!e || typeof e.loaded !== 'number') { + return; + } const rawLoaded = e.loaded; const total = e.lengthComputable ? e.total : undefined; const loaded = total != null ? Math.min(rawLoaded, total) : rawLoaded; @@ -8938,11 +10795,13 @@ const asyncDecorator = fn => (...args) => utils$1.asap(() => fn(...args)); * Estimate decoded byte length of a data:// URL *without* allocating large buffers. * - For base64: compute exact decoded size using length and padding; * handle %XX at the character-count level (no string allocation). - * - For non-base64: use UTF-8 byteLength of the encoded body as a safe upper bound. + * - For non-base64: compute the exact percent-decoded UTF-8 byte length. * * @param {string} url * @returns {number} */ +const isHexDigit = charCode => charCode >= 48 && charCode <= 57 || charCode >= 65 && charCode <= 70 || charCode >= 97 && charCode <= 102; +const isPercentEncodedByte = (str, i, len) => i + 2 < len && isHexDigit(str.charCodeAt(i + 1)) && isHexDigit(str.charCodeAt(i + 2)); function estimateDataURLDecodedBytes(url) { if (!url || typeof url !== 'string') return 0; if (!url.startsWith('data:')) return 0; @@ -8959,7 +10818,7 @@ function estimateDataURLDecodedBytes(url) { if (body.charCodeAt(i) === 37 /* '%' */ && i + 2 < len) { const a = body.charCodeAt(i + 1); const b = body.charCodeAt(i + 2); - const isHex = (a >= 48 && a <= 57 || a >= 65 && a <= 70 || a >= 97 && a <= 102) && (b >= 48 && b <= 57 || b >= 65 && b <= 70 || b >= 97 && b <= 102); + const isHex = isHexDigit(a) && isHexDigit(b); if (isHex) { effectiveLen -= 2; i += 2; @@ -8994,18 +10853,18 @@ function estimateDataURLDecodedBytes(url) { const bytes = groups * 3 - (pad || 0); return bytes > 0 ? bytes : 0; } - if (typeof Buffer !== 'undefined' && typeof Buffer.byteLength === 'function') { - return Buffer.byteLength(body, 'utf8'); - } // Compute UTF-8 byte length directly from UTF-16 code units without allocating // a byte buffer (TextEncoder.encode would defeat the DoS guard on large bodies). - // Using body.length here would undercount non-ASCII (e.g. '€' is 1 code unit - // but 3 UTF-8 bytes). + // Valid %XX triplets count as one decoded byte; this matches the bytes that + // decodeURIComponent(body) would produce before Buffer re-encodes the string. let bytes = 0; for (let i = 0, len = body.length; i < len; i++) { const c = body.charCodeAt(i); - if (c < 0x80) { + if (c === 37 /* '%' */ && isPercentEncodedByte(body, i, len)) { + bytes += 1; + i += 2; + } else if (c < 0x80) { bytes += 1; } else if (c < 0x800) { bytes += 2; @@ -9032,7 +10891,14 @@ const brotliOptions = { flush: zlib.constants.BROTLI_OPERATION_FLUSH, finishFlush: zlib.constants.BROTLI_OPERATION_FLUSH }; +const zstdOptions = { + flush: zlib.constants.ZSTD_e_flush, + finishFlush: zlib.constants.ZSTD_e_flush +}; const isBrotliSupported = utils$1.isFunction(zlib.createBrotliDecompress); +const isZstdSupported = utils$1.isFunction(zlib.createZstdDecompress); +const ACCEPT_ENCODING = 'gzip, compress, deflate' + (isBrotliSupported ? ', br' : ''); +const ACCEPT_ENCODING_WITH_ZSTD = ACCEPT_ENCODING + (isZstdSupported ? ', zstd' : ''); const { http: httpFollow, https: httpsFollow @@ -9055,6 +10921,78 @@ function setFormDataHeaders$1(headers, formHeaders, policy) { // the request currently owning that socket across keep-alive reuse (issue #10780). const kAxiosSocketListener = Symbol('axios.http.socketListener'); const kAxiosCurrentReq = Symbol('axios.http.currentReq'); + +// Tags HttpsProxyAgent instances installed by setProxy() so the redirect path +// can strip them without clobbering a user-supplied agent that happens to be +// an HttpsProxyAgent. +const kAxiosInstalledTunnel = Symbol('axios.http.installedTunnel'); + +// Cache of CONNECT-tunneling agents keyed by proxy config so repeat requests +// through the same proxy reuse a single agent (and its socket pool). The +// keyspace is bounded by the set of distinct proxy configs the process uses, +// so unbounded growth is not a concern in practice. +const tunnelingAgentCache = new Map(); +const tunnelingAgentCacheUser = new WeakMap(); +// Minimum minor versions where Node's HTTP Agent supports native proxyEnv +// handling. Checking the selected agent below also covers startup modes such +// as NODE_OPTIONS=--use-env-proxy and --no-use-env-proxy precedence. +const NODE_NATIVE_ENV_PROXY_SUPPORT = { + 22: 21, + 24: 5 +}; +function isNodeNativeEnvProxySupported(nodeVersion = process.versions && process.versions.node) { + if (!nodeVersion) { + return false; + } + const [major, minor] = nodeVersion.split('.').map(part => Number(part)); + if (!Number.isInteger(major) || !Number.isInteger(minor)) { + return false; + } + if (major > 24) { + return true; + } + return NODE_NATIVE_ENV_PROXY_SUPPORT[major] != null && minor >= NODE_NATIVE_ENV_PROXY_SUPPORT[major]; +} +function isNodeEnvProxyEnabled(agent, nodeVersion = process.versions && process.versions.node) { + if (!isNodeNativeEnvProxySupported(nodeVersion)) { + return false; + } + const agentOptions = agent && agent.options; + return Boolean(agentOptions && utils$1.hasOwnProp(agentOptions, 'proxyEnv') && agentOptions.proxyEnv != null); +} +function getProxyEnvAgent(options, configHttpAgent, configHttpsAgent) { + return isHttps.test(options.protocol) ? configHttpsAgent || https.globalAgent : configHttpAgent || http.globalAgent; +} +function getTunnelingAgent(agentOptions, userHttpsAgent) { + const key = agentOptions.protocol + '//' + agentOptions.hostname + ':' + (agentOptions.port || '') + '#' + (agentOptions.auth || ''); + const cache = userHttpsAgent ? tunnelingAgentCacheUser.get(userHttpsAgent) || tunnelingAgentCacheUser.set(userHttpsAgent, new Map()).get(userHttpsAgent) : tunnelingAgentCache; + let agent = cache.get(key); + if (agent) return agent; + // Forward the user's TLS options (custom CA, rejectUnauthorized, client cert, + // etc.) into the tunneling agent so they apply to the origin TLS upgrade + // performed after CONNECT. Our proxy fields take precedence on conflict. + const merged = userHttpsAgent && userHttpsAgent.options ? { + ...userHttpsAgent.options, + ...agentOptions + } : agentOptions; + agent = new HttpsProxyAgent(merged); + if (userHttpsAgent && userHttpsAgent.options) { + const originTLSOptions = { + ...userHttpsAgent.options + }; + const callback = agent.callback; + agent.callback = function axiosTunnelingAgentCallback(req, opts) { + // HttpsProxyAgent v5 reads callback opts for the post-CONNECT origin TLS upgrade. + return callback.call(this, req, { + ...originTLSOptions, + ...opts + }); + }; + } + agent[kAxiosInstalledTunnel] = true; + cache.set(key, agent); + return agent; +} const supportedProtocols = platform.protocols.map(protocol => { return protocol + ':'; }); @@ -9063,7 +11001,7 @@ const supportedProtocols = platform.protocols.map(protocol => { // Decode before composing the `auth` option so credentials such as // `my%40email.com:pass` are sent as `my@email.com:pass`. Falls back to the // original value for malformed input so a bad encoding never throws. -const decodeURIComponentSafe = value => { +const decodeURIComponentSafe$1 = value => { if (!utils$1.isString(value)) { return value; } @@ -9077,84 +11015,11 @@ const flushOnFinish = (stream, [throttled, flush]) => { stream.on('end', flush).on('error', flush); return throttled; }; -class Http2Sessions { - constructor() { - this.sessions = Object.create(null); - } - getSession(authority, options) { - options = Object.assign({ - sessionTimeout: 1000 - }, options); - let authoritySessions = this.sessions[authority]; - if (authoritySessions) { - let len = authoritySessions.length; - for (let i = 0; i < len; i++) { - const [sessionHandle, sessionOptions] = authoritySessions[i]; - if (!sessionHandle.destroyed && !sessionHandle.closed && util.isDeepStrictEqual(sessionOptions, options)) { - return sessionHandle; - } - } - } - const session = http2.connect(authority, options); - let removed; - const removeSession = () => { - if (removed) { - return; - } - removed = true; - let entries = authoritySessions, - len = entries.length, - i = len; - while (i--) { - if (entries[i][0] === session) { - if (len === 1) { - delete this.sessions[authority]; - } else { - entries.splice(i, 1); - } - if (!session.closed) { - session.close(); - } - return; - } - } - }; - const originalRequestFn = session.request; - const { - sessionTimeout - } = options; - if (sessionTimeout != null) { - let timer; - let streamsCount = 0; - session.request = function () { - const stream = originalRequestFn.apply(this, arguments); - streamsCount++; - if (timer) { - clearTimeout(timer); - timer = null; - } - stream.once('close', () => { - if (! --streamsCount) { - timer = setTimeout(() => { - timer = null; - removeSession(); - }, sessionTimeout); - } - }); - return stream; - }; - } - session.once('close', removeSession); - let entry = [session, options]; - authoritySessions ? authoritySessions.push(entry) : authoritySessions = this.sessions[authority] = [entry]; - return session; - } -} const http2Sessions = new Http2Sessions(); /** - * If the proxy or config beforeRedirects functions are defined, call them with the options - * object. + * If the proxy, auth, sensitive header, or config beforeRedirects functions are defined, + * call them with the options object. * * @param {Object} options - The options object that was passed to the request. * @@ -9164,10 +11029,37 @@ function dispatchBeforeRedirect(options, responseDetails, requestDetails) { if (options.beforeRedirects.proxy) { options.beforeRedirects.proxy(options); } + if (options.beforeRedirects.auth) { + options.beforeRedirects.auth(options); + } + if (options.beforeRedirects.sensitiveHeaders) { + options.beforeRedirects.sensitiveHeaders(options, requestDetails); + } if (options.beforeRedirects.config) { options.beforeRedirects.config(options, responseDetails, requestDetails); } } +function stripMatchingHeaders(headers, sensitiveSet) { + if (!headers) { + return; + } + Object.keys(headers).forEach(header => { + if (sensitiveSet.has(header.toLowerCase())) { + delete headers[header]; + } + }); +} +function isSameOriginRedirect(redirectOptions, requestDetails) { + if (!requestDetails) { + return false; + } + try { + return new URL(requestDetails.url).origin === new URL(redirectOptions.href).origin; + } catch (e) { + // If origin comparison fails, treat the redirect as unsafe. + return false; + } +} /** * If the proxy or config afterRedirects functions are defined, call them with the options @@ -9178,9 +11070,10 @@ function dispatchBeforeRedirect(options, responseDetails, requestDetails) { * * @returns {http.ClientRequestArgs} */ -function setProxy(options, configProxy, location, isRedirect) { +function setProxy(options, configProxy, location, isRedirect, configHttpsAgent, configHttpAgent) { let proxy = configProxy; - if (!proxy && proxy !== false) { + const proxyEnvAgent = getProxyEnvAgent(options, configHttpAgent, configHttpsAgent); + if (!proxy && proxy !== false && !isNodeEnvProxyEnabled(proxyEnvAgent)) { const proxyUrl = getProxyForUrl(location); if (proxyUrl) { if (!shouldBypassProxy(location)) { @@ -9199,6 +11092,13 @@ function setProxy(options, configProxy, location, isRedirect) { } } } + // Strip any tunneling agent we installed for the previous hop so a redirect + // that drops the proxy or crosses an HTTPS↔HTTP boundary doesn't reuse a + // stale one. Match on our Symbol marker so a user-supplied HttpsProxyAgent + // (which won't carry the marker) is left alone. + if (isRedirect && options.agent && options.agent[kAxiosInstalledTunnel]) { + options.agent = undefined; + } if (proxy) { // Read proxy fields without traversing the prototype chain. URL instances expose // username/password/hostname/host/port/protocol via getters on URL.prototype (so @@ -9231,37 +11131,84 @@ function setProxy(options, configProxy, location, isRedirect) { proxy }); } - const base64 = Buffer.from(proxyAuth, 'utf8').toString('base64'); - options.headers['Proxy-Authorization'] = 'Basic ' + base64; } + const targetIsHttps = isHttps.test(options.protocol); + if (targetIsHttps) { + // CONNECT-tunneling path for HTTPS targets. Preserves end-to-end TLS to + // the origin so the proxy cannot inspect the URL, headers, or body — the + // behavior already promised by THREATMODEL.md (T-R9). HttpsProxyAgent + // sends Proxy-Authorization on the CONNECT request only, never on the + // wrapped TLS request, which is why we don't stamp it onto + // options.headers here. If the user already supplied an HttpsProxyAgent, + // they own tunneling end-to-end and we leave them alone; otherwise we + // install our own tunneling agent and forward their TLS options (if any) + // so a custom httpsAgent for cert pinning / rejectUnauthorized still + // applies to the origin TLS upgrade. + if (!(configHttpsAgent instanceof HttpsProxyAgent)) { + const proxyHost = readProxyField('hostname') || readProxyField('host'); + const proxyPort = readProxyField('port'); + const rawProxyProtocol = readProxyField('protocol'); + const normalizedProtocol = rawProxyProtocol ? rawProxyProtocol.includes(':') ? rawProxyProtocol : `${rawProxyProtocol}:` : 'http:'; + // Bracket IPv6 literals for URL parsing; URL.hostname strips the + // brackets again on read so the agent receives the raw form. + const proxyHostForURL = proxyHost && proxyHost.includes(':') && !proxyHost.startsWith('[') ? `[${proxyHost}]` : proxyHost; + const proxyURL = new URL(`${normalizedProtocol}//${proxyHostForURL}${proxyPort ? ':' + proxyPort : ''}`); + const agentOptions = { + protocol: proxyURL.protocol, + hostname: proxyURL.hostname.replace(/^\[|\]$/g, ''), + port: proxyURL.port, + auth: proxyAuth && typeof proxyAuth === 'string' ? proxyAuth : undefined + }; + if (proxyURL.protocol === 'https:') { + agentOptions.ALPNProtocols = ['http/1.1']; + } + const tunnelingAgent = getTunnelingAgent(agentOptions, configHttpsAgent); + // Set both: `options.agent` is consumed by the native https.request path + // (maxRedirects === 0); `options.agents.https` is consumed by + // follow-redirects, which ignores `options.agent` when `options.agents` + // is present. + options.agent = tunnelingAgent; + if (options.agents) { + options.agents.https = tunnelingAgent; + } + } + } else { + // Forward-proxy mode for plaintext HTTP targets. The request line carries + // the absolute URL and the proxy sees everything — acceptable for plain + // HTTP since the wire was already plaintext. + if (proxyAuth) { + const base64 = Buffer.from(proxyAuth, 'utf8').toString('base64'); + options.headers['Proxy-Authorization'] = 'Basic ' + base64; + } - // Preserve a user-supplied Host header (case-insensitive) so callers can override - // the value forwarded to the proxy; otherwise default to the request URL's host. - let hasUserHostHeader = false; - for (const name of Object.keys(options.headers)) { - if (name.toLowerCase() === 'host') { - hasUserHostHeader = true; - break; + // Preserve a user-supplied Host header (case-insensitive) so callers can override + // the value forwarded to the proxy; otherwise default to the request URL's host. + let hasUserHostHeader = false; + for (const name of Object.keys(options.headers)) { + if (name.toLowerCase() === 'host') { + hasUserHostHeader = true; + break; + } + } + if (!hasUserHostHeader) { + options.headers.host = options.hostname + (options.port ? ':' + options.port : ''); + } + const proxyHost = readProxyField('hostname') || readProxyField('host'); + options.hostname = proxyHost; + // Replace 'host' since options is not a URL object + options.host = proxyHost; + options.port = readProxyField('port'); + options.path = location; + const proxyProtocol = readProxyField('protocol'); + if (proxyProtocol) { + options.protocol = proxyProtocol.includes(':') ? proxyProtocol : `${proxyProtocol}:`; } - } - if (!hasUserHostHeader) { - options.headers.host = options.hostname + (options.port ? ':' + options.port : ''); - } - const proxyHost = readProxyField('hostname') || readProxyField('host'); - options.hostname = proxyHost; - // Replace 'host' since options is not a URL object - options.host = proxyHost; - options.port = readProxyField('port'); - options.path = location; - const proxyProtocol = readProxyField('protocol'); - if (proxyProtocol) { - options.protocol = proxyProtocol.includes(':') ? proxyProtocol : `${proxyProtocol}:`; } } options.beforeRedirects.proxy = function beforeRedirect(redirectOptions) { // Configure proxy for redirected request, passing the original config proxy to apply // the exact same logic as if the redirected request was performed by axios directly. - setProxy(redirectOptions, configProxy, redirectOptions.href, true); + setProxy(redirectOptions, configProxy, redirectOptions.href, true, configHttpsAgent, configHttpAgent); }; } const isHttpAdapterSupported = typeof process !== 'undefined' && utils$1.kindOf(process) === 'process'; @@ -9344,16 +11291,30 @@ const http2Transport = { /*eslint consistent-return:0*/ var httpAdapter = isHttpAdapterSupported && function httpAdapter(config) { return wrapAsync(async function dispatchHttpRequest(resolve, reject, onDone) { - const own = key => utils$1.hasOwnProp(config, key) ? config[key] : undefined; + // Read config pollution-safely: own properties and members inherited from + // a non-Object.prototype source (e.g. an Object.create(defaults) template) + // are honored, but values injected onto a polluted Object.prototype are + // ignored. All behavior-affecting reads in this adapter go through own() + // so the protection boundary stays consistent. + const own = key => utils$1.getSafeProp(config, key); + const transitional = own('transitional') || transitionalDefaults; let data = own('data'); let lookup = own('lookup'); let family = own('family'); let httpVersion = own('httpVersion'); if (httpVersion === undefined) httpVersion = 1; let http2Options = own('http2Options'); + const httpAgent = own('httpAgent'); + const httpsAgent = own('httpsAgent'); + const configProxy = own('proxy'); const responseType = own('responseType'); const responseEncoding = own('responseEncoding'); - const method = config.method.toUpperCase(); + const socketPath = own('socketPath'); + const method = own('method').toUpperCase(); + const maxRedirects = own('maxRedirects'); + const maxBodyLength = own('maxBodyLength'); + const maxContentLength = own('maxContentLength'); + const decompress = own('decompress'); let isDone; let rejected = false; let req; @@ -9384,7 +11345,7 @@ var httpAdapter = isHttpAdapterSupported && function httpAdapter(config) { try { abortEmitter.emit('abort', !reason || reason.type ? new CanceledError(null, config, req) : reason); } catch (err) { - console.warn('emit error', err); + // ignore emit errors } } function clearConnectPhaseTimer() { @@ -9394,10 +11355,11 @@ var httpAdapter = isHttpAdapterSupported && function httpAdapter(config) { } } function createTimeoutError() { - let timeoutErrorMessage = config.timeout ? 'timeout of ' + config.timeout + 'ms exceeded' : 'timeout exceeded'; - const transitional = config.transitional || transitionalDefaults; - if (config.timeoutErrorMessage) { - timeoutErrorMessage = config.timeoutErrorMessage; + const configTimeout = own('timeout'); + let timeoutErrorMessage = configTimeout ? 'timeout of ' + configTimeout + 'ms exceeded' : 'timeout exceeded'; + const configTimeoutErrorMessage = own('timeoutErrorMessage'); + if (configTimeoutErrorMessage) { + timeoutErrorMessage = configTimeoutErrorMessage; } return new AxiosError(timeoutErrorMessage, transitional.clarifyTimeoutError ? AxiosError.ETIMEDOUT : AxiosError.ECONNABORTED, config, req); } @@ -9440,17 +11402,22 @@ var httpAdapter = isHttpAdapterSupported && function httpAdapter(config) { }); // Parse url - const fullPath = buildFullPath(config.baseURL, config.url, config.allowAbsoluteUrls); - const parsed = new URL(fullPath, platform.hasBrowserEnv ? platform.origin : undefined); + const fullPath = buildFullPath(own('baseURL'), own('url'), own('allowAbsoluteUrls'), config); + // Unix-socket requests (own socketPath) commonly pass a path-only url + // like '/foo'; supply a synthetic base so new URL() can still parse it. + // Use the own-property value (not config.socketPath) so a polluted + // prototype cannot influence URL base selection. + const urlBase = socketPath ? 'http://localhost' : platform.hasBrowserEnv ? platform.origin : undefined; + const parsed = new URL(fullPath, urlBase); const protocol = parsed.protocol || supportedProtocols[0]; if (protocol === 'data:') { // Apply the same semantics as HTTP: only enforce if a finite, non-negative cap is set. - if (config.maxContentLength > -1) { - // Use the exact string passed to fromDataURI (config.url); fall back to fullPath if needed. - const dataUrl = String(config.url || fullPath || ''); + if (maxContentLength > -1) { + // Use the exact string passed to fromDataURI (the configured url); fall back to fullPath if needed. + const dataUrl = String(own('url') || fullPath || ''); const estimated = estimateDataURLDecodedBytes(dataUrl); - if (estimated > config.maxContentLength) { - return reject(new AxiosError('maxContentLength size of ' + config.maxContentLength + ' exceeded', AxiosError.ERR_BAD_RESPONSE, config)); + if (estimated > maxContentLength) { + return reject(new AxiosError('maxContentLength size of ' + maxContentLength + ' exceeded', AxiosError.ERR_BAD_RESPONSE, config)); } } let convertedData; @@ -9463,7 +11430,7 @@ var httpAdapter = isHttpAdapterSupported && function httpAdapter(config) { }); } try { - convertedData = fromDataURI(config.url, responseType === 'blob', { + convertedData = fromDataURI(own('url'), responseType === 'blob', { Blob: config.env && config.env.Blob }); } catch (err) { @@ -9537,7 +11504,7 @@ var httpAdapter = isHttpAdapterSupported && function httpAdapter(config) { // Add Content-Length header if data exists headers.setContentLength(data.length, false); - if (config.maxBodyLength > -1 && data.length > config.maxBodyLength) { + if (maxBodyLength > -1 && data.length > maxBodyLength) { return reject(new AxiosError('Request body larger than maxBodyLength limit', AxiosError.ERR_BAD_REQUEST, config)); } } @@ -9564,37 +11531,36 @@ var httpAdapter = isHttpAdapterSupported && function httpAdapter(config) { let auth = undefined; const configAuth = own('auth'); if (configAuth) { - const username = configAuth.username || ''; - const password = configAuth.password || ''; + const username = utils$1.getSafeProp(configAuth, 'username') || ''; + const password = utils$1.getSafeProp(configAuth, 'password') || ''; auth = username + ':' + password; } - if (!auth && parsed.username) { - const urlUsername = decodeURIComponentSafe(parsed.username); - const urlPassword = decodeURIComponentSafe(parsed.password); + if (!auth && (parsed.username || parsed.password)) { + const urlUsername = decodeURIComponentSafe$1(parsed.username); + const urlPassword = decodeURIComponentSafe$1(parsed.password); auth = urlUsername + ':' + urlPassword; } auth && headers.delete('authorization'); let path$1; try { - path$1 = buildURL(parsed.pathname + parsed.search, config.params, config.paramsSerializer).replace(/^\?/, ''); + path$1 = buildURL(parsed.pathname + parsed.search, own('params'), own('paramsSerializer')).replace(/^\?/, ''); } catch (err) { - const customErr = new Error(err.message); - customErr.config = config; - customErr.url = config.url; - customErr.exists = true; - return reject(customErr); + return reject(AxiosError.from(err, AxiosError.ERR_BAD_REQUEST, config, null, null, { + url: own('url'), + exists: true + })); } - headers.set('Accept-Encoding', 'gzip, compress, deflate' + (isBrotliSupported ? ', br' : ''), false); + headers.set('Accept-Encoding', utils$1.hasOwnProp(transitional, 'advertiseZstdAcceptEncoding') && transitional.advertiseZstdAcceptEncoding === true ? ACCEPT_ENCODING_WITH_ZSTD : ACCEPT_ENCODING, false); // Null-prototype to block prototype pollution gadgets on properties read // directly by Node's http.request (e.g. insecureHTTPParser, lookup). const options = Object.assign(Object.create(null), { path: path$1, method: method, - headers: headers.toJSON(), + headers: toByteStringHeaderObject(headers), agents: { - http: config.httpAgent, - https: config.httpsAgent + http: httpAgent, + https: httpsAgent }, auth, protocol, @@ -9606,52 +11572,105 @@ var httpAdapter = isHttpAdapterSupported && function httpAdapter(config) { // cacheable-lookup integration hotfix !utils$1.isUndefined(lookup) && (options.lookup = lookup); - if (config.socketPath) { - if (typeof config.socketPath !== 'string') { + if (socketPath) { + if (typeof socketPath !== 'string') { return reject(new AxiosError('socketPath must be a string', AxiosError.ERR_BAD_OPTION_VALUE, config)); } - if (config.allowedSocketPaths != null) { - const allowed = Array.isArray(config.allowedSocketPaths) ? config.allowedSocketPaths : [config.allowedSocketPaths]; - const resolvedSocket = path.resolve(config.socketPath); + const allowedSocketPaths = own('allowedSocketPaths'); + if (allowedSocketPaths != null) { + const allowed = Array.isArray(allowedSocketPaths) ? allowedSocketPaths : [allowedSocketPaths]; + const resolvedSocket = path.resolve(socketPath); const isAllowed = allowed.some(entry => typeof entry === 'string' && path.resolve(entry) === resolvedSocket); if (!isAllowed) { - return reject(new AxiosError(`socketPath "${config.socketPath}" is not permitted by allowedSocketPaths`, AxiosError.ERR_BAD_OPTION_VALUE, config)); + return reject(new AxiosError(`socketPath "${socketPath}" is not permitted by allowedSocketPaths`, AxiosError.ERR_BAD_OPTION_VALUE, config)); } } - options.socketPath = config.socketPath; + options.socketPath = socketPath; } else { options.hostname = parsed.hostname.startsWith('[') ? parsed.hostname.slice(1, -1) : parsed.hostname; options.port = parsed.port; - setProxy(options, config.proxy, protocol + '//' + parsed.hostname + (parsed.port ? ':' + parsed.port : '') + options.path); + setProxy(options, configProxy, protocol + '//' + parsed.hostname + (parsed.port ? ':' + parsed.port : '') + options.path, false, httpsAgent, httpAgent); } let transport; let isNativeTransport = false; + // True only for the follow-redirects transport, which applies + // options.maxBodyLength itself. Every other transport (http2, native + // http/https, a user-supplied custom transport) needs the explicit + // byte-counting pipeline below to enforce maxBodyLength on streamed uploads. + let transportEnforcesMaxBodyLength = false; const isHttpsRequest = isHttps.test(options.protocol); - options.agent = isHttpsRequest ? config.httpsAgent : config.httpAgent; + // Don't clobber a CONNECT-tunneling agent installed by setProxy() for an + // HTTPS target. + if (options.agent == null) { + options.agent = isHttpsRequest ? httpsAgent : httpAgent; + } if (isHttp2) { transport = http2Transport; } else { const configTransport = own('transport'); if (configTransport) { transport = configTransport; - } else if (config.maxRedirects === 0) { + } else if (maxRedirects === 0) { transport = isHttpsRequest ? https : http; isNativeTransport = true; } else { - if (config.maxRedirects) { - options.maxRedirects = config.maxRedirects; + transportEnforcesMaxBodyLength = true; + options.sensitiveHeaders = []; + if (maxRedirects) { + options.maxRedirects = maxRedirects; } const configBeforeRedirect = own('beforeRedirect'); if (configBeforeRedirect) { options.beforeRedirects.config = configBeforeRedirect; } + if (auth) { + // Restore HTTP Basic credentials on same-origin redirects only. + // follow-redirects >= 1.15.8 strips Authorization on every redirect (see #6929); + // cross-origin stripping is the documented mitigation for T-R2 in THREATMODEL.md + // and is preserved by deliberately not restoring on origin change. + const requestOrigin = parsed.origin; + const authToRestore = auth; + options.beforeRedirects.auth = function beforeRedirectAuth(redirectOptions) { + try { + if (new URL(redirectOptions.href).origin === requestOrigin) { + redirectOptions.auth = authToRestore; + } + } catch (e) { + // ignore malformed URL: leaving auth stripped is fail-safe + } + }; + } + const sensitiveHeaders = own('sensitiveHeaders'); + if (sensitiveHeaders != null) { + if (!utils$1.isArray(sensitiveHeaders)) { + return reject(new AxiosError('sensitiveHeaders must be an array of strings', AxiosError.ERR_BAD_OPTION_VALUE, config)); + } + const sensitiveSet = new Set(); + for (const header of sensitiveHeaders) { + if (!utils$1.isString(header)) { + return reject(new AxiosError('sensitiveHeaders must be an array of strings', AxiosError.ERR_BAD_OPTION_VALUE, config)); + } + sensitiveSet.add(header.toLowerCase()); + } + if (sensitiveSet.size) { + options.sensitiveHeaders = Array.from(sensitiveSet); + options.beforeRedirects.sensitiveHeaders = function beforeRedirectSensitiveHeaders(redirectOptions, requestDetails) { + if (!isSameOriginRedirect(redirectOptions, requestDetails)) { + stripMatchingHeaders(redirectOptions.headers, sensitiveSet); + } + }; + } + } transport = isHttpsRequest ? httpsFollow : httpFollow; } } - if (config.maxBodyLength > -1) { - options.maxBodyLength = config.maxBodyLength; + + // Set an explicit maxBodyLength option for transports that inspect it. + // When maxBodyLength is -1 (default/unlimited), use Infinity so + // follow-redirects does not fall back to its own 10MB default. + if (maxBodyLength > -1) { + options.maxBodyLength = maxBodyLength; } else { - // follow-redirects does not skip comparison, so it should always succeed for axios -1 unlimited options.maxBodyLength = Infinity; } @@ -9681,7 +11700,7 @@ var httpAdapter = isHttpAdapterSupported && function httpAdapter(config) { const lastRequest = res.req || req; // if decompress disabled we should not decompress - if (config.decompress !== false && res.headers['content-encoding']) { + if (decompress !== false && res.headers['content-encoding']) { // if no content, but headers still say that it is encoded, // remove the header not confuse downstream operations if (method === 'HEAD' || res.statusCode === 204) { @@ -9713,6 +11732,13 @@ var httpAdapter = isHttpAdapterSupported && function httpAdapter(config) { streams.push(zlib.createBrotliDecompress(brotliOptions)); delete res.headers['content-encoding']; } + break; + case 'zstd': + if (isZstdSupported) { + streams.push(zlib.createZstdDecompress(zstdOptions)); + delete res.headers['content-encoding']; + } + break; } } responseStream = streams.length > 1 ? stream.pipeline(streams, utils$1.noop) : streams[0]; @@ -9726,8 +11752,8 @@ var httpAdapter = isHttpAdapterSupported && function httpAdapter(config) { if (responseType === 'stream') { // Enforce maxContentLength on streamed responses; previously this // was applied only to buffered responses. - if (config.maxContentLength > -1) { - const limit = config.maxContentLength; + if (maxContentLength > -1) { + const limit = maxContentLength; const source = responseStream; async function* enforceMaxContentLength() { let totalResponseBytes = 0; @@ -9753,11 +11779,11 @@ var httpAdapter = isHttpAdapterSupported && function httpAdapter(config) { totalResponseBytes += chunk.length; // make sure the content length is not over the maxContentLength if specified - if (config.maxContentLength > -1 && totalResponseBytes > config.maxContentLength) { + if (maxContentLength > -1 && totalResponseBytes > maxContentLength) { // stream.destroy() emit aborted event before calling reject() on Node.js v16 rejected = true; responseStream.destroy(); - abort(new AxiosError('maxContentLength size of ' + config.maxContentLength + ' exceeded', AxiosError.ERR_BAD_RESPONSE, config, lastRequest)); + abort(new AxiosError('maxContentLength size of ' + maxContentLength + ' exceeded', AxiosError.ERR_BAD_RESPONSE, config, lastRequest)); } }); responseStream.on('aborted', function handlerStreamAborted() { @@ -9820,7 +11846,11 @@ var httpAdapter = isHttpAdapterSupported && function httpAdapter(config) { const boundSockets = new Set(); req.on('socket', function handleRequestSocket(socket) { // default interval of sending ack packet is 1 minute - socket.setKeepAlive(true, 1000 * 60); + // proxy agents (e.g. agent-base) may return a generic Duplex stream + // that doesn't have setKeepAlive, so guard before calling + if (typeof socket.setKeepAlive === 'function') { + socket.setKeepAlive(true, 1000 * 60); + } // Install a single 'error' listener per socket (not per request) to avoid // accumulating listeners on pooled keep-alive sockets that get reassigned @@ -9850,9 +11880,9 @@ var httpAdapter = isHttpAdapterSupported && function httpAdapter(config) { }); // Handle request timeout - if (config.timeout) { + if (own('timeout')) { // This is forcing a int timeout to avoid problems if the `req` interface doesn't handle other types. - const timeout = parseInt(config.timeout, 10); + const timeout = parseInt(own('timeout'), 10); if (Number.isNaN(timeout)) { abort(new AxiosError('error trying to parse `config.timeout` to int', AxiosError.ERR_BAD_OPTION_VALUE, config, req)); return; @@ -9896,12 +11926,13 @@ var httpAdapter = isHttpAdapterSupported && function httpAdapter(config) { } }); - // Enforce maxBodyLength for streamed uploads on the native http/https - // transport (maxRedirects === 0); follow-redirects enforces it on the - // other path. + // Enforce maxBodyLength for streamed uploads on every transport that + // does not apply options.maxBodyLength itself (native http/https, http2, + // and user-supplied custom transports). The follow-redirects transport + // enforces it on the redirected HTTP/1 path. let uploadStream = data; - if (config.maxBodyLength > -1 && config.maxRedirects === 0) { - const limit = config.maxBodyLength; + if (maxBodyLength > -1 && !transportEnforcesMaxBodyLength) { + const limit = maxBodyLength; let bytesSent = 0; uploadStream = stream.pipeline([data, new stream.Transform({ transform(chunk, _enc, cb) { @@ -9964,7 +11995,11 @@ var cookies = platform.hasStandardBrowserEnv ? const cookie = cookies[i].replace(/^\s+/, ''); const eq = cookie.indexOf('='); if (eq !== -1 && cookie.slice(0, eq) === name) { - return decodeURIComponent(cookie.slice(eq + 1)); + try { + return decodeURIComponent(cookie.slice(eq + 1)); + } catch (e) { + return cookie.slice(eq + 1); + } } } return null; @@ -9997,6 +12032,7 @@ const headersToObject = thing => thing instanceof AxiosHeaders ? { */ function mergeConfig(config1, config2) { // eslint-disable-next-line no-param-reassign + config1 = config1 || {}; config2 = config2 || {}; // Use a null-prototype object so that downstream reads such as `config.auth` @@ -10048,6 +12084,23 @@ function mergeConfig(config1, config2) { return getMergedValue(undefined, a); } } + function getMergedTransitionalOption(prop) { + const transitional2 = utils$1.hasOwnProp(config2, 'transitional') ? config2.transitional : undefined; + if (!utils$1.isUndefined(transitional2)) { + if (utils$1.isPlainObject(transitional2)) { + if (utils$1.hasOwnProp(transitional2, prop)) { + return transitional2[prop]; + } + } else { + return undefined; + } + } + const transitional1 = utils$1.hasOwnProp(config1, 'transitional') ? config1.transitional : undefined; + if (utils$1.isPlainObject(transitional1) && utils$1.hasOwnProp(transitional1, prop)) { + return transitional1[prop]; + } + return undefined; + } // eslint-disable-next-line consistent-return function mergeDirectKeys(a, b, prop) { @@ -10100,6 +12153,13 @@ function mergeConfig(config1, config2) { const configValue = merge(a, b, prop); utils$1.isUndefined(configValue) && merge !== mergeDirectKeys || (config[prop] = configValue); }); + if (utils$1.hasOwnProp(config2, 'validateStatus') && utils$1.isUndefined(config2.validateStatus) && getMergedTransitionalOption('validateStatusUndefinedResolves') === false) { + if (utils$1.hasOwnProp(config1, 'validateStatus')) { + config.validateStatus = getMergedValue(undefined, config1.validateStatus); + } else { + delete config.validateStatus; + } + } return config; } @@ -10109,7 +12169,7 @@ function setFormDataHeaders(headers, formHeaders, policy) { headers.set(formHeaders); return; } - Object.entries(formHeaders).forEach(([key, val]) => { + Object.entries(formHeaders || {}).forEach(([key, val]) => { if (FORM_DATA_CONTENT_HEADERS.includes(key.toLowerCase())) { headers.set(key, val); } @@ -10124,8 +12184,8 @@ function setFormDataHeaders(headers, formHeaders, policy) { * * @returns {string} UTF-8 bytes as a Latin-1 string */ -const encodeUTF8 = str => encodeURIComponent(str).replace(/%([0-9A-F]{2})/gi, (_, hex) => String.fromCharCode(parseInt(hex, 16))); -var resolveConfig = config => { +const encodeUTF8$1 = str => encodeURIComponent(str).replace(/%([0-9A-F]{2})/gi, (_, hex) => String.fromCharCode(parseInt(hex, 16))); +function resolveConfig(config) { const newConfig = mergeConfig({}, config); // Read only own properties to prevent prototype pollution gadgets @@ -10141,15 +12201,21 @@ var resolveConfig = config => { const allowAbsoluteUrls = own('allowAbsoluteUrls'); const url = own('url'); newConfig.headers = headers = AxiosHeaders.from(headers); - newConfig.url = buildURL(buildFullPath(baseURL, url, allowAbsoluteUrls), config.params, config.paramsSerializer); + newConfig.url = buildURL(buildFullPath(baseURL, url, allowAbsoluteUrls, newConfig), own('params'), own('paramsSerializer')); // HTTP basic authentication if (auth) { - headers.set('Authorization', 'Basic ' + btoa((auth.username || '') + ':' + (auth.password ? encodeUTF8(auth.password) : ''))); + const username = utils$1.getSafeProp(auth, 'username') || ''; + const password = utils$1.getSafeProp(auth, 'password') || ''; + try { + headers.set('Authorization', 'Basic ' + btoa(username + ':' + (password ? encodeUTF8$1(password) : ''))); + } catch (e) { + throw AxiosError.from(e, AxiosError.ERR_BAD_OPTION_VALUE, config); + } } if (utils$1.isFormData(data)) { - if (platform.hasStandardBrowserEnv || platform.hasStandardBrowserWebWorkerEnv) { - headers.setContentType(undefined); // browser handles it + if (platform.hasStandardBrowserEnv || platform.hasStandardBrowserWebWorkerEnv || utils$1.isReactNative(data)) { + headers.setContentType(undefined); // browser/web worker/RN handles it } else if (utils$1.isFunction(data.getHeaders)) { // Node.js FormData (like form-data package) setFormDataHeaders(headers, data.getHeaders(), own('formDataHeaderPolicy')); @@ -10177,7 +12243,7 @@ var resolveConfig = config => { } } return newConfig; -}; +} const isXHRAdapterSupported = typeof XMLHttpRequest !== 'undefined'; var xhrAdapter = isXHRAdapterSupported && function (config) { @@ -10299,7 +12365,7 @@ var xhrAdapter = isXHRAdapterSupported && function (config) { // Add headers to the request if ('setRequestHeader' in request) { - utils$1.forEach(requestHeaders.toJSON(), function setRequestHeader(val, key) { + utils$1.forEach(toByteStringHeaderObject(requestHeaders), function setRequestHeader(val, key) { request.setRequestHeader(key, val); }); } @@ -10346,6 +12412,7 @@ var xhrAdapter = isXHRAdapterSupported && function (config) { const protocol = parseProtocol(_config.url); if (protocol && !platform.protocols.includes(protocol)) { reject(new AxiosError('Unsupported protocol ' + protocol + ':', AxiosError.ERR_BAD_REQUEST, config)); + done(); return; } @@ -10355,41 +12422,43 @@ var xhrAdapter = isXHRAdapterSupported && function (config) { }; const composeSignals = (signals, timeout) => { - const { - length - } = signals = signals ? signals.filter(Boolean) : []; - if (timeout || length) { - let controller = new AbortController(); - let aborted; - const onabort = function (reason) { - if (!aborted) { - aborted = true; - unsubscribe(); - const err = reason instanceof Error ? reason : this.reason; - controller.abort(err instanceof AxiosError ? err : new CanceledError(err instanceof Error ? err.message : err)); - } - }; - let timer = timeout && setTimeout(() => { - timer = null; - onabort(new AxiosError(`timeout of ${timeout}ms exceeded`, AxiosError.ETIMEDOUT)); - }, timeout); - const unsubscribe = () => { - if (signals) { - timer && clearTimeout(timer); - timer = null; - signals.forEach(signal => { - signal.unsubscribe ? signal.unsubscribe(onabort) : signal.removeEventListener('abort', onabort); - }); - signals = null; - } - }; - signals.forEach(signal => signal.addEventListener('abort', onabort)); - const { - signal - } = controller; - signal.unsubscribe = () => utils$1.asap(unsubscribe); - return signal; + signals = signals ? signals.filter(Boolean) : []; + if (!timeout && !signals.length) { + return; } + const controller = new AbortController(); + let aborted = false; + const onabort = function (reason) { + if (!aborted) { + aborted = true; + unsubscribe(); + const err = reason instanceof Error ? reason : this.reason; + controller.abort(err instanceof AxiosError ? err : new CanceledError(err instanceof Error ? err.message : err)); + } + }; + let timer = timeout && setTimeout(() => { + timer = null; + onabort(new AxiosError(`timeout of ${timeout}ms exceeded`, AxiosError.ETIMEDOUT)); + }, timeout); + const unsubscribe = () => { + if (!signals) { + return; + } + timer && clearTimeout(timer); + timer = null; + signals.forEach(signal => { + signal.unsubscribe ? signal.unsubscribe(onabort) : signal.removeEventListener('abort', onabort); + }); + signals = null; + }; + signals.forEach(signal => signal.addEventListener('abort', onabort, { + once: true + })); + const { + signal + } = controller; + signal.unsubscribe = () => utils$1.asap(unsubscribe); + return signal; }; const streamChunk = function* (chunk, chunkSize) { @@ -10478,6 +12547,31 @@ const DEFAULT_CHUNK_SIZE = 64 * 1024; const { isFunction } = utils$1; + +/** + * Encode a UTF-8 string to a Latin-1 byte string for use with btoa(). + * This is a modern replacement for the deprecated unescape(encodeURIComponent(str)) pattern. + * + * @param {string} str The string to encode + * + * @returns {string} UTF-8 bytes as a Latin-1 string + */ +const encodeUTF8 = str => encodeURIComponent(str).replace(/%([0-9A-F]{2})/gi, (_, hex) => String.fromCharCode(parseInt(hex, 16))); + +// Node's WHATWG URL parser returns `username` and `password` percent-encoded. +// Decode before composing the `auth` option so credentials such as +// `my%40email.com:pass` are sent as `my@email.com:pass`. Falls back to the +// original value for malformed input so a bad encoding never throws. +const decodeURIComponentSafe = value => { + if (!utils$1.isString(value)) { + return value; + } + try { + return decodeURIComponent(value); + } catch (error) { + return value; + } +}; const test = (fn, ...args) => { try { return !!fn(...args); @@ -10485,9 +12579,16 @@ const test = (fn, ...args) => { return false; } }; +const maybeWithAuthCredentials = url => { + const protocolIndex = url.indexOf('://'); + let urlToCheck = url; + if (protocolIndex !== -1) { + urlToCheck = urlToCheck.slice(protocolIndex + 3); + } + return urlToCheck.includes('@') || urlToCheck.includes(':'); +}; const factory = env => { - var _utils$global; - const globalObject = (_utils$global = utils$1.global) !== null && _utils$global !== void 0 ? _utils$global : globalThis; + const globalObject = utils$1.global !== undefined && utils$1.global !== null ? utils$1.global : globalThis; const { ReadableStream, TextEncoder @@ -10589,6 +12690,7 @@ const factory = env => { } = resolveConfig(config); const hasMaxContentLength = utils$1.isNumber(maxContentLength) && maxContentLength > -1; const hasMaxBodyLength = utils$1.isNumber(maxBodyLength) && maxBodyLength > -1; + const own = key => utils$1.hasOwnProp(config, key) ? config[key] : undefined; let _fetch = envFetch || fetch; responseType = responseType ? (responseType + '').toLowerCase() : 'text'; let composedSignal = composeSignals([signal, cancelToken && cancelToken.toAbortSignal()], timeout); @@ -10597,7 +12699,46 @@ const factory = env => { composedSignal.unsubscribe(); }); let requestContentLength; + + // AxiosError we raise while the request body is being streamed. Captured + // by identity so the catch block can surface it directly, regardless of + // how the runtime wraps the resulting fetch rejection (undici exposes it + // as `err.cause`; some browsers drop the original error entirely). + let pendingBodyError = null; + const maxBodyLengthError = () => new AxiosError('Request body larger than maxBodyLength limit', AxiosError.ERR_BAD_REQUEST, config, request); try { + // HTTP basic authentication + let auth = undefined; + const configAuth = own('auth'); + if (configAuth) { + const username = utils$1.getSafeProp(configAuth, 'username') || ''; + const password = utils$1.getSafeProp(configAuth, 'password') || ''; + auth = { + username, + password + }; + } + if (maybeWithAuthCredentials(url)) { + const parsedURL = new URL(url, platform.origin); + if (!auth && (parsedURL.username || parsedURL.password)) { + const urlUsername = decodeURIComponentSafe(parsedURL.username); + const urlPassword = decodeURIComponentSafe(parsedURL.password); + auth = { + username: urlUsername, + password: urlPassword + }; + } + if (parsedURL.username || parsedURL.password) { + parsedURL.username = ''; + parsedURL.password = ''; + url = parsedURL.href; + } + } + if (auth) { + headers.delete('authorization'); + headers.set('Authorization', 'Basic ' + btoa(encodeUTF8((auth.username || '') + ':' + (auth.password || '')))); + } + // Enforce maxContentLength for data: URLs up-front so we never materialize // an oversized payload. The HTTP adapter applies the same check (see http.js // "if (protocol === 'data:')" branch). @@ -10608,30 +12749,54 @@ const factory = env => { } } - // Enforce maxBodyLength against the outbound request body before dispatch. - // Mirrors http.js behavior (ERR_BAD_REQUEST / 'Request body larger than - // maxBodyLength limit'). Skip when the body length cannot be determined - // (e.g. a live ReadableStream supplied by the caller). + // Enforce maxBodyLength against known-size bodies before dispatch using + // the body's *actual* size — never a caller-declared Content-Length, + // which could under-report to slip an oversized body past the check. + // Unknown-size streams return undefined here and are counted per-chunk + // below as fetch consumes them. if (hasMaxBodyLength && method !== 'get' && method !== 'head') { - const outboundLength = await resolveBodyLength(headers, data); - if (typeof outboundLength === 'number' && isFinite(outboundLength) && outboundLength > maxBodyLength) { - throw new AxiosError('Request body larger than maxBodyLength limit', AxiosError.ERR_BAD_REQUEST, config, request); + const outboundLength = await getBodyLength(data); + if (typeof outboundLength === 'number' && isFinite(outboundLength)) { + requestContentLength = outboundLength; + if (outboundLength > maxBodyLength) { + throw maxBodyLengthError(); + } } } - 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); + + // A streamed body under maxBodyLength must be counted as fetch consumes + // it; its size is never trusted from a caller-declared Content-Length. + const mustEnforceStreamBody = hasMaxBodyLength && (utils$1.isReadableStream(data) || utils$1.isStream(data)); + const trackRequestStream = (stream, onProgress, flush) => trackStream(stream, DEFAULT_CHUNK_SIZE, loadedBytes => { + if (hasMaxBodyLength && loadedBytes > maxBodyLength) { + throw pendingBodyError = maxBodyLengthError(); } - if (_request.body) { - const [onProgress, flush] = progressEventDecorator(requestContentLength, progressEventReducer(asyncDecorator(onUploadProgress))); - data = trackStream(_request.body, DEFAULT_CHUNK_SIZE, onProgress, flush); + onProgress && onProgress(loadedBytes); + }, flush); + if (supportsRequestStream && method !== 'get' && method !== 'head' && (onUploadProgress || mustEnforceStreamBody)) { + requestContentLength = requestContentLength == null ? await resolveBodyLength(headers, data) : requestContentLength; + + // A declared length of 0 is only trusted to skip the wrap when we are + // not enforcing a stream limit (which must not rely on that header). + if (requestContentLength !== 0 || mustEnforceStreamBody) { + 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] = onUploadProgress && progressEventDecorator(requestContentLength, progressEventReducer(asyncDecorator(onUploadProgress))) || []; + data = trackRequestStream(_request.body, onProgress, flush); + } } + } else if (mustEnforceStreamBody && !isRequestSupported && isReadableStreamSupported && method !== 'get' && method !== 'head') { + data = trackRequestStream(data); + } else if (mustEnforceStreamBody && isRequestSupported && !supportsRequestStream && method !== 'get' && method !== 'head') { + throw new AxiosError('Stream request bodies are not supported by the current fetch implementation', AxiosError.ERR_NOT_SUPPORT, config, request); } if (!utils$1.isString(withCredentials)) { withCredentials = withCredentials ? 'include' : 'omit'; @@ -10656,18 +12821,19 @@ const factory = env => { ...fetchOptions, signal: composedSignal, method: method.toUpperCase(), - headers: headers.normalize().toJSON(), + headers: toByteStringHeaderObject(headers.normalize()), body: data, duplex: 'half', credentials: isCredentialsSupported ? withCredentials : undefined }; request = isRequestSupported && new Request(url, resolvedOptions); let response = await (isRequestSupported ? _fetch(request, fetchOptions) : _fetch(url, resolvedOptions)); + const responseHeaders = AxiosHeaders.from(response.headers); // Cheap pre-check: if the server honestly declares a content-length that // already exceeds the cap, reject before we start streaming. if (hasMaxContentLength) { - const declaredLength = utils$1.toFiniteNumber(response.headers.get('content-length')); + const declaredLength = utils$1.toFiniteNumber(responseHeaders.getContentLength()); if (declaredLength != null && declaredLength > maxContentLength) { throw new AxiosError('maxContentLength size of ' + maxContentLength + ' exceeded', AxiosError.ERR_BAD_RESPONSE, config, request); } @@ -10678,7 +12844,7 @@ const factory = env => { ['status', 'statusText', 'headers'].forEach(prop => { options[prop] = response[prop]; }); - const responseContentLength = utils$1.toFiniteNumber(response.headers.get('content-length')); + const responseContentLength = utils$1.toFiniteNumber(responseHeaders.getContentLength()); const [onProgress, flush] = onDownloadProgress && progressEventDecorator(responseContentLength, progressEventReducer(asyncDecorator(onDownloadProgress), true)) || []; let bytesRead = 0; const onChunkProgress = loadedBytes => { @@ -10737,13 +12903,48 @@ const factory = env => { const canceledError = composedSignal.reason; canceledError.config = config; request && (canceledError.request = request); - err !== canceledError && (canceledError.cause = err); + if (err !== canceledError) { + // Non-enumerable to match native Error `cause` semantics so loggers + // don't recurse into circular fetch internals (see #7205). + Object.defineProperty(canceledError, 'cause', { + __proto__: null, + value: err, + writable: true, + enumerable: false, + configurable: true + }); + } throw canceledError; } + + // Surface a maxBodyLength violation we raised while the request body was + // being streamed. Matching by identity (rather than reading + // `err.cause.isAxiosError`) keeps the error deterministic across runtimes + // and avoids both prototype-pollution reads and mis-attributing a foreign + // AxiosError that merely happened to land in `err.cause`. + if (pendingBodyError) { + request && !pendingBodyError.request && (pendingBodyError.request = request); + throw pendingBodyError; + } + + // Re-throw AxiosErrors we raised synchronously (data: URL / content-length + // pre-checks, response size enforcement) without re-wrapping them. + if (err instanceof AxiosError) { + request && !err.request && (err.request = request); + throw err; + } if (err && err.name === 'TypeError' && /Load failed|fetch/i.test(err.message)) { - throw Object.assign(new AxiosError('Network Error', AxiosError.ERR_NETWORK, config, request, err && err.response), { - cause: err.cause || err + const networkError = new AxiosError('Network Error', AxiosError.ERR_NETWORK, config, request, err && err.response); + // Non-enumerable to match native Error `cause` semantics so loggers + // don't recurse into circular fetch internals (see #7205). + Object.defineProperty(networkError, 'cause', { + __proto__: null, + value: err.cause || err, + writable: true, + enumerable: false, + configurable: true }); + throw networkError; } throw AxiosError.from(err, err && err.code, config, request, err && err.response); } @@ -10862,7 +13063,7 @@ function getAdapter(adapters, config) { if (!adapter) { const reasons = Object.entries(rejectedReasons).map(([id, state]) => `adapter ${id} ` + (state === false ? 'is not supported by the environment' : 'is not available in the build')); let s = length ? reasons.length > 1 ? 'since :\n' + reasons.map(renderReason).join('\n') : ' ' + renderReason(reasons[0]) : 'as no adapter specified'; - throw new AxiosError(`There is no suitable adapter to dispatch the request ` + s, 'ERR_NOT_SUPPORT'); + throw new AxiosError(`There is no suitable adapter to dispatch the request ` + s, AxiosError.ERR_NOT_SUPPORT); } return adapter; } @@ -11005,7 +13206,7 @@ validators$1.spelling = function spelling(correctSpelling) { */ function assertOptions(options, schema, allowUnknown) { - if (typeof options !== 'object') { + if (typeof options !== 'object' || options === null) { throw new AxiosError('options must be an object', AxiosError.ERR_BAD_OPTION_VALUE); } const keys = Object.keys(options); @@ -11114,7 +13315,9 @@ class Axios { silentJSONParsing: validators.transitional(validators.boolean), forcedJSONParsing: validators.transitional(validators.boolean), clarifyTimeoutError: validators.transitional(validators.boolean), - legacyInterceptorReqResOrdering: validators.transitional(validators.boolean) + legacyInterceptorReqResOrdering: validators.transitional(validators.boolean), + advertiseZstdAcceptEncoding: validators.transitional(validators.boolean), + validateStatusUndefinedResolves: validators.transitional(validators.boolean) }, false); } if (paramsSerializer != null) { @@ -11211,7 +13414,7 @@ class Axios { } getUri(config) { config = mergeConfig(this.defaults, config); - const fullPath = buildFullPath(config.baseURL, config.url, config.allowAbsoluteUrls); + const fullPath = buildFullPath(config.baseURL, config.url, config.allowAbsoluteUrls, config); return buildURL(fullPath, config.params, config.paramsSerializer); } } @@ -11223,7 +13426,7 @@ utils$1.forEach(['delete', 'get', 'head', 'options'], function forEachMethodNoDa return this.request(mergeConfig(config || {}, { method, url, - data: (config || {}).data + data: config && utils$1.hasOwnProp(config, 'data') ? config.data : undefined })); }; }); diff --git a/yarn.lock b/yarn.lock index 3422c70..5a59084 100644 --- a/yarn.lock +++ b/yarn.lock @@ -22,18 +22,26 @@ resolved "https://registry.yarnpkg.com/@vercel/ncc/-/ncc-0.38.3.tgz#5475eeee3ac0f1a439f237596911525a490a88b5" integrity sha512-rnK6hJBS6mwc+Bkab+PGPs9OiS0i/3kdTO+CkI8V0/VrW3vmz7O2Pxjw/owOlmo6PKEIxRSeZKv/kuL9itnpYA== +agent-base@6: + version "6.0.2" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" + integrity "sha1-Sf/1hXfP7j83F2/qtMIuAPhtf3c= sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==" + dependencies: + debug "4" + asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== axios@^1.9.0: - version "1.16.0" - resolved "https://registry.yarnpkg.com/axios/-/axios-1.16.0.tgz#f8e5dd931cef2a5f8c32216d5784eda2f8750eb7" - integrity "sha1-+OXdkxzvKl+MMiFtV4Ttovh1Drc= sha512-6hp5CwvTPlN2A31g5dxnwAX0orzM7pmCRDLnZSX772mv8WDqICwFjowHuPs04Mc8deIld1+ejhtaMn5vp6b+1w==" + version "1.18.1" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.18.1.tgz#d63f9863bcd8938815c86f9e2abd380189d96dfe" + integrity "sha1-1j+YY7zYk4gVyG+eKr04AYnZbf4= sha512-3nTvFlvpn9Zu/RkHUqtc7/+al4UpRW5az71ap5zccp6e8RAYEzhMTecX8Dz1wWDYrPpUoB1HAQEGEAEvUr7S9g==" dependencies: follow-redirects "^1.16.0" form-data "^4.0.5" + https-proxy-agent "^5.0.1" proxy-from-env "^2.1.0" call-bind-apply-helpers@^1.0.1, call-bind-apply-helpers@^1.0.2: @@ -51,6 +59,13 @@ combined-stream@^1.0.8: dependencies: delayed-stream "~1.0.0" +debug@4: + version "4.4.3" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.3.tgz#c6ae432d9bd9662582fce08709b038c58e9e3d6a" + integrity "sha1-xq5DLZvZZiWC/OCHCbA4xY6ePWo= sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==" + dependencies: + ms "^2.1.3" + delayed-stream@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" @@ -168,6 +183,14 @@ hasown@^2.0.4: dependencies: function-bind "^1.1.2" +https-proxy-agent@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" + integrity "sha1-xZ7yJKBP6LdU89sAY6Jeow0ABdY= sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==" + dependencies: + agent-base "6" + debug "4" + math-intrinsics@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz#a0dd74be81e2aa5c2f27e65ce283605ee4e2b7f9" @@ -185,6 +208,11 @@ mime-types@^2.1.35: dependencies: mime-db "1.52.0" +ms@^2.1.3: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity "sha1-V0yBOM4dK1hh8LRFedut1gxmFbI= sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + proxy-from-env@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-2.1.0.tgz#a7487568adad577cfaaa7e88c49cab3ab3081aba"