Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/axios/axios into feat/par…
Browse files Browse the repository at this point in the history
…amsSerializer
  • Loading branch information
DigitalBrainJS committed May 20, 2022
2 parents f6fb238 + 467025b commit a2188b3
Show file tree
Hide file tree
Showing 20 changed files with 358 additions and 68 deletions.
2 changes: 1 addition & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ module.exports = {
'no-new-wrappers': 2, // http://eslint.org/docs/rules/no-new-wrappers
'no-octal': 2, // http://eslint.org/docs/rules/no-octal
'no-octal-escape': 2, // http://eslint.org/docs/rules/no-octal-escape
'no-param-reassign': 2, // http://eslint.org/docs/rules/no-param-reassign
'no-param-reassign': 0, // http://eslint.org/docs/rules/no-param-reassign
'no-proto': 2, // http://eslint.org/docs/rules/no-proto
'no-redeclare': 2, // http://eslint.org/docs/rules/no-redeclare
'no-return-assign': 2, // http://eslint.org/docs/rules/no-return-assign
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:

strategy:
matrix:
node-version: [12.x, 14.x, 16.x]
node-version: [12.x, 14.x, 16.x, 18.x]

steps:
- uses: actions/checkout@v2
Expand Down
22 changes: 22 additions & 0 deletions bin/ssl_hotfix.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
const {spawn} = require('child_process');

const args = process.argv.slice(2);

console.log(`Running ${args.join(' ')} on ${process.version}\n`);

const match = /v(\d+)/.exec(process.version);

const isHotfixNeeded = match && match[1] > 16;

isHotfixNeeded && console.warn('Setting --openssl-legacy-provider as ssl hotfix');

const test = spawn('cross-env',
isHotfixNeeded ? ['NODE_OPTIONS=--openssl-legacy-provider', ...args] : args, {
shell: true,
stdio: 'inherit'
}
);

test.on('exit', function (code) {
process.exit(code)
})
9 changes: 6 additions & 3 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,8 +125,8 @@ export interface AxiosRequestConfig<D = any> {
responseEncoding?: responseEncoding | string;
xsrfCookieName?: string;
xsrfHeaderName?: string;
onUploadProgress?: (progressEvent: any) => void;
onDownloadProgress?: (progressEvent: any) => void;
onUploadProgress?: (progressEvent: ProgressEvent) => void;
onDownloadProgress?: (progressEvent: ProgressEvent) => void;
maxContentLength?: number;
validateStatus?: ((status: number) => boolean) | null;
maxBodyLength?: number;
Expand Down Expand Up @@ -194,13 +194,16 @@ export class AxiosError<T = unknown, D = any> extends Error {
isAxiosError: boolean;
status?: number;
toJSON: () => object;
cause?: Error;
static readonly ERR_FR_TOO_MANY_REDIRECTS = "ERR_FR_TOO_MANY_REDIRECTS";
static readonly ERR_BAD_OPTION_VALUE = "ERR_BAD_OPTION_VALUE";
static readonly ERR_BAD_OPTION = "ERR_BAD_OPTION";
static readonly ERR_NETWORK = "ERR_NETWORK";
static readonly ERR_DEPRECATED = "ERR_DEPRECATED";
static readonly ERR_BAD_RESPONSE = "ERR_BAD_RESPONSE";
static readonly ERR_BAD_REQUEST = "ERR_BAD_REQUEST";
static readonly ERR_NOT_SUPPORT = "ERR_NOT_SUPPORT";
static readonly ERR_INVALID_URL = "ERR_INVALID_URL";
static readonly ERR_CANCELED = "ERR_CANCELED";
static readonly ECONNABORTED = "ECONNABORTED";
static readonly ETIMEDOUT = "ETIMEDOUT";
Expand Down Expand Up @@ -292,7 +295,7 @@ export interface AxiosStatic extends AxiosInstance {
Axios: typeof Axios;
AxiosError: typeof AxiosError;
readonly VERSION: string;
isCancel(value: any): boolean;
isCancel(value: any): value is Cancel;
all<T>(values: Array<T | Promise<T>>): Promise<T[]>;
spread<T, R>(callback: (...args: T[]) => R): (array: T[]) => R;
isAxiosError<T = any, D = any>(payload: any): payload is AxiosError<T, D>;
Expand Down
107 changes: 79 additions & 28 deletions lib/adapters/http.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,15 @@ var VERSION = require('./../env/data').version;
var transitionalDefaults = require('../defaults/transitional');
var AxiosError = require('../core/AxiosError');
var CanceledError = require('../cancel/CanceledError');
var platform = require('../platform');
var fromDataURI = require('../helpers/fromDataURI');
var stream = require('stream');

var isHttps = /https:?/;

var supportedProtocols = [ 'http:', 'https:', 'file:' ];
var supportedProtocols = platform.protocols.map(function(protocol) {
return protocol + ':';
});

function dispatchBeforeRedirect(options) {
if (options.beforeRedirects.proxy) {
Expand Down Expand Up @@ -99,6 +104,62 @@ module.exports = function httpAdapter(config) {
rejectPromise(value);
};
var data = config.data;
var responseType = config.responseType;
var responseEncoding = config.responseEncoding;
var method = config.method.toUpperCase();

// Parse url
var fullPath = buildFullPath(config.baseURL, config.url);
var parsed = url.parse(fullPath);
var protocol = parsed.protocol || supportedProtocols[0];

if (protocol === 'data:') {
var convertedData;

if (method !== 'GET') {
return settle(resolve, reject, {
status: 405,
statusText: 'method not allowed',
headers: {},
config: config
});
}

try {
convertedData = fromDataURI(config.url, responseType === 'blob', {
Blob: config.env && config.env.Blob
});
} catch (err) {
throw AxiosError.from(err, AxiosError.ERR_BAD_REQUEST, config);
}

if (responseType === 'text') {
convertedData = convertedData.toString(responseEncoding);

if (!responseEncoding || responseEncoding === 'utf8') {
data = utils.stripBOM(convertedData);
}
} else if (responseType === 'stream') {
convertedData = stream.Readable.from(convertedData);
}

return settle(resolve, reject, {
data: convertedData,
status: 200,
statusText: 'OK',
headers: {},
config: config
});
}

if (supportedProtocols.indexOf(protocol) === -1) {
return reject(new AxiosError(
'Unsupported protocol ' + protocol,
AxiosError.ERR_BAD_REQUEST,
config
));
}

var headers = config.headers;
var headerNames = {};

Expand Down Expand Up @@ -159,19 +220,6 @@ module.exports = function httpAdapter(config) {
auth = username + ':' + password;
}

// Parse url
var fullPath = buildFullPath(config.baseURL, config.url);
var parsed = url.parse(fullPath);
var protocol = parsed.protocol || supportedProtocols[0];

if (supportedProtocols.indexOf(protocol) === -1) {
return reject(new AxiosError(
'Unsupported protocol ' + protocol,
AxiosError.ERR_BAD_REQUEST,
config
));
}

if (!auth && parsed.auth) {
var urlAuth = parsed.auth.split(':');
var urlUsername = urlAuth[0] || '';
Expand All @@ -195,7 +243,7 @@ module.exports = function httpAdapter(config) {

var options = {
path: buildURL(parsed.path, config.params, config.paramsSerializer).replace(/^\?/, ''),
method: config.method.toUpperCase(),
method: method,
headers: headers,
agents: { http: config.httpAgent, https: config.httpsAgent },
auth: auth,
Expand Down Expand Up @@ -231,6 +279,9 @@ module.exports = function httpAdapter(config) {

if (config.maxBodyLength > -1) {
options.maxBodyLength = config.maxBodyLength;
} else {
// follow-redirects does not skip comparison, so it should always succeed for axios -1 unlimited
options.maxBodyLength = Infinity;
}

if (config.insecureHTTPParser) {
Expand All @@ -242,7 +293,7 @@ module.exports = function httpAdapter(config) {
if (req.aborted) return;

// uncompress the response body transparently if required
var stream = res;
var responseStream = res;

// return the last request in case of redirects
var lastRequest = res.req || req;
Expand All @@ -261,7 +312,7 @@ module.exports = function httpAdapter(config) {
case 'compress':
case 'deflate':
// add the unzipper to the body stream processing pipeline
stream = stream.pipe(zlib.createUnzip());
responseStream = responseStream.pipe(zlib.createUnzip());

// remove the content-encoding in order to not confuse downstream operations
delete res.headers['content-encoding'];
Expand All @@ -277,31 +328,31 @@ module.exports = function httpAdapter(config) {
request: lastRequest
};

if (config.responseType === 'stream') {
response.data = stream;
if (responseType === 'stream') {
response.data = responseStream;
settle(resolve, reject, response);
} else {
var responseBuffer = [];
var totalResponseBytes = 0;
stream.on('data', function handleStreamData(chunk) {
responseStream.on('data', function handleStreamData(chunk) {
responseBuffer.push(chunk);
totalResponseBytes += chunk.length;

// make sure the content length is not over the maxContentLength if specified
if (config.maxContentLength > -1 && totalResponseBytes > config.maxContentLength) {
// stream.destroy() emit aborted event before calling reject() on Node.js v16
rejected = true;
stream.destroy();
responseStream.destroy();
reject(new AxiosError('maxContentLength size of ' + config.maxContentLength + ' exceeded',
AxiosError.ERR_BAD_RESPONSE, config, lastRequest));
}
});

stream.on('aborted', function handlerStreamAborted() {
responseStream.on('aborted', function handlerStreamAborted() {
if (rejected) {
return;
}
stream.destroy();
responseStream.destroy();
reject(new AxiosError(
'maxContentLength size of ' + config.maxContentLength + ' exceeded',
AxiosError.ERR_BAD_RESPONSE,
Expand All @@ -310,17 +361,17 @@ module.exports = function httpAdapter(config) {
));
});

stream.on('error', function handleStreamError(err) {
responseStream.on('error', function handleStreamError(err) {
if (req.aborted) return;
reject(AxiosError.from(err, null, config, lastRequest));
});

stream.on('end', function handleStreamEnd() {
responseStream.on('end', function handleStreamEnd() {
try {
var responseData = responseBuffer.length === 1 ? responseBuffer[0] : Buffer.concat(responseBuffer);
if (config.responseType !== 'arraybuffer') {
responseData = responseData.toString(config.responseEncoding);
if (!config.responseEncoding || config.responseEncoding === 'utf8') {
if (responseType !== 'arraybuffer') {
responseData = responseData.toString(responseEncoding);
if (!responseEncoding || responseEncoding === 'utf8') {
responseData = utils.stripBOM(responseData);
}
}
Expand Down
3 changes: 2 additions & 1 deletion lib/adapters/xhr.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ var transitionalDefaults = require('../defaults/transitional');
var AxiosError = require('../core/AxiosError');
var CanceledError = require('../cancel/CanceledError');
var parseProtocol = require('../helpers/parseProtocol');
var platform = require('../platform');

module.exports = function xhrAdapter(config) {
return new Promise(function dispatchXhrRequest(resolve, reject) {
Expand Down Expand Up @@ -210,7 +211,7 @@ module.exports = function xhrAdapter(config) {

var protocol = parseProtocol(fullPath);

if (protocol && [ 'http', 'https', 'file', 'blob' ].indexOf(protocol) === -1) {
if (protocol && platform.protocols.indexOf(protocol) === -1) {
reject(new AxiosError('Unsupported protocol ' + protocol + ':', AxiosError.ERR_BAD_REQUEST, config));
return;
}
Expand Down
6 changes: 5 additions & 1 deletion lib/core/AxiosError.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,9 @@ var descriptors = {};
'ERR_DEPRECATED',
'ERR_BAD_RESPONSE',
'ERR_BAD_REQUEST',
'ERR_CANCELED'
'ERR_CANCELED',
'ERR_NOT_SUPPORT',
'ERR_INVALID_URL'
// eslint-disable-next-line func-names
].forEach(function(code) {
descriptors[code] = {value: code};
Expand All @@ -83,6 +85,8 @@ AxiosError.from = function(error, code, config, request, response, customProps)

AxiosError.call(axiosError, error.message, code, config, request, response);

axiosError.cause = error;

axiosError.name = error.name;

customProps && Object.assign(axiosError, customProps);
Expand Down
12 changes: 8 additions & 4 deletions lib/defaults/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ var AxiosError = require('../core/AxiosError');
var transitionalDefaults = require('./transitional');
var toFormData = require('../helpers/toFormData');
var toURLEncodedForm = require('../helpers/toURLEncodedForm');
var platform = require('../platform');

var DEFAULT_CONTENT_TYPE = {
'Content-Type': 'application/x-www-form-urlencoded'
Expand Down Expand Up @@ -101,11 +102,13 @@ var defaults = {

transformResponse: [function transformResponse(data) {
var transitional = this.transitional || defaults.transitional;
var silentJSONParsing = transitional && transitional.silentJSONParsing;
var forcedJSONParsing = transitional && transitional.forcedJSONParsing;
var strictJSONParsing = !silentJSONParsing && this.responseType === 'json';
var JSONRequested = this.responseType === 'json';

if (data && utils.isString(data) && ((forcedJSONParsing && !this.responseType) || JSONRequested)) {
var silentJSONParsing = transitional && transitional.silentJSONParsing;
var strictJSONParsing = !silentJSONParsing && JSONRequested;

if (strictJSONParsing || (forcedJSONParsing && utils.isString(data) && data.length)) {
try {
return JSON.parse(data);
} catch (e) {
Expand Down Expand Up @@ -134,7 +137,8 @@ var defaults = {
maxBodyLength: -1,

env: {
FormData: require('./env/FormData')
FormData: platform.classes.FormData,
Blob: platform.classes.Blob
},

validateStatus: function validateStatus(status) {
Expand Down
File renamed without changes.
51 changes: 51 additions & 0 deletions lib/helpers/fromDataURI.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
'use strict';

var AxiosError = require('../core/AxiosError');
var parseProtocol = require('./parseProtocol');
var platform = require('../platform');

var DATA_URL_PATTERN = /^(?:([^;]+);)?(?:[^;]+;)?(base64|),([\s\S]*)$/;

/**
* Parse data uri to a Buffer or Blob
* @param {String} uri
* @param {?Boolean} asBlob
* @param {?Object} options
* @param {?Function} options.Blob
* @returns {Buffer|Blob}
*/
module.exports = function fromDataURI(uri, asBlob, options) {
var _Blob = options && options.Blob || platform.classes.Blob;
var protocol = parseProtocol(uri);

if (asBlob === undefined && _Blob) {
asBlob = true;
}

if (protocol === 'data') {
uri = protocol.length ? uri.slice(protocol.length + 1) : uri;

var match = DATA_URL_PATTERN.exec(uri);

if (!match) {
throw new AxiosError('Invalid URL', AxiosError.ERR_INVALID_URL);
}

var mime = match[1];
var isBase64 = match[2];
var body = match[3];
var buffer = Buffer.from(decodeURIComponent(body), isBase64 ? 'base64' : 'utf8');

if (asBlob) {
if (!_Blob) {
throw new AxiosError('Blob is not supported', AxiosError.ERR_NOT_SUPPORT);
}

return new _Blob([buffer], {type: mime});
}

return buffer;
}

throw new AxiosError('Unsupported protocol ' + protocol, AxiosError.ERR_NOT_SUPPORT);
};

0 comments on commit a2188b3

Please sign in to comment.