2
0
mirror of https://github.com/tenrok/axios.git synced 2026-06-17 19:21:29 +03:00

Release/v0.22.0 (#4107)

* fix/Avoid package.json import; (#4041)

* Added auto-generated config module `env/data.js` for importing package environment vars without importing the whole `package.json`;
Refactored `http.js` to use `env/data.js` instead of package.json;

* Added `env/data.js`;
Added `env/README.md`;

* Feat/export package version constant (#4065)

* Added auto-generated config module `env/data.js` for importing package environment vars without importing the whole `package.json`;
Refactored `http.js` to use `env/data.js` instead of package.json;

* Added `env/data.js`;
Added `env/README.md`;

* Export package version constant;

* Fixed cancelToken leakage; Added AbortController support; (#3305)

* Fixed cancelToken leakage;
Added AbortController support;

* Fixed typings;

* Documented `signal` option;

* Added processing of early cancellation using AbortController without sending a request;

Co-authored-by: Jay <jasonsaayman@gmail.com>

* Updating CI to run on release branches

* Fixed default transitional config for custom Axios instance; (#4052)

Refactored `/core/mergeConfig`;

Co-authored-by: Jay <jasonsaayman@gmail.com>

* Prepping v0.22.0 for release

* Updated date

Co-authored-by: Dmitriy Mozgovoy <robotshara@gmail.com>
This commit is contained in:
Jay
2021-10-01 08:02:13 +02:00
committed by GitHub
parent 7d6bddba2d
commit 76f09afc03
27 changed files with 623 additions and 365 deletions
+29 -7
View File
@@ -10,9 +10,11 @@ var httpFollow = require('follow-redirects').http;
var httpsFollow = require('follow-redirects').https;
var url = require('url');
var zlib = require('zlib');
var pkg = require('./../../package.json');
var VERSION = require('./../env/data').version;
var createError = require('../core/createError');
var enhanceError = require('../core/enhanceError');
var defaults = require('../defaults');
var Cancel = require('../cancel/Cancel');
var isHttps = /https:?/;
@@ -44,10 +46,22 @@ function setProxy(options, proxy, location) {
/*eslint consistent-return:0*/
module.exports = function httpAdapter(config) {
return new Promise(function dispatchHttpRequest(resolvePromise, rejectPromise) {
var onCanceled;
function done() {
if (config.cancelToken) {
config.cancelToken.unsubscribe(onCanceled);
}
if (config.signal) {
config.signal.removeEventListener('abort', onCanceled);
}
}
var resolve = function resolve(value) {
done();
resolvePromise(value);
};
var reject = function reject(value) {
done();
rejectPromise(value);
};
var data = config.data;
@@ -68,7 +82,7 @@ module.exports = function httpAdapter(config) {
// Otherwise, use specified value
} else {
// Only set header if it hasn't been set in config
headers['User-Agent'] = 'axios/' + pkg.version;
headers['User-Agent'] = 'axios/' + VERSION;
}
if (data && !utils.isStream(data)) {
@@ -310,25 +324,33 @@ module.exports = function httpAdapter(config) {
// ClientRequest.setTimeout will be fired on the specify milliseconds, and can make sure that abort() will be fired after connect.
req.setTimeout(timeout, function handleRequestTimeout() {
req.abort();
var transitional = config.transitional || defaults.transitional;
reject(createError(
'timeout of ' + timeout + 'ms exceeded',
config,
config.transitional && config.transitional.clarifyTimeoutError ? 'ETIMEDOUT' : 'ECONNABORTED',
transitional.clarifyTimeoutError ? 'ETIMEDOUT' : 'ECONNABORTED',
req
));
});
}
if (config.cancelToken) {
if (config.cancelToken || config.signal) {
// Handle cancellation
config.cancelToken.promise.then(function onCanceled(cancel) {
// eslint-disable-next-line func-names
onCanceled = function(cancel) {
if (req.aborted) return;
req.abort();
reject(cancel);
});
reject(!cancel || (cancel && cancel.type) ? new Cancel('canceled') : cancel);
};
config.cancelToken && config.cancelToken.subscribe(onCanceled);
if (config.signal) {
config.signal.aborted ? onCanceled() : config.signal.addEventListener('abort', onCanceled);
}
}
// Send the request
if (utils.isStream(data)) {
data.on('error', function handleStreamError(err) {
+31 -8
View File
@@ -8,12 +8,24 @@ var buildFullPath = require('../core/buildFullPath');
var parseHeaders = require('./../helpers/parseHeaders');
var isURLSameOrigin = require('./../helpers/isURLSameOrigin');
var createError = require('../core/createError');
var defaults = require('../defaults');
var Cancel = require('../cancel/Cancel');
module.exports = function xhrAdapter(config) {
return new Promise(function dispatchXhrRequest(resolve, reject) {
var requestData = config.data;
var requestHeaders = config.headers;
var responseType = config.responseType;
var onCanceled;
function done() {
if (config.cancelToken) {
config.cancelToken.unsubscribe(onCanceled);
}
if (config.signal) {
config.signal.removeEventListener('abort', onCanceled);
}
}
if (utils.isFormData(requestData)) {
delete requestHeaders['Content-Type']; // Let the browser set it
@@ -51,7 +63,13 @@ module.exports = function xhrAdapter(config) {
request: request
};
settle(resolve, reject, response);
settle(function _resolve(value) {
resolve(value);
done();
}, function _reject(err) {
reject(err);
done();
}, response);
// Clean up request
request = null;
@@ -105,13 +123,14 @@ module.exports = function xhrAdapter(config) {
// Handle timeout
request.ontimeout = function handleTimeout() {
var timeoutErrorMessage = config.timeout ? 'timeout of ' + config.timeout + 'ms exceeded' : 'timeout exceeded';
var transitional = config.transitional || defaults.transitional;
if (config.timeoutErrorMessage) {
timeoutErrorMessage = config.timeoutErrorMessage;
}
reject(createError(
timeoutErrorMessage,
config,
config.transitional && config.transitional.clarifyTimeoutError ? 'ETIMEDOUT' : 'ECONNABORTED',
transitional.clarifyTimeoutError ? 'ETIMEDOUT' : 'ECONNABORTED',
request));
// Clean up request
@@ -165,18 +184,22 @@ module.exports = function xhrAdapter(config) {
request.upload.addEventListener('progress', config.onUploadProgress);
}
if (config.cancelToken) {
if (config.cancelToken || config.signal) {
// Handle cancellation
config.cancelToken.promise.then(function onCanceled(cancel) {
// eslint-disable-next-line func-names
onCanceled = function(cancel) {
if (!request) {
return;
}
reject(!cancel || (cancel && cancel.type) ? new Cancel('canceled') : cancel);
request.abort();
reject(cancel);
// Clean up request
request = null;
});
};
config.cancelToken && config.cancelToken.subscribe(onCanceled);
if (config.signal) {
config.signal.aborted ? onCanceled() : config.signal.addEventListener('abort', onCanceled);
}
}
if (!requestData) {
+1
View File
@@ -40,6 +40,7 @@ axios.Axios = Axios;
axios.Cancel = require('./cancel/Cancel');
axios.CancelToken = require('./cancel/CancelToken');
axios.isCancel = require('./cancel/isCancel');
axios.VERSION = require('./env/data').version;
// Expose all/spread
axios.all = function all(promises) {
+62
View File
@@ -14,11 +14,42 @@ function CancelToken(executor) {
}
var resolvePromise;
this.promise = new Promise(function promiseExecutor(resolve) {
resolvePromise = resolve;
});
var token = this;
// eslint-disable-next-line func-names
this.promise.then(function(cancel) {
if (!token._listeners) return;
var i;
var l = token._listeners.length;
for (i = 0; i < l; i++) {
token._listeners[i](cancel);
}
token._listeners = null;
});
// eslint-disable-next-line func-names
this.promise.then = function(onfulfilled) {
var _resolve;
// eslint-disable-next-line func-names
var promise = new Promise(function(resolve) {
token.subscribe(resolve);
_resolve = resolve;
}).then(onfulfilled);
promise.cancel = function reject() {
token.unsubscribe(_resolve);
};
return promise;
};
executor(function cancel(message) {
if (token.reason) {
// Cancellation has already been requested
@@ -39,6 +70,37 @@ CancelToken.prototype.throwIfRequested = function throwIfRequested() {
}
};
/**
* Subscribe to the cancel signal
*/
CancelToken.prototype.subscribe = function subscribe(listener) {
if (this.reason) {
listener(this.reason);
return;
}
if (this._listeners) {
this._listeners.push(listener);
} else {
this._listeners = [listener];
}
};
/**
* Unsubscribe from the cancel signal
*/
CancelToken.prototype.unsubscribe = function unsubscribe(listener) {
if (!this._listeners) {
return;
}
var index = this._listeners.indexOf(listener);
if (index !== -1) {
this._listeners.splice(index, 1);
}
};
/**
* Returns an object that contains a new `CancelToken` and a function that, when called,
* cancels the `CancelToken`.
+3 -3
View File
@@ -51,9 +51,9 @@ Axios.prototype.request = function request(config) {
if (transitional !== undefined) {
validator.assertOptions(transitional, {
silentJSONParsing: validators.transitional(validators.boolean, '1.0.0'),
forcedJSONParsing: validators.transitional(validators.boolean, '1.0.0'),
clarifyTimeoutError: validators.transitional(validators.boolean, '1.0.0')
silentJSONParsing: validators.transitional(validators.boolean),
forcedJSONParsing: validators.transitional(validators.boolean),
clarifyTimeoutError: validators.transitional(validators.boolean)
}, false);
}
+5
View File
@@ -4,6 +4,7 @@ var utils = require('./../utils');
var transformData = require('./transformData');
var isCancel = require('../cancel/isCancel');
var defaults = require('../defaults');
var Cancel = require('../cancel/Cancel');
/**
* Throws a `Cancel` if cancellation has been requested.
@@ -12,6 +13,10 @@ function throwIfCancellationRequested(config) {
if (config.cancelToken) {
config.cancelToken.throwIfRequested();
}
if (config.signal && config.signal.aborted) {
throw new Cancel('canceled');
}
}
/**
+51 -39
View File
@@ -15,17 +15,6 @@ module.exports = function mergeConfig(config1, config2) {
config2 = config2 || {};
var config = {};
var valueFromConfig2Keys = ['url', 'method', 'data'];
var mergeDeepPropertiesKeys = ['headers', 'auth', 'proxy', 'params'];
var defaultToConfig2Keys = [
'baseURL', 'transformRequest', 'transformResponse', 'paramsSerializer',
'timeout', 'timeoutMessage', 'withCredentials', 'adapter', 'responseType', 'xsrfCookieName',
'xsrfHeaderName', 'onUploadProgress', 'onDownloadProgress', 'decompress',
'maxContentLength', 'maxBodyLength', 'maxRedirects', 'transport', 'httpAgent',
'httpsAgent', 'cancelToken', 'socketPath', 'responseEncoding'
];
var directMergeKeys = ['validateStatus'];
function getMergedValue(target, source) {
if (utils.isPlainObject(target) && utils.isPlainObject(source)) {
return utils.merge(target, source);
@@ -37,51 +26,74 @@ module.exports = function mergeConfig(config1, config2) {
return source;
}
// eslint-disable-next-line consistent-return
function mergeDeepProperties(prop) {
if (!utils.isUndefined(config2[prop])) {
config[prop] = getMergedValue(config1[prop], config2[prop]);
return getMergedValue(config1[prop], config2[prop]);
} else if (!utils.isUndefined(config1[prop])) {
config[prop] = getMergedValue(undefined, config1[prop]);
return getMergedValue(undefined, config1[prop]);
}
}
utils.forEach(valueFromConfig2Keys, function valueFromConfig2(prop) {
// eslint-disable-next-line consistent-return
function valueFromConfig2(prop) {
if (!utils.isUndefined(config2[prop])) {
config[prop] = getMergedValue(undefined, config2[prop]);
return getMergedValue(undefined, config2[prop]);
}
});
}
utils.forEach(mergeDeepPropertiesKeys, mergeDeepProperties);
utils.forEach(defaultToConfig2Keys, function defaultToConfig2(prop) {
// eslint-disable-next-line consistent-return
function defaultToConfig2(prop) {
if (!utils.isUndefined(config2[prop])) {
config[prop] = getMergedValue(undefined, config2[prop]);
return getMergedValue(undefined, config2[prop]);
} else if (!utils.isUndefined(config1[prop])) {
config[prop] = getMergedValue(undefined, config1[prop]);
return getMergedValue(undefined, config1[prop]);
}
});
}
utils.forEach(directMergeKeys, function merge(prop) {
// eslint-disable-next-line consistent-return
function mergeDirectKeys(prop) {
if (prop in config2) {
config[prop] = getMergedValue(config1[prop], config2[prop]);
return getMergedValue(config1[prop], config2[prop]);
} else if (prop in config1) {
config[prop] = getMergedValue(undefined, config1[prop]);
return getMergedValue(undefined, config1[prop]);
}
}
var mergeMap = {
'url': valueFromConfig2,
'method': valueFromConfig2,
'data': valueFromConfig2,
'baseURL': defaultToConfig2,
'transformRequest': defaultToConfig2,
'transformResponse': defaultToConfig2,
'paramsSerializer': defaultToConfig2,
'timeout': defaultToConfig2,
'timeoutMessage': defaultToConfig2,
'withCredentials': defaultToConfig2,
'adapter': defaultToConfig2,
'responseType': defaultToConfig2,
'xsrfCookieName': defaultToConfig2,
'xsrfHeaderName': defaultToConfig2,
'onUploadProgress': defaultToConfig2,
'onDownloadProgress': defaultToConfig2,
'decompress': defaultToConfig2,
'maxContentLength': defaultToConfig2,
'maxBodyLength': defaultToConfig2,
'transport': defaultToConfig2,
'httpAgent': defaultToConfig2,
'httpsAgent': defaultToConfig2,
'cancelToken': defaultToConfig2,
'socketPath': defaultToConfig2,
'responseEncoding': defaultToConfig2,
'validateStatus': mergeDirectKeys
};
utils.forEach(Object.keys(config1).concat(Object.keys(config2)), function computeConfigValue(prop) {
var merge = mergeMap[prop] || mergeDeepProperties;
var configValue = merge(prop);
(utils.isUndefined(configValue) && merge !== mergeDirectKeys) || (config[prop] = configValue);
});
var axiosKeys = valueFromConfig2Keys
.concat(mergeDeepPropertiesKeys)
.concat(defaultToConfig2Keys)
.concat(directMergeKeys);
var otherKeys = Object
.keys(config1)
.concat(Object.keys(config2))
.filter(function filterAxiosKeys(key) {
return axiosKeys.indexOf(key) === -1;
});
utils.forEach(otherKeys, mergeDeepProperties);
return config;
};
+6 -6
View File
@@ -79,7 +79,7 @@ var defaults = {
}],
transformResponse: [function transformResponse(data) {
var transitional = this.transitional;
var transitional = this.transitional || defaults.transitional;
var silentJSONParsing = transitional && transitional.silentJSONParsing;
var forcedJSONParsing = transitional && transitional.forcedJSONParsing;
var strictJSONParsing = !silentJSONParsing && this.responseType === 'json';
@@ -114,12 +114,12 @@ var defaults = {
validateStatus: function validateStatus(status) {
return status >= 200 && status < 300;
}
};
},
defaults.headers = {
common: {
'Accept': 'application/json, text/plain, */*'
headers: {
common: {
'Accept': 'application/json, text/plain, */*'
}
}
};
+3
View File
@@ -0,0 +1,3 @@
# axios // env
The `data.js` file is updated automatically when the package version is upgrading. Please do not edit it manually.
+3
View File
@@ -0,0 +1,3 @@
module.exports = {
"version": "0.22.0"
};
+7 -30
View File
@@ -1,6 +1,6 @@
'use strict';
var pkg = require('./../../package.json');
var VERSION = require('../env/data').version;
var validators = {};
@@ -12,48 +12,26 @@ var validators = {};
});
var deprecatedWarnings = {};
var currentVerArr = pkg.version.split('.');
/**
* Compare package versions
* @param {string} version
* @param {string?} thanVersion
* @returns {boolean}
*/
function isOlderVersion(version, thanVersion) {
var pkgVersionArr = thanVersion ? thanVersion.split('.') : currentVerArr;
var destVer = version.split('.');
for (var i = 0; i < 3; i++) {
if (pkgVersionArr[i] > destVer[i]) {
return true;
} else if (pkgVersionArr[i] < destVer[i]) {
return false;
}
}
return false;
}
/**
* Transitional option validator
* @param {function|boolean?} validator
* @param {string?} version
* @param {string} message
* @param {function|boolean?} validator - set to false if the transitional option has been removed
* @param {string?} version - deprecated version / removed since version
* @param {string?} message - some message with additional info
* @returns {function}
*/
validators.transitional = function transitional(validator, version, message) {
var isDeprecated = version && isOlderVersion(version);
function formatMessage(opt, desc) {
return '[Axios v' + pkg.version + '] Transitional option \'' + opt + '\'' + desc + (message ? '. ' + message : '');
return '[Axios v' + VERSION + '] Transitional option \'' + opt + '\'' + desc + (message ? '. ' + message : '');
}
// eslint-disable-next-line func-names
return function(value, opt, opts) {
if (validator === false) {
throw new Error(formatMessage(opt, ' has been removed in ' + version));
throw new Error(formatMessage(opt, ' has been removed' + (version ? ' in ' + version : '')));
}
if (isDeprecated && !deprecatedWarnings[opt]) {
if (version && !deprecatedWarnings[opt]) {
deprecatedWarnings[opt] = true;
// eslint-disable-next-line no-console
console.warn(
@@ -99,7 +77,6 @@ function assertOptions(options, schema, allowUnknown) {
}
module.exports = {
isOlderVersion: isOlderVersion,
assertOptions: assertOptions,
validators: validators
};