mirror of
https://github.com/tenrok/axios.git
synced 2026-06-17 19:21:29 +03:00
9d92bcd326
* chore: remove un-needed ghsa in the comments of files * fix: auth header * fix: escape regex chars in cookies.read * fix: read-side merge and descriptors * fix: enable redaction in the .toJson for errors * fix: general IPv4-mapped IPv6 normalization in NO_PROXY * fix: added regression tests for scenarios already covered * chore: remove un-needed comments * fix: harden proxy host detection and error redaction * fix: make form-data header change opt-in * fix: apply suggestions form github review * fix: cubic review * fix: widen the regexs for matches Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com> * fix: smaller issue found by cubic * fix: address prototype chain * fix: update as per cubic --------- Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
177 lines
5.4 KiB
JavaScript
177 lines
5.4 KiB
JavaScript
'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;
|