UNPKG

axios

Version:

Promise based HTTP client for the browser and node.js

177 lines (151 loc) 5.56 kB
'use strict'; import utils from '../utils.js'; import AxiosHeaders from './AxiosHeaders.js'; const REDACTED = '[REDACTED ****]'; function hasOwnOrPrototypeToJSON(source) { if (utils.hasOwnProp(source, 'toJSON')) { return true; } let prototype = Object.getPrototypeOf(source); while (prototype && prototype !== Object.prototype) { if (utils.hasOwnProp(prototype, 'toJSON')) { return true; } prototype = Object.getPrototypeOf(prototype); } return false; } // Build a plain-object snapshot of `config` and replace the value of any key // (case-insensitive) listed in `redactKeys` with REDACTED. Walks through arrays // and AxiosHeaders, and short-circuits on circular references. function redactConfig(config, redactKeys) { const lowerKeys = new Set(redactKeys.map((k) => String(k).toLowerCase())); const seen = []; const visit = (source) => { if (source === null || typeof source !== 'object') return source; if (utils.isBuffer(source)) return source; if (seen.indexOf(source) !== -1) return undefined; if (source instanceof AxiosHeaders) { source = source.toJSON(); } seen.push(source); let result; if (utils.isArray(source)) { result = []; source.forEach((v, i) => { const reducedValue = visit(v); if (!utils.isUndefined(reducedValue)) { result[i] = reducedValue; } }); } else { if (!utils.isPlainObject(source) && hasOwnOrPrototypeToJSON(source)) { seen.pop(); return source; } result = Object.create(null); for (const [key, value] of Object.entries(source)) { const reducedValue = lowerKeys.has(key.toLowerCase()) ? REDACTED : visit(value); if (!utils.isUndefined(reducedValue)) { result[key] = reducedValue; } } } seen.pop(); return result; }; return visit(config); } 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; axiosError.name = error.name; // Preserve status from the original error if not already set from response if (error.status != null && axiosError.status == null) { axiosError.status = error.status; } customProps && Object.assign(axiosError, customProps); return axiosError; } /** * Create an Error with the specified message, config, error code, request and response. * * @param {string} message The error message. * @param {string} [code] The error code (for example, 'ECONNABORTED'). * @param {Object} [config] The config. * @param {Object} [request] The request. * @param {Object} [response] The response. * * @returns {Error} The created error. */ constructor(message, code, config, request, response) { super(message); // Make message enumerable to maintain backward compatibility // The native Error constructor sets message as non-enumerable, // but axios < v1.13.3 had it as enumerable Object.defineProperty(this, 'message', { // Null-proto descriptor so a polluted Object.prototype.get cannot turn // this data descriptor into an accessor descriptor on the way in. __proto__: null, value: message, enumerable: true, writable: true, configurable: true, }); this.name = 'AxiosError'; this.isAxiosError = true; code && (this.code = code); config && (this.config = config); request && (this.request = request); if (response) { this.response = response; this.status = response.status; } } toJSON() { // Opt-in redaction: when the request config carries a `redact` array, the // value of any matching key (case-insensitive, at any depth) is replaced // with REDACTED in the serialized snapshot. Undefined or empty leaves the // existing serialization behavior unchanged. const config = this.config; const redactKeys = config && utils.hasOwnProp(config, 'redact') ? config.redact : undefined; const serializedConfig = utils.isArray(redactKeys) && redactKeys.length > 0 ? redactConfig(config, redactKeys) : utils.toJSONObject(config); return { // Standard message: this.message, name: this.name, // Microsoft description: this.description, number: this.number, // Mozilla fileName: this.fileName, lineNumber: this.lineNumber, columnNumber: this.columnNumber, stack: this.stack, // Axios config: serializedConfig, code: this.code, status: this.status, }; } } // This can be changed to static properties as soon as the parser options in .eslint.cjs are updated. AxiosError.ERR_BAD_OPTION_VALUE = 'ERR_BAD_OPTION_VALUE'; AxiosError.ERR_BAD_OPTION = 'ERR_BAD_OPTION'; AxiosError.ECONNABORTED = 'ECONNABORTED'; AxiosError.ETIMEDOUT = 'ETIMEDOUT'; AxiosError.ECONNREFUSED = 'ECONNREFUSED'; AxiosError.ERR_NETWORK = 'ERR_NETWORK'; AxiosError.ERR_FR_TOO_MANY_REDIRECTS = 'ERR_FR_TOO_MANY_REDIRECTS'; AxiosError.ERR_DEPRECATED = 'ERR_DEPRECATED'; AxiosError.ERR_BAD_RESPONSE = 'ERR_BAD_RESPONSE'; AxiosError.ERR_BAD_REQUEST = 'ERR_BAD_REQUEST'; AxiosError.ERR_CANCELED = 'ERR_CANCELED'; 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'; export default AxiosError;