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

Axios ES2017 (#4787)

* Added AxiosHeaders class;

* Fixed README.md href;

* Fixed a potential bug with headers normalization;

* Fixed a potential bug with headers normalization;
Refactored accessor building routine;
Refactored default transforms;
Removed `normalizeHeaderName` helper;

* Added `Content-Length` accessor;
Added missed `has` accessor to TS types;

* Added `AxiosTransformStream` class;
Added progress capturing ability for node.js environment;
Added `maxRate` option to limit the data rate in node.js environment;
Refactored event handled by `onUploadProgress` && `onDownloadProgress` listeners in browser environment;
Added progress & data rate tests for the http adapter;
Added response stream aborting test;
Added a manual progress capture test for the browser;
Updated TS types;
Added TS tests;
Refactored request abort logic for the http adapter;
Added ability to abort the response stream;

* Remove `stream/promises` & `timers/promises` modules usage in tests;

* Use `abortcontroller-polyfill`;

* Fixed AxiosTransformStream dead-lock in legacy node versions;
Fixed CancelError emitting in streams;

* Reworked AxiosTransformStream internal logic to optimize memory consumption;
Added throwing an error if the request stream was silently destroying (without error) Refers to #3966;

* Treat the destruction of the request stream as a cancellation of the request;
Fixed tests;

* Emit `progress` event in the next tick;

* Initial refactoring;

* Refactored Mocha tests to use ESM;

* Refactored Karma tests to use rollup preprocessor & ESM;
Replaced grunt with gulp;
Improved dev scripts;
Added Babel for rollup build;

* Added default commonjs package export for Node build;
Added automatic contributors list generator for package.json;

Co-authored-by: Jay <jasonsaayman@gmail.com>
This commit is contained in:
Dmitriy Mozgovoy
2022-06-18 12:19:27 +03:00
committed by GitHub
parent 1db715dd3b
commit bdf493cf8b
125 changed files with 10462 additions and 7291 deletions
+191
View File
@@ -0,0 +1,191 @@
'use strict';
import stream from 'stream';
import utils from '../utils.js';
import throttle from './throttle.js';
import speedometer from './speedometer.js';
const kInternals = Symbol('internals');
class AxiosTransformStream extends stream.Transform{
constructor(options) {
options = utils.toFlatObject(options, {
maxRate: 0,
chunkSize: 64 * 1024,
minChunkSize: 100,
timeWindow: 500,
ticksRate: 2,
samplesCount: 15
}, null, (prop, source) => {
return !utils.isUndefined(source[prop]);
});
super({
readableHighWaterMark: options.chunkSize
});
const self = this;
const internals = this[kInternals] = {
length: options.length,
timeWindow: options.timeWindow,
ticksRate: options.ticksRate,
chunkSize: options.chunkSize,
maxRate: options.maxRate,
minChunkSize: options.minChunkSize,
bytesSeen: 0,
isCaptured: false,
notifiedBytesLoaded: 0,
ts: Date.now(),
bytes: 0,
onReadCallback: null
};
const _speedometer = speedometer(internals.ticksRate * options.samplesCount, internals.timeWindow);
this.on('newListener', event => {
if (event === 'progress') {
if (!internals.isCaptured) {
internals.isCaptured = true;
}
}
});
let bytesNotified = 0;
internals.updateProgress = throttle(function throttledHandler() {
const totalBytes = internals.length;
const bytesTransferred = internals.bytesSeen;
const progressBytes = bytesTransferred - bytesNotified;
if (!progressBytes || self.destroyed) return;
const rate = _speedometer(progressBytes);
bytesNotified = bytesTransferred;
process.nextTick(() => {
self.emit('progress', {
'loaded': bytesTransferred,
'total': totalBytes,
'progress': totalBytes ? (bytesTransferred / totalBytes) : undefined,
'bytes': progressBytes,
'rate': rate ? rate : undefined,
'estimated': rate && totalBytes && bytesTransferred <= totalBytes ?
(totalBytes - bytesTransferred) / rate : undefined
});
});
}, internals.ticksRate);
const onFinish = () => {
internals.updateProgress(true);
};
this.once('end', onFinish);
this.once('error', onFinish);
}
_read(size) {
const internals = this[kInternals];
if (internals.onReadCallback) {
internals.onReadCallback();
}
return super._read(size);
}
_transform(chunk, encoding, callback) {
const self = this;
const internals = this[kInternals];
const maxRate = internals.maxRate;
const readableHighWaterMark = this.readableHighWaterMark;
const timeWindow = internals.timeWindow;
const divider = 1000 / timeWindow;
const bytesThreshold = (maxRate / divider);
const minChunkSize = internals.minChunkSize !== false ? Math.max(internals.minChunkSize, bytesThreshold * 0.01) : 0;
function pushChunk(_chunk, _callback) {
const bytes = Buffer.byteLength(_chunk);
internals.bytesSeen += bytes;
internals.bytes += bytes;
if (internals.isCaptured) {
internals.updateProgress();
}
if (self.push(_chunk)) {
process.nextTick(_callback);
} else {
internals.onReadCallback = () => {
internals.onReadCallback = null;
process.nextTick(_callback);
};
}
}
const transformChunk = (_chunk, _callback) => {
const chunkSize = Buffer.byteLength(_chunk);
let chunkRemainder = null;
let maxChunkSize = readableHighWaterMark;
let bytesLeft;
let passed = 0;
if (maxRate) {
const now = Date.now();
if (!internals.ts || (passed = (now - internals.ts)) >= timeWindow) {
internals.ts = now;
bytesLeft = bytesThreshold - internals.bytes;
internals.bytes = bytesLeft < 0 ? -bytesLeft : 0;
passed = 0;
}
bytesLeft = bytesThreshold - internals.bytes;
}
if (maxRate) {
if (bytesLeft <= 0) {
// next time window
return setTimeout(() => {
_callback(null, _chunk);
}, timeWindow - passed);
}
if (bytesLeft < maxChunkSize) {
maxChunkSize = bytesLeft;
}
}
if (maxChunkSize && chunkSize > maxChunkSize && (chunkSize - maxChunkSize) > minChunkSize) {
chunkRemainder = _chunk.subarray(maxChunkSize);
_chunk = _chunk.subarray(0, maxChunkSize);
}
pushChunk(_chunk, chunkRemainder ? () => {
process.nextTick(_callback, null, chunkRemainder);
} : _callback);
};
transformChunk(chunk, function transformNextChunk(err, _chunk) {
if (err) {
return callback(err);
}
if (_chunk) {
transformChunk(_chunk, transformNextChunk);
} else {
callback(null);
}
});
}
setLength(length) {
this[kInternals].length = +length;
return this;
}
}
export default AxiosTransformStream;
+6 -6
View File
@@ -1,6 +1,6 @@
'use strict';
var toFormData = require('./toFormData');
import toFormData from './toFormData.js';
/**
* It encodes a string by replacing all characters that are not in the unreserved set with
@@ -11,7 +11,7 @@ var toFormData = require('./toFormData');
* @returns {string} The encoded string.
*/
function encode(str) {
var charMap = {
const charMap = {
'!': '%21',
"'": '%27',
'(': '%28',
@@ -20,7 +20,7 @@ function encode(str) {
'%20': '+',
'%00': '\x00'
};
return encodeURIComponent(str).replace(/[!'\(\)~]|%20|%00/g, function replacer(match) {
return encodeURIComponent(str).replace(/[!'()~]|%20|%00/g, function replacer(match) {
return charMap[match];
});
}
@@ -39,14 +39,14 @@ function AxiosURLSearchParams(params, options) {
params && toFormData(params, this, options);
}
var prototype = AxiosURLSearchParams.prototype;
const prototype = AxiosURLSearchParams.prototype;
prototype.append = function append(name, value) {
this._pairs.push([name, value]);
};
prototype.toString = function toString(encoder) {
var _encode = encoder ? function(value) {
const _encode = encoder ? function(value) {
return encoder.call(this, value, encode);
} : encode;
@@ -55,4 +55,4 @@ prototype.toString = function toString(encoder) {
}, '').join('&');
};
module.exports = AxiosURLSearchParams;
export default AxiosURLSearchParams;
+2 -2
View File
@@ -1,7 +1,7 @@
'use strict';
module.exports = function bind(fn, thisArg) {
export default function bind(fn, thisArg) {
return function wrap() {
return fn.apply(thisArg, arguments);
};
};
}
+7 -7
View File
@@ -1,7 +1,7 @@
'use strict';
var utils = require('../utils');
var AxiosURLSearchParams = require('../helpers/AxiosURLSearchParams');
import utils from '../utils.js';
import AxiosURLSearchParams from '../helpers/AxiosURLSearchParams.js';
/**
* It replaces all instances of the characters `:`, `$`, `,`, `+`, `[`, and `]` with their
@@ -30,21 +30,21 @@ function encode(val) {
*
* @returns {string} The formatted url
*/
module.exports = function buildURL(url, params, options) {
export default function buildURL(url, params, options) {
/*eslint no-param-reassign:0*/
if (!params) {
return url;
}
var hashmarkIndex = url.indexOf('#');
const hashmarkIndex = url.indexOf('#');
if (hashmarkIndex !== -1) {
url = url.slice(0, hashmarkIndex);
}
var _encode = options && options.encode || encode;
const _encode = options && options.encode || encode;
var serializerParams = utils.isURLSearchParams(params) ?
const serializerParams = utils.isURLSearchParams(params) ?
params.toString() :
new AxiosURLSearchParams(params, options).toString(_encode);
@@ -53,4 +53,4 @@ module.exports = function buildURL(url, params, options) {
}
return url;
};
}
+2 -2
View File
@@ -8,8 +8,8 @@
*
* @returns {string} The combined URL
*/
module.exports = function combineURLs(baseURL, relativeURL) {
export default function combineURLs(baseURL, relativeURL) {
return relativeURL
? baseURL.replace(/\/+$/, '') + '/' + relativeURL.replace(/^\/+/, '')
: baseURL;
};
}
+44 -46
View File
@@ -1,53 +1,51 @@
'use strict';
var utils = require('./../utils');
import utils from './../utils.js';
module.exports = (
utils.isStandardBrowserEnv() ?
export default utils.isStandardBrowserEnv() ?
// Standard browser envs support document.cookie
(function standardBrowserEnv() {
return {
write: function write(name, value, expires, path, domain, secure) {
var cookie = [];
cookie.push(name + '=' + encodeURIComponent(value));
// Standard browser envs support document.cookie
(function standardBrowserEnv() {
return {
write: function write(name, value, expires, path, domain, secure) {
const cookie = [];
cookie.push(name + '=' + encodeURIComponent(value));
if (utils.isNumber(expires)) {
cookie.push('expires=' + new Date(expires).toGMTString());
}
if (utils.isString(path)) {
cookie.push('path=' + path);
}
if (utils.isString(domain)) {
cookie.push('domain=' + domain);
}
if (secure === true) {
cookie.push('secure');
}
document.cookie = cookie.join('; ');
},
read: function read(name) {
var match = document.cookie.match(new RegExp('(^|;\\s*)(' + name + ')=([^;]*)'));
return (match ? decodeURIComponent(match[3]) : null);
},
remove: function remove(name) {
this.write(name, '', Date.now() - 86400000);
if (utils.isNumber(expires)) {
cookie.push('expires=' + new Date(expires).toGMTString());
}
};
})() :
// Non standard browser env (web workers, react-native) lack needed support.
(function nonStandardBrowserEnv() {
return {
write: function write() {},
read: function read() { return null; },
remove: function remove() {}
};
})()
);
if (utils.isString(path)) {
cookie.push('path=' + path);
}
if (utils.isString(domain)) {
cookie.push('domain=' + domain);
}
if (secure === true) {
cookie.push('secure');
}
document.cookie = cookie.join('; ');
},
read: function read(name) {
const match = document.cookie.match(new RegExp('(^|;\\s*)(' + name + ')=([^;]*)'));
return (match ? decodeURIComponent(match[3]) : null);
},
remove: function remove(name) {
this.write(name, '', Date.now() - 86400000);
}
};
})() :
// Non standard browser env (web workers, react-native) lack needed support.
(function nonStandardBrowserEnv() {
return {
write: function write() {},
read: function read() { return null; },
remove: function remove() {}
};
})();
+2 -2
View File
@@ -12,7 +12,7 @@
*
* @returns {void}
*/
module.exports = function deprecatedMethod(method, instead, docs) {
export default function deprecatedMethod(method, instead, docs) {
try {
console.warn(
'DEPRECATED method `' + method + '`.' +
@@ -23,4 +23,4 @@ module.exports = function deprecatedMethod(method, instead, docs) {
console.warn('For more information about usage see ' + docs);
}
} catch (e) { /* Ignore */ }
};
}
+15 -15
View File
@@ -1,6 +1,6 @@
'use strict';
var utils = require('../utils');
import utils from '../utils.js';
/**
* It takes a string like `foo[x][y][z]` and returns an array like `['foo', 'x', 'y', 'z']
@@ -14,7 +14,7 @@ function parsePropPath(name) {
// foo.x.y.z
// foo-x-y-z
// foo x y z
return utils.matchAll(/\w+|\[(\w*)]/g, name).map(function(match) {
return utils.matchAll(/\w+|\[(\w*)]/g, name).map(match => {
return match[0] === '[]' ? '' : match[1] || match[0];
});
}
@@ -27,11 +27,11 @@ function parsePropPath(name) {
* @returns An object with the same keys and values as the array.
*/
function arrayToObject(arr) {
var obj = {};
var keys = Object.keys(arr);
var i;
var len = keys.length;
var key;
const obj = {};
const keys = Object.keys(arr);
let i;
const len = keys.length;
let key;
for (i = 0; i < len; i++) {
key = keys[i];
obj[key] = arr[key];
@@ -48,13 +48,13 @@ function arrayToObject(arr) {
*/
function formDataToJSON(formData) {
function buildPath(path, value, target, index) {
var name = path[index++];
var isNumericKey = Number.isFinite(+name);
var isLast = index >= path.length;
let name = path[index++];
const isNumericKey = Number.isFinite(+name);
const isLast = index >= path.length;
name = !name && utils.isArray(target) ? target.length : name;
if (isLast) {
if (utils.hasOwnProperty(target, name)) {
if (utils.hasOwnProp(target, name)) {
target[name] = [target[name], value];
} else {
target[name] = value;
@@ -67,7 +67,7 @@ function formDataToJSON(formData) {
target[name] = [];
}
var result = buildPath(path, value, target[name], index);
const result = buildPath(path, value, target[name], index);
if (result && utils.isArray(target[name])) {
target[name] = arrayToObject(target[name]);
@@ -77,9 +77,9 @@ function formDataToJSON(formData) {
}
if (utils.isFormData(formData) && utils.isFunction(formData.entries)) {
var obj = {};
const obj = {};
utils.forEachEntry(formData, function(name, value) {
utils.forEachEntry(formData, (name, value) => {
buildPath(parsePropPath(name), value, obj, 0);
});
@@ -89,4 +89,4 @@ function formDataToJSON(formData) {
return null;
}
module.exports = formDataToJSON;
export default formDataToJSON;
+13 -13
View File
@@ -1,10 +1,10 @@
'use strict';
var AxiosError = require('../core/AxiosError');
var parseProtocol = require('./parseProtocol');
var platform = require('../platform');
import AxiosError from '../core/AxiosError.js';
import parseProtocol from './parseProtocol.js';
import platform from '../platform/index.js';
var DATA_URL_PATTERN = /^(?:([^;]+);)?(?:[^;]+;)?(base64|),([\s\S]*)$/;
const DATA_URL_PATTERN = /^(?:([^;]+);)?(?:[^;]+;)?(base64|),([\s\S]*)$/;
/**
* Parse data uri to a Buffer or Blob
@@ -16,9 +16,9 @@ var DATA_URL_PATTERN = /^(?:([^;]+);)?(?:[^;]+;)?(base64|),([\s\S]*)$/;
*
* @returns {Buffer|Blob}
*/
module.exports = function fromDataURI(uri, asBlob, options) {
var _Blob = options && options.Blob || platform.classes.Blob;
var protocol = parseProtocol(uri);
export default function fromDataURI(uri, asBlob, options) {
const _Blob = options && options.Blob || platform.classes.Blob;
const protocol = parseProtocol(uri);
if (asBlob === undefined && _Blob) {
asBlob = true;
@@ -27,16 +27,16 @@ module.exports = function fromDataURI(uri, asBlob, options) {
if (protocol === 'data') {
uri = protocol.length ? uri.slice(protocol.length + 1) : uri;
var match = DATA_URL_PATTERN.exec(uri);
const 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');
const mime = match[1];
const isBase64 = match[2];
const body = match[3];
const buffer = Buffer.from(decodeURIComponent(body), isBase64 ? 'base64' : 'utf8');
if (asBlob) {
if (!_Blob) {
@@ -50,4 +50,4 @@ module.exports = function fromDataURI(uri, asBlob, options) {
}
throw new AxiosError('Unsupported protocol ' + protocol, AxiosError.ERR_NOT_SUPPORT);
};
}
+2 -2
View File
@@ -7,9 +7,9 @@
*
* @returns {boolean} True if the specified URL is absolute, otherwise false
*/
module.exports = function isAbsoluteURL(url) {
export default function isAbsoluteURL(url) {
// A URL is considered absolute if it begins with "<scheme>://" or "//" (protocol-relative URL).
// RFC 3986 defines scheme name as a sequence of characters beginning with a letter and followed
// by any combination of letters, digits, plus, period, or hyphen.
return /^([a-z][a-z\d+\-.]*:)?\/\//i.test(url);
};
}
+3 -3
View File
@@ -1,6 +1,6 @@
'use strict';
var utils = require('./../utils');
import utils from './../utils.js';
/**
* Determines whether the payload is an error thrown by Axios
@@ -9,6 +9,6 @@ var utils = require('./../utils');
*
* @returns {boolean} True if the payload is an error thrown by Axios, otherwise false
*/
module.exports = function isAxiosError(payload) {
export default function isAxiosError(payload) {
return utils.isObject(payload) && (payload.isAxiosError === true);
};
}
+54 -56
View File
@@ -1,68 +1,66 @@
'use strict';
var utils = require('./../utils');
import utils from './../utils.js';
module.exports = (
utils.isStandardBrowserEnv() ?
export default utils.isStandardBrowserEnv() ?
// Standard browser envs have full support of the APIs needed to test
// whether the request URL is of the same origin as current location.
(function standardBrowserEnv() {
var msie = /(msie|trident)/i.test(navigator.userAgent);
var urlParsingNode = document.createElement('a');
var originURL;
// Standard browser envs have full support of the APIs needed to test
// whether the request URL is of the same origin as current location.
(function standardBrowserEnv() {
const msie = /(msie|trident)/i.test(navigator.userAgent);
const urlParsingNode = document.createElement('a');
let originURL;
/**
* Parse a URL to discover it's components
*
* @param {String} url The URL to be parsed
* @returns {Object}
*/
function resolveURL(url) {
var href = url;
if (msie) {
// IE needs attribute set twice to normalize properties
urlParsingNode.setAttribute('href', href);
href = urlParsingNode.href;
}
/**
* Parse a URL to discover it's components
*
* @param {String} url The URL to be parsed
* @returns {Object}
*/
function resolveURL(url) {
let href = url;
if (msie) {
// IE needs attribute set twice to normalize properties
urlParsingNode.setAttribute('href', href);
// urlParsingNode provides the UrlUtils interface - http://url.spec.whatwg.org/#urlutils
return {
href: urlParsingNode.href,
protocol: urlParsingNode.protocol ? urlParsingNode.protocol.replace(/:$/, '') : '',
host: urlParsingNode.host,
search: urlParsingNode.search ? urlParsingNode.search.replace(/^\?/, '') : '',
hash: urlParsingNode.hash ? urlParsingNode.hash.replace(/^#/, '') : '',
hostname: urlParsingNode.hostname,
port: urlParsingNode.port,
pathname: (urlParsingNode.pathname.charAt(0) === '/') ?
urlParsingNode.pathname :
'/' + urlParsingNode.pathname
};
href = urlParsingNode.href;
}
originURL = resolveURL(window.location.href);
urlParsingNode.setAttribute('href', href);
/**
* Determine if a URL shares the same origin as the current location
*
* @param {String} requestURL The URL to test
* @returns {boolean} True if URL shares the same origin, otherwise false
*/
return function isURLSameOrigin(requestURL) {
var parsed = (utils.isString(requestURL)) ? resolveURL(requestURL) : requestURL;
return (parsed.protocol === originURL.protocol &&
parsed.host === originURL.host);
// urlParsingNode provides the UrlUtils interface - http://url.spec.whatwg.org/#urlutils
return {
href: urlParsingNode.href,
protocol: urlParsingNode.protocol ? urlParsingNode.protocol.replace(/:$/, '') : '',
host: urlParsingNode.host,
search: urlParsingNode.search ? urlParsingNode.search.replace(/^\?/, '') : '',
hash: urlParsingNode.hash ? urlParsingNode.hash.replace(/^#/, '') : '',
hostname: urlParsingNode.hostname,
port: urlParsingNode.port,
pathname: (urlParsingNode.pathname.charAt(0) === '/') ?
urlParsingNode.pathname :
'/' + urlParsingNode.pathname
};
})() :
}
// Non standard browser envs (web workers, react-native) lack needed support.
(function nonStandardBrowserEnv() {
return function isURLSameOrigin() {
return true;
};
})()
);
originURL = resolveURL(window.location.href);
/**
* Determine if a URL shares the same origin as the current location
*
* @param {String} requestURL The URL to test
* @returns {boolean} True if URL shares the same origin, otherwise false
*/
return function isURLSameOrigin(requestURL) {
const parsed = (utils.isString(requestURL)) ? resolveURL(requestURL) : requestURL;
return (parsed.protocol === originURL.protocol &&
parsed.host === originURL.host);
};
})() :
// Non standard browser envs (web workers, react-native) lack needed support.
(function nonStandardBrowserEnv() {
return function isURLSameOrigin() {
return true;
};
})();
-12
View File
@@ -1,12 +0,0 @@
'use strict';
var utils = require('../utils');
module.exports = function normalizeHeaderName(headers, normalizedName) {
utils.forEach(headers, function processHeader(value, name) {
if (name !== normalizedName && name.toUpperCase() === normalizedName.toUpperCase()) {
headers[normalizedName] = value;
delete headers[name];
}
});
};
+1 -1
View File
@@ -1,2 +1,2 @@
// eslint-disable-next-line strict
module.exports = null;
export default null;
+23 -22
View File
@@ -1,15 +1,15 @@
'use strict';
var utils = require('./../utils');
import utils from './../utils.js';
// Headers whose duplicates are ignored by node
// RawAxiosHeaders whose duplicates are ignored by node
// c.f. https://nodejs.org/api/http.html#http_message_headers
var ignoreDuplicateOf = [
const ignoreDuplicateOf = utils.toObjectSet([
'age', 'authorization', 'content-length', 'content-type', 'etag',
'expires', 'from', 'host', 'if-modified-since', 'if-unmodified-since',
'last-modified', 'location', 'max-forwards', 'proxy-authorization',
'referer', 'retry-after', 'user-agent'
];
]);
/**
* Parse headers into an object
@@ -21,32 +21,33 @@ var ignoreDuplicateOf = [
* Transfer-Encoding: chunked
* ```
*
* @param {String} headers Headers needing to be parsed
* @param {String} rawHeaders Headers needing to be parsed
*
* @returns {Object} Headers parsed into an object
*/
module.exports = function parseHeaders(headers) {
var parsed = {};
var key;
var val;
var i;
export default rawHeaders => {
const parsed = {};
let key;
let val;
let i;
if (!headers) { return parsed; }
utils.forEach(headers.split('\n'), function parser(line) {
rawHeaders && rawHeaders.split('\n').forEach(function parser(line) {
i = line.indexOf(':');
key = utils.trim(line.slice(0, i)).toLowerCase();
val = utils.trim(line.slice(i + 1));
key = line.substring(0, i).trim().toLowerCase();
val = line.substring(i + 1).trim();
if (key) {
if (parsed[key] && ignoreDuplicateOf.indexOf(key) >= 0) {
return;
}
if (key === 'set-cookie') {
parsed[key] = (parsed[key] ? parsed[key] : []).concat([val]);
if (!key || (parsed[key] && ignoreDuplicateOf[key])) {
return;
}
if (key === 'set-cookie') {
if (parsed[key]) {
parsed[key].push(val);
} else {
parsed[key] = parsed[key] ? parsed[key] + ', ' + val : val;
parsed[key] = [val];
}
} else {
parsed[key] = parsed[key] ? parsed[key] + ', ' + val : val;
}
});
+3 -3
View File
@@ -1,6 +1,6 @@
'use strict';
module.exports = function parseProtocol(url) {
var match = /^([-+\w]{1,25})(:?\/\/|:)/.exec(url);
export default function parseProtocol(url) {
const match = /^([-+\w]{1,25})(:?\/\/|:)/.exec(url);
return match && match[1] || '';
};
}
+55
View File
@@ -0,0 +1,55 @@
'use strict';
/**
* Calculate data maxRate
* @param {Number} [samplesCount= 10]
* @param {Number} [min= 1000]
* @returns {Function}
*/
function speedometer(samplesCount, min) {
samplesCount = samplesCount || 10;
const bytes = new Array(samplesCount);
const timestamps = new Array(samplesCount);
let head = 0;
let tail = 0;
let firstSampleTS;
min = min !== undefined ? min : 1000;
return function push(chunkLength) {
const now = Date.now();
const startedAt = timestamps[tail];
if (!firstSampleTS) {
firstSampleTS = now;
}
bytes[head] = chunkLength;
timestamps[head] = now;
let i = tail;
let bytesCount = 0;
while (i !== head) {
bytesCount += bytes[i++];
i = i % samplesCount;
}
head = (head + 1) % samplesCount;
if (head === tail) {
tail = (tail + 1) % samplesCount;
}
if (now - firstSampleTS < min) {
return;
}
const passed = startedAt && now - startedAt;
return passed ? Math.round(bytesCount * 1000 / passed) : undefined;
};
}
export default speedometer;
+2 -2
View File
@@ -21,8 +21,8 @@
*
* @returns {Function}
*/
module.exports = function spread(callback) {
export default function spread(callback) {
return function wrap(arr) {
return callback.apply(null, arr);
};
};
}
+33
View File
@@ -0,0 +1,33 @@
'use strict';
/**
* Throttle decorator
* @param {Function} fn
* @param {Number} freq
* @return {Function}
*/
function throttle(fn, freq) {
let timestamp = 0;
const threshold = 1000 / freq;
let timer = null;
return function throttled(force, args) {
const now = Date.now();
if (force || now - timestamp > threshold) {
if (timer) {
clearTimeout(timer);
timer = null;
}
timestamp = now;
return fn.apply(null, args);
}
if (!timer) {
timer = setTimeout(() => {
timer = null;
timestamp = Date.now();
return fn.apply(null, args);
}, threshold - (now - timestamp));
}
};
}
export default throttle;
+18 -18
View File
@@ -1,8 +1,8 @@
'use strict';
var utils = require('../utils');
var AxiosError = require('../core/AxiosError');
var envFormData = require('../env/classes/FormData');
import utils from '../utils.js';
import AxiosError from '../core/AxiosError.js';
import envFormData from '../env/classes/FormData.js';
/**
* Determines if the given thing is a array or js object.
@@ -55,7 +55,7 @@ function isFlatArray(arr) {
return utils.isArray(arr) && !arr.some(isVisitable);
}
var predicates = utils.toFlatObject(utils, {}, null, function filter(prop) {
const predicates = utils.toFlatObject(utils, {}, null, function filter(prop) {
return /^is[A-Z]/.test(prop);
});
@@ -111,13 +111,13 @@ function toFormData(obj, formData, options) {
return !utils.isUndefined(source[option]);
});
var metaTokens = options.metaTokens;
const metaTokens = options.metaTokens;
// eslint-disable-next-line no-use-before-define
var visitor = options.visitor || defaultVisitor;
var dots = options.dots;
var indexes = options.indexes;
var _Blob = options.Blob || typeof Blob !== 'undefined' && Blob;
var useBlob = _Blob && isSpecCompliant(formData);
const visitor = options.visitor || defaultVisitor;
const dots = options.dots;
const indexes = options.indexes;
const _Blob = options.Blob || typeof Blob !== 'undefined' && Blob;
const useBlob = _Blob && isSpecCompliant(formData);
if (!utils.isFunction(visitor)) {
throw new TypeError('visitor must be a function');
@@ -152,7 +152,7 @@ function toFormData(obj, formData, options) {
* @returns {boolean} return true to visit the each prop of the value recursively
*/
function defaultVisitor(value, key, path) {
var arr = value;
let arr = value;
if (value && !path && typeof value === 'object') {
if (utils.endsWith(key, '{}')) {
@@ -187,12 +187,12 @@ function toFormData(obj, formData, options) {
return false;
}
var stack = [];
const stack = [];
var exposedHelpers = Object.assign(predicates, {
defaultVisitor: defaultVisitor,
convertValue: convertValue,
isVisitable: isVisitable
const exposedHelpers = Object.assign(predicates, {
defaultVisitor,
convertValue,
isVisitable
});
function build(value, path) {
@@ -205,7 +205,7 @@ function toFormData(obj, formData, options) {
stack.push(value);
utils.forEach(value, function each(el, key) {
var result = !utils.isUndefined(el) && visitor.call(
const result = !utils.isUndefined(el) && visitor.call(
formData, el, utils.isString(key) ? key.trim() : key, path, exposedHelpers
);
@@ -226,4 +226,4 @@ function toFormData(obj, formData, options) {
return formData;
}
module.exports = toFormData;
export default toFormData;
+5 -5
View File
@@ -1,10 +1,10 @@
'use strict';
var utils = require('../utils');
var toFormData = require('./toFormData');
var platform = require('../platform/');
import utils from '../utils.js';
import toFormData from './toFormData.js';
import platform from '../platform/index.js';
module.exports = function toURLEncodedForm(data, options) {
export default function toURLEncodedForm(data, options) {
return toFormData(data, new platform.classes.URLSearchParams(), Object.assign({
visitor: function(value, key, path, helpers) {
if (platform.isNode && utils.isBuffer(value)) {
@@ -15,4 +15,4 @@ module.exports = function toURLEncodedForm(data, options) {
return helpers.defaultVisitor.apply(this, arguments);
}
}, options));
};
}
+15 -15
View File
@@ -1,18 +1,18 @@
'use strict';
var VERSION = require('../env/data').version;
var AxiosError = require('../core/AxiosError');
import {VERSION} from '../env/data.js';
import AxiosError from '../core/AxiosError.js';
var validators = {};
const validators = {};
// eslint-disable-next-line func-names
['object', 'boolean', 'number', 'function', 'string', 'symbol'].forEach(function(type, i) {
['object', 'boolean', 'number', 'function', 'string', 'symbol'].forEach((type, i) => {
validators[type] = function validator(thing) {
return typeof thing === type || 'a' + (i < 1 ? 'n ' : ' ') + type;
};
});
var deprecatedWarnings = {};
const deprecatedWarnings = {};
/**
* Transitional option validator
@@ -29,7 +29,7 @@ validators.transitional = function transitional(validator, version, message) {
}
// eslint-disable-next-line func-names
return function(value, opt, opts) {
return (value, opt, opts) => {
if (validator === false) {
throw new AxiosError(
formatMessage(opt, ' has been removed' + (version ? ' in ' + version : '')),
@@ -66,14 +66,14 @@ function assertOptions(options, schema, allowUnknown) {
if (typeof options !== 'object') {
throw new AxiosError('options must be an object', AxiosError.ERR_BAD_OPTION_VALUE);
}
var keys = Object.keys(options);
var i = keys.length;
const keys = Object.keys(options);
let i = keys.length;
while (i-- > 0) {
var opt = keys[i];
var validator = schema[opt];
const opt = keys[i];
const validator = schema[opt];
if (validator) {
var value = options[opt];
var result = value === undefined || validator(value, opt, options);
const value = options[opt];
const result = value === undefined || validator(value, opt, options);
if (result !== true) {
throw new AxiosError('option ' + opt + ' must be ' + result, AxiosError.ERR_BAD_OPTION_VALUE);
}
@@ -85,7 +85,7 @@ function assertOptions(options, schema, allowUnknown) {
}
}
module.exports = {
assertOptions: assertOptions,
validators: validators
export default {
assertOptions,
validators
};