axios 0.30.3 → 0.31.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +26 -7
- package/UPGRADE_GUIDE.md +2 -2
- package/dist/axios.js +98 -31
- package/dist/axios.js.map +1 -1
- package/dist/axios.min.js +1 -1
- package/dist/axios.min.js.map +1 -1
- package/dist/esm/axios.js +98 -31
- package/dist/esm/axios.js.map +1 -1
- package/dist/esm/axios.min.js +1 -1
- package/dist/esm/axios.min.js.map +1 -1
- package/index.d.ts +3 -2
- package/lib/adapters/http.js +89 -10
- package/lib/adapters/xhr.js +7 -3
- package/lib/core/AxiosError.js +2 -1
- package/lib/core/dispatchRequest.js +5 -0
- package/lib/core/mergeConfig.js +20 -10
- package/lib/defaults/index.js +6 -3
- package/lib/env/data.js +2 -2
- package/lib/helpers/AxiosURLSearchParams.js +4 -3
- package/lib/helpers/sanitizeHeaderValue.js +22 -0
- package/lib/helpers/shouldBypassProxy.js +133 -0
- package/lib/helpers/toFormData.js +14 -3
- package/lib/utils.js +20 -6
- package/package.json +1 -1
package/lib/adapters/http.js
CHANGED
|
@@ -19,6 +19,7 @@ var platform = require('../platform');
|
|
|
19
19
|
var fromDataURI = require('../helpers/fromDataURI');
|
|
20
20
|
var stream = require('stream');
|
|
21
21
|
var estimateDataURLDecodedBytes = require('../helpers/estimateDataURLDecodedBytes.js');
|
|
22
|
+
var shouldBypassProxy = require('../helpers/shouldBypassProxy');
|
|
22
23
|
|
|
23
24
|
var isHttps = /https:?/;
|
|
24
25
|
|
|
@@ -46,9 +47,11 @@ function setProxy(options, configProxy, location) {
|
|
|
46
47
|
if (!proxy && proxy !== false) {
|
|
47
48
|
var proxyUrl = getProxyForUrl(location);
|
|
48
49
|
if (proxyUrl) {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
50
|
+
if (!shouldBypassProxy(location)) {
|
|
51
|
+
proxy = url.parse(proxyUrl);
|
|
52
|
+
// replace 'host' since the proxy object is not a URL object
|
|
53
|
+
proxy.host = proxy.hostname;
|
|
54
|
+
}
|
|
52
55
|
}
|
|
53
56
|
}
|
|
54
57
|
if (proxy) {
|
|
@@ -142,8 +145,9 @@ module.exports = function httpAdapter(config) {
|
|
|
142
145
|
}
|
|
143
146
|
|
|
144
147
|
try {
|
|
148
|
+
var envOption = utils.hasOwnProperty(config, 'env') ? config.env : undefined;
|
|
145
149
|
convertedData = fromDataURI(config.url, responseType === 'blob', {
|
|
146
|
-
Blob:
|
|
150
|
+
Blob: envOption && envOption.Blob
|
|
147
151
|
});
|
|
148
152
|
} catch (err) {
|
|
149
153
|
throw AxiosError.from(err, AxiosError.ERR_BAD_REQUEST, config);
|
|
@@ -197,7 +201,8 @@ module.exports = function httpAdapter(config) {
|
|
|
197
201
|
}
|
|
198
202
|
|
|
199
203
|
// support for https://www.npmjs.com/package/form-data api
|
|
200
|
-
if (utils.isFormData(data) && utils.isFunction(data.getHeaders)
|
|
204
|
+
if (utils.isFormData(data) && utils.isFunction(data.getHeaders) &&
|
|
205
|
+
data.getHeaders !== Object.prototype.getHeaders) {
|
|
201
206
|
Object.assign(headers, data.getHeaders());
|
|
202
207
|
} else if (data && !utils.isStream(data)) {
|
|
203
208
|
if (Buffer.isBuffer(data)) {
|
|
@@ -273,13 +278,13 @@ module.exports = function httpAdapter(config) {
|
|
|
273
278
|
} else {
|
|
274
279
|
options.hostname = parsed.hostname;
|
|
275
280
|
options.port = parsed.port;
|
|
276
|
-
setProxy(options, config.proxy, protocol + '//' + parsed.
|
|
281
|
+
setProxy(options, config.proxy, protocol + '//' + parsed.host + options.path);
|
|
277
282
|
}
|
|
278
283
|
|
|
279
284
|
var transport;
|
|
280
285
|
var isHttpsRequest = isHttps.test(options.protocol);
|
|
281
286
|
options.agent = isHttpsRequest ? config.httpsAgent : config.httpAgent;
|
|
282
|
-
if (config.transport) {
|
|
287
|
+
if (utils.hasOwnProperty(config, 'transport') && config.transport) {
|
|
283
288
|
transport = config.transport;
|
|
284
289
|
} else if (config.maxRedirects === 0) {
|
|
285
290
|
transport = isHttpsRequest ? https : http;
|
|
@@ -345,8 +350,47 @@ module.exports = function httpAdapter(config) {
|
|
|
345
350
|
};
|
|
346
351
|
|
|
347
352
|
if (responseType === 'stream') {
|
|
348
|
-
|
|
349
|
-
|
|
353
|
+
// Enforce maxContentLength on streamed responses too (GHSA-vf2m-468p-8v99).
|
|
354
|
+
// Previously the stream path bypassed the size guard because the check only
|
|
355
|
+
// ran on the buffering branch.
|
|
356
|
+
if (config.maxContentLength > -1) {
|
|
357
|
+
var maxContentLength = config.maxContentLength;
|
|
358
|
+
var streamedBytes = 0;
|
|
359
|
+
var limiter = new stream.Transform({
|
|
360
|
+
transform: function transformChunk(chunk, encoding, callback) {
|
|
361
|
+
streamedBytes += chunk.length;
|
|
362
|
+
if (streamedBytes > maxContentLength) {
|
|
363
|
+
callback(new AxiosError(
|
|
364
|
+
'maxContentLength size of ' + maxContentLength + ' exceeded',
|
|
365
|
+
AxiosError.ERR_BAD_RESPONSE,
|
|
366
|
+
config,
|
|
367
|
+
lastRequest
|
|
368
|
+
));
|
|
369
|
+
return;
|
|
370
|
+
}
|
|
371
|
+
callback(null, chunk);
|
|
372
|
+
}
|
|
373
|
+
});
|
|
374
|
+
limiter.on('error', function handleLimiterError() {
|
|
375
|
+
rejected = true;
|
|
376
|
+
responseStream.destroy();
|
|
377
|
+
});
|
|
378
|
+
responseStream.on('error', function forwardError(err) {
|
|
379
|
+
limiter.destroy(err);
|
|
380
|
+
});
|
|
381
|
+
response.data = limiter;
|
|
382
|
+
settle(resolve, reject, response);
|
|
383
|
+
// Defer piping via setImmediate so the caller's `.then` (a microtask)
|
|
384
|
+
// has run and attached any `error`/`data` listeners before chunks flow
|
|
385
|
+
// through the transform. `process.nextTick` would drain before those
|
|
386
|
+
// microtasks and lose the error event.
|
|
387
|
+
setImmediate(function startPipe() {
|
|
388
|
+
responseStream.pipe(limiter);
|
|
389
|
+
});
|
|
390
|
+
} else {
|
|
391
|
+
response.data = responseStream;
|
|
392
|
+
settle(resolve, reject, response);
|
|
393
|
+
}
|
|
350
394
|
} else {
|
|
351
395
|
var responseBuffer = [];
|
|
352
396
|
var totalResponseBytes = 0;
|
|
@@ -471,7 +515,42 @@ module.exports = function httpAdapter(config) {
|
|
|
471
515
|
if (utils.isStream(data)) {
|
|
472
516
|
data.on('error', function handleStreamError(err) {
|
|
473
517
|
reject(AxiosError.from(err, config, null, req));
|
|
474
|
-
})
|
|
518
|
+
});
|
|
519
|
+
|
|
520
|
+
// follow-redirects enforces options.maxBodyLength for stream uploads, but the
|
|
521
|
+
// native http/https transport (used when maxRedirects === 0) does not.
|
|
522
|
+
// Count bytes ourselves so the limit is always honored (GHSA-5c9x-8gcm-mpgx).
|
|
523
|
+
var nativeTransport = transport === http || transport === https;
|
|
524
|
+
if (nativeTransport && config.maxBodyLength > -1) {
|
|
525
|
+
var maxBodyLength = config.maxBodyLength;
|
|
526
|
+
var uploadedBytes = 0;
|
|
527
|
+
var bodyLimiter = new stream.Transform({
|
|
528
|
+
transform: function transformChunk(chunk, encoding, callback) {
|
|
529
|
+
uploadedBytes += chunk.length;
|
|
530
|
+
if (uploadedBytes > maxBodyLength) {
|
|
531
|
+
callback(new AxiosError(
|
|
532
|
+
'Request body larger than maxBodyLength limit',
|
|
533
|
+
AxiosError.ERR_BAD_REQUEST,
|
|
534
|
+
config,
|
|
535
|
+
req
|
|
536
|
+
));
|
|
537
|
+
return;
|
|
538
|
+
}
|
|
539
|
+
callback(null, chunk);
|
|
540
|
+
}
|
|
541
|
+
});
|
|
542
|
+
bodyLimiter.on('error', function handleLimiterError(err) {
|
|
543
|
+
if (rejected) return;
|
|
544
|
+
rejected = true;
|
|
545
|
+
try { data.unpipe(bodyLimiter); } catch (e) { /* noop */ }
|
|
546
|
+
try { bodyLimiter.unpipe(req); } catch (e) { /* noop */ }
|
|
547
|
+
req.destroy();
|
|
548
|
+
reject(err);
|
|
549
|
+
});
|
|
550
|
+
data.pipe(bodyLimiter).pipe(req);
|
|
551
|
+
} else {
|
|
552
|
+
data.pipe(req);
|
|
553
|
+
}
|
|
475
554
|
} else {
|
|
476
555
|
req.end(data);
|
|
477
556
|
}
|
package/lib/adapters/xhr.js
CHANGED
|
@@ -18,7 +18,8 @@ module.exports = function xhrAdapter(config) {
|
|
|
18
18
|
var requestData = config.data;
|
|
19
19
|
var requestHeaders = config.headers;
|
|
20
20
|
var responseType = config.responseType;
|
|
21
|
-
|
|
21
|
+
// Guard against prototype pollution (GHSA-xx6v-rp6x-q39c): only honor own properties.
|
|
22
|
+
var withXSRFToken = utils.hasOwnProperty(config, 'withXSRFToken') ? config.withXSRFToken : undefined;
|
|
22
23
|
var onCanceled;
|
|
23
24
|
function done() {
|
|
24
25
|
if (config.cancelToken) {
|
|
@@ -146,8 +147,11 @@ module.exports = function xhrAdapter(config) {
|
|
|
146
147
|
// Specifically not if we're in a web worker, or react-native.
|
|
147
148
|
if (utils.isStandardBrowserEnv()) {
|
|
148
149
|
// Add xsrf header
|
|
149
|
-
|
|
150
|
-
|
|
150
|
+
if (utils.isFunction(withXSRFToken)) {
|
|
151
|
+
withXSRFToken = withXSRFToken(config);
|
|
152
|
+
}
|
|
153
|
+
// Strict boolean check (GHSA-xx6v-rp6x-q39c): only `true` short-circuits the same-origin guard.
|
|
154
|
+
if (withXSRFToken === true || (withXSRFToken !== false && isURLSameOrigin(fullPath))) {
|
|
151
155
|
// Add xsrf header
|
|
152
156
|
var xsrfValue = config.xsrfHeaderName && config.xsrfCookieName && cookies.read(config.xsrfCookieName);
|
|
153
157
|
if (xsrfValue) {
|
package/lib/core/AxiosError.js
CHANGED
|
@@ -66,7 +66,8 @@ var descriptors = {};
|
|
|
66
66
|
'ERR_BAD_REQUEST',
|
|
67
67
|
'ERR_CANCELED',
|
|
68
68
|
'ERR_NOT_SUPPORT',
|
|
69
|
-
'ERR_INVALID_URL'
|
|
69
|
+
'ERR_INVALID_URL',
|
|
70
|
+
'ERR_FORM_DATA_DEPTH_EXCEEDED'
|
|
70
71
|
// eslint-disable-next-line func-names
|
|
71
72
|
].forEach(function(code) {
|
|
72
73
|
descriptors[code] = {value: code};
|
|
@@ -6,6 +6,7 @@ var isCancel = require('../cancel/isCancel');
|
|
|
6
6
|
var defaults = require('../defaults');
|
|
7
7
|
var CanceledError = require('../cancel/CanceledError');
|
|
8
8
|
var normalizeHeaderName = require('../helpers/normalizeHeaderName');
|
|
9
|
+
var sanitizeHeaderValue = require('../helpers/sanitizeHeaderValue');
|
|
9
10
|
|
|
10
11
|
/**
|
|
11
12
|
* Throws a `CanceledError` if cancellation has been requested.
|
|
@@ -58,6 +59,10 @@ module.exports = function dispatchRequest(config) {
|
|
|
58
59
|
}
|
|
59
60
|
);
|
|
60
61
|
|
|
62
|
+
utils.forEach(config.headers, function sanitizeHeaderConfigValue(value, header) {
|
|
63
|
+
config.headers[header] = sanitizeHeaderValue(value);
|
|
64
|
+
});
|
|
65
|
+
|
|
61
66
|
var adapter = config.adapter || defaults.adapter;
|
|
62
67
|
|
|
63
68
|
return adapter(config).then(function onAdapterResolution(response) {
|
package/lib/core/mergeConfig.js
CHANGED
|
@@ -13,7 +13,17 @@ var utils = require('../utils');
|
|
|
13
13
|
module.exports = function mergeConfig(config1, config2) {
|
|
14
14
|
// eslint-disable-next-line no-param-reassign
|
|
15
15
|
config2 = config2 || {};
|
|
16
|
-
|
|
16
|
+
// Use a null-prototype object so a polluted Object.prototype cannot leak
|
|
17
|
+
// values (e.g. transport, adapter) into the returned config via inheritance.
|
|
18
|
+
var config = Object.create(null);
|
|
19
|
+
|
|
20
|
+
function getOwn(source, prop) {
|
|
21
|
+
return utils.hasOwnProperty(source, prop) ? source[prop] : undefined;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function hasOwn(source, prop) {
|
|
25
|
+
return utils.hasOwnProperty(source, prop);
|
|
26
|
+
}
|
|
17
27
|
|
|
18
28
|
function getMergedValue(target, source) {
|
|
19
29
|
if (utils.isPlainObject(target) && utils.isPlainObject(source)) {
|
|
@@ -30,34 +40,34 @@ module.exports = function mergeConfig(config1, config2) {
|
|
|
30
40
|
|
|
31
41
|
// eslint-disable-next-line consistent-return
|
|
32
42
|
function mergeDeepProperties(prop) {
|
|
33
|
-
if (!utils.isUndefined(config2[prop])) {
|
|
34
|
-
return getMergedValue(config1
|
|
35
|
-
} else if (!utils.isUndefined(config1[prop])) {
|
|
43
|
+
if (hasOwn(config2, prop) && !utils.isUndefined(config2[prop])) {
|
|
44
|
+
return getMergedValue(getOwn(config1, prop), config2[prop]);
|
|
45
|
+
} else if (hasOwn(config1, prop) && !utils.isUndefined(config1[prop])) {
|
|
36
46
|
return getMergedValue(undefined, config1[prop]);
|
|
37
47
|
}
|
|
38
48
|
}
|
|
39
49
|
|
|
40
50
|
// eslint-disable-next-line consistent-return
|
|
41
51
|
function valueFromConfig2(prop) {
|
|
42
|
-
if (!utils.isUndefined(config2[prop])) {
|
|
52
|
+
if (hasOwn(config2, prop) && !utils.isUndefined(config2[prop])) {
|
|
43
53
|
return getMergedValue(undefined, config2[prop]);
|
|
44
54
|
}
|
|
45
55
|
}
|
|
46
56
|
|
|
47
57
|
// eslint-disable-next-line consistent-return
|
|
48
58
|
function defaultToConfig2(prop) {
|
|
49
|
-
if (!utils.isUndefined(config2[prop])) {
|
|
59
|
+
if (hasOwn(config2, prop) && !utils.isUndefined(config2[prop])) {
|
|
50
60
|
return getMergedValue(undefined, config2[prop]);
|
|
51
|
-
} else if (!utils.isUndefined(config1[prop])) {
|
|
61
|
+
} else if (hasOwn(config1, prop) && !utils.isUndefined(config1[prop])) {
|
|
52
62
|
return getMergedValue(undefined, config1[prop]);
|
|
53
63
|
}
|
|
54
64
|
}
|
|
55
65
|
|
|
56
66
|
// eslint-disable-next-line consistent-return
|
|
57
67
|
function mergeDirectKeys(prop) {
|
|
58
|
-
if (prop
|
|
59
|
-
return getMergedValue(config1
|
|
60
|
-
} else if (prop
|
|
68
|
+
if (hasOwn(config2, prop)) {
|
|
69
|
+
return getMergedValue(getOwn(config1, prop), config2[prop]);
|
|
70
|
+
} else if (hasOwn(config1, prop)) {
|
|
61
71
|
return getMergedValue(undefined, config1[prop]);
|
|
62
72
|
}
|
|
63
73
|
}
|
package/lib/defaults/index.js
CHANGED
|
@@ -89,17 +89,20 @@ var defaults = {
|
|
|
89
89
|
var isFileList;
|
|
90
90
|
|
|
91
91
|
if (isObjectPayload) {
|
|
92
|
+
var formSerializer = utils.hasOwnProperty(this, 'formSerializer') ? this.formSerializer : undefined;
|
|
93
|
+
var envOption = utils.hasOwnProperty(this, 'env') ? this.env : undefined;
|
|
94
|
+
|
|
92
95
|
if (contentType.indexOf('application/x-www-form-urlencoded') !== -1) {
|
|
93
|
-
return toURLEncodedForm(data,
|
|
96
|
+
return toURLEncodedForm(data, formSerializer).toString();
|
|
94
97
|
}
|
|
95
98
|
|
|
96
99
|
if ((isFileList = utils.isFileList(data)) || contentType.indexOf('multipart/form-data') > -1) {
|
|
97
|
-
var _FormData =
|
|
100
|
+
var _FormData = envOption && envOption.FormData;
|
|
98
101
|
|
|
99
102
|
return toFormData(
|
|
100
103
|
isFileList ? {'files[]': data} : data,
|
|
101
104
|
_FormData && new _FormData(),
|
|
102
|
-
|
|
105
|
+
formSerializer
|
|
103
106
|
);
|
|
104
107
|
}
|
|
105
108
|
}
|
package/lib/env/data.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
module.exports = {
|
|
2
|
-
version: "0.
|
|
3
|
-
};
|
|
2
|
+
"version": "0.31.1"
|
|
3
|
+
};
|
|
@@ -3,16 +3,17 @@
|
|
|
3
3
|
var toFormData = require('./toFormData');
|
|
4
4
|
|
|
5
5
|
function encode(str) {
|
|
6
|
+
// Do not map `%00` back to a raw null byte (GHSA-xhjh-pmcv-23jw): that reversed
|
|
7
|
+
// the safe percent-encoding from encodeURIComponent and enabled null byte injection.
|
|
6
8
|
var charMap = {
|
|
7
9
|
'!': '%21',
|
|
8
10
|
"'": '%27',
|
|
9
11
|
'(': '%28',
|
|
10
12
|
')': '%29',
|
|
11
13
|
'~': '%7E',
|
|
12
|
-
'%20': '+'
|
|
13
|
-
'%00': '\x00'
|
|
14
|
+
'%20': '+'
|
|
14
15
|
};
|
|
15
|
-
return encodeURIComponent(str).replace(/[!'\(\)~]|%20
|
|
16
|
+
return encodeURIComponent(str).replace(/[!'\(\)~]|%20/g, function replacer(match) {
|
|
16
17
|
return charMap[match];
|
|
17
18
|
});
|
|
18
19
|
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var utils = require('../utils');
|
|
4
|
+
|
|
5
|
+
var INVALID_HEADER_VALUE_RE = /[^\x09\x20-\x7E\x80-\xFF]/g;
|
|
6
|
+
var BOUNDARY_WHITESPACE_RE = /^[\x09\x20]+|[\x09\x20]+$/g;
|
|
7
|
+
|
|
8
|
+
function sanitizeHeaderValue(value) {
|
|
9
|
+
if (value === false || value == null) {
|
|
10
|
+
return value;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
if (utils.isArray(value)) {
|
|
14
|
+
return value.map(sanitizeHeaderValue);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return String(value)
|
|
18
|
+
.replace(INVALID_HEADER_VALUE_RE, '')
|
|
19
|
+
.replace(BOUNDARY_WHITESPACE_RE, '');
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
module.exports = sanitizeHeaderValue;
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var URL = require('url').URL;
|
|
4
|
+
|
|
5
|
+
var DEFAULT_PORTS = {
|
|
6
|
+
http: 80,
|
|
7
|
+
https: 443,
|
|
8
|
+
ws: 80,
|
|
9
|
+
wss: 443,
|
|
10
|
+
ftp: 21
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
function parseNoProxyEntry(entry) {
|
|
14
|
+
var entryHost = entry;
|
|
15
|
+
var entryPort = 0;
|
|
16
|
+
|
|
17
|
+
if (entryHost.charAt(0) === '[') {
|
|
18
|
+
var bracketIndex = entryHost.indexOf(']');
|
|
19
|
+
|
|
20
|
+
if (bracketIndex !== -1) {
|
|
21
|
+
var host = entryHost.slice(1, bracketIndex);
|
|
22
|
+
var rest = entryHost.slice(bracketIndex + 1);
|
|
23
|
+
|
|
24
|
+
if (rest.charAt(0) === ':' && /^\d+$/.test(rest.slice(1))) {
|
|
25
|
+
entryPort = parseInt(rest.slice(1), 10);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return [host, entryPort];
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
var firstColon = entryHost.indexOf(':');
|
|
33
|
+
var lastColon = entryHost.lastIndexOf(':');
|
|
34
|
+
|
|
35
|
+
if (firstColon !== -1 && firstColon === lastColon && /^\d+$/.test(entryHost.slice(lastColon + 1))) {
|
|
36
|
+
entryPort = parseInt(entryHost.slice(lastColon + 1), 10);
|
|
37
|
+
entryHost = entryHost.slice(0, lastColon);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return [entryHost, entryPort];
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function normalizeNoProxyHost(hostname) {
|
|
44
|
+
if (!hostname) {
|
|
45
|
+
return hostname;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (hostname.charAt(0) === '[' && hostname.charAt(hostname.length - 1) === ']') {
|
|
49
|
+
hostname = hostname.slice(1, -1);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return hostname.replace(/\.+$/, '');
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function isLoopbackIPv4(hostname) {
|
|
56
|
+
var octets = hostname.split('.');
|
|
57
|
+
|
|
58
|
+
if (octets.length !== 4) {
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (octets[0] !== '127') {
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return octets.every(function testOctet(octet) {
|
|
67
|
+
return /^\d+$/.test(octet) && Number(octet) >= 0 && Number(octet) <= 255;
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function isLoopbackHost(hostname) {
|
|
72
|
+
return hostname === 'localhost' || hostname === '::1' || isLoopbackIPv4(hostname);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
module.exports = function shouldBypassProxy(location) {
|
|
76
|
+
var parsed;
|
|
77
|
+
|
|
78
|
+
try {
|
|
79
|
+
parsed = new URL(location);
|
|
80
|
+
} catch (err) {
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
var noProxy = (process.env.no_proxy || process.env.NO_PROXY || '').toLowerCase();
|
|
85
|
+
|
|
86
|
+
if (!noProxy) {
|
|
87
|
+
return false;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if (noProxy === '*') {
|
|
91
|
+
return true;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
var protocol = parsed.protocol.split(':', 1)[0];
|
|
95
|
+
var port = parsed.port !== '' ? parseInt(parsed.port, 10) : (DEFAULT_PORTS[protocol] || 0);
|
|
96
|
+
var hostname = normalizeNoProxyHost(parsed.hostname.toLowerCase());
|
|
97
|
+
|
|
98
|
+
return noProxy.split(/[\s,]+/).some(function testNoProxyEntry(entry) {
|
|
99
|
+
if (!entry) {
|
|
100
|
+
return false;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
var entryParts = parseNoProxyEntry(entry);
|
|
104
|
+
var entryHost = normalizeNoProxyHost(entryParts[0]);
|
|
105
|
+
var entryPort = entryParts[1];
|
|
106
|
+
|
|
107
|
+
if (entryHost === '*') {
|
|
108
|
+
return true;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (!entryHost) {
|
|
112
|
+
return false;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if (entryPort && entryPort !== port) {
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
if (isLoopbackHost(hostname) && isLoopbackHost(entryHost)) {
|
|
120
|
+
return true;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
if (entryHost.charAt(0) === '*') {
|
|
124
|
+
entryHost = entryHost.slice(1);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (entryHost.charAt(0) === '.') {
|
|
128
|
+
return hostname.slice(-entryHost.length) === entryHost;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
return hostname === entryHost;
|
|
132
|
+
});
|
|
133
|
+
};
|
|
@@ -69,6 +69,7 @@ function toFormData(obj, formData, options) {
|
|
|
69
69
|
var dots = options.dots;
|
|
70
70
|
var indexes = options.indexes;
|
|
71
71
|
var _Blob = options.Blob || typeof Blob !== 'undefined' && Blob;
|
|
72
|
+
var maxDepth = options.maxDepth === undefined ? 100 : options.maxDepth;
|
|
72
73
|
var useBlob = _Blob && isSpecCompliant(formData);
|
|
73
74
|
|
|
74
75
|
if (!utils.isFunction(visitor)) {
|
|
@@ -145,9 +146,19 @@ function toFormData(obj, formData, options) {
|
|
|
145
146
|
isVisitable: isVisitable
|
|
146
147
|
});
|
|
147
148
|
|
|
148
|
-
function build(value, path) {
|
|
149
|
+
function build(value, path, depth) {
|
|
149
150
|
if (utils.isUndefined(value)) return;
|
|
150
151
|
|
|
152
|
+
// eslint-disable-next-line no-param-reassign
|
|
153
|
+
depth = depth || 0;
|
|
154
|
+
|
|
155
|
+
if (depth > maxDepth) {
|
|
156
|
+
throw new AxiosError(
|
|
157
|
+
'Maximum object depth of ' + maxDepth + ' exceeded (got ' + depth + ' levels)',
|
|
158
|
+
AxiosError.ERR_FORM_DATA_DEPTH_EXCEEDED
|
|
159
|
+
);
|
|
160
|
+
}
|
|
161
|
+
|
|
151
162
|
if (stack.indexOf(value) !== -1) {
|
|
152
163
|
throw Error('Circular reference detected in ' + path.join('.'));
|
|
153
164
|
}
|
|
@@ -160,7 +171,7 @@ function toFormData(obj, formData, options) {
|
|
|
160
171
|
);
|
|
161
172
|
|
|
162
173
|
if (result === true) {
|
|
163
|
-
build(el, path ? path.concat(key) : [key]);
|
|
174
|
+
build(el, path ? path.concat(key) : [key], depth + 1);
|
|
164
175
|
}
|
|
165
176
|
});
|
|
166
177
|
|
|
@@ -171,7 +182,7 @@ function toFormData(obj, formData, options) {
|
|
|
171
182
|
throw new TypeError('data must be an object');
|
|
172
183
|
}
|
|
173
184
|
|
|
174
|
-
build(obj);
|
|
185
|
+
build(obj, null, 0);
|
|
175
186
|
|
|
176
187
|
return formData;
|
|
177
188
|
}
|
package/lib/utils.js
CHANGED
|
@@ -131,7 +131,15 @@ function isPlainObject(val) {
|
|
|
131
131
|
* @return {boolean} True if value is a empty Object, otherwise false
|
|
132
132
|
*/
|
|
133
133
|
function isEmptyObject(val) {
|
|
134
|
-
|
|
134
|
+
if (!isPlainObject(val)) {
|
|
135
|
+
return false;
|
|
136
|
+
}
|
|
137
|
+
for (var key in val) {
|
|
138
|
+
if (Object.prototype.hasOwnProperty.call(val, key)) {
|
|
139
|
+
return false;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return true;
|
|
135
143
|
}
|
|
136
144
|
|
|
137
145
|
/**
|
|
@@ -198,11 +206,17 @@ function isStream(val) {
|
|
|
198
206
|
*/
|
|
199
207
|
function isFormData(thing) {
|
|
200
208
|
var pattern = '[object FormData]';
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
);
|
|
209
|
+
if (!thing) return false;
|
|
210
|
+
if (typeof FormData === 'function' && thing instanceof FormData) return true;
|
|
211
|
+
// Reject non-objects (strings, numbers, booleans) up front — Object.getPrototypeOf
|
|
212
|
+
// throws a TypeError on primitives in ES5 environments.
|
|
213
|
+
if (!isObject(thing)) return false;
|
|
214
|
+
// Reject plain objects inheriting directly from Object.prototype so prototype-pollution gadgets can't spoof FormData (GHSA-6chq-wfr3-2hj9).
|
|
215
|
+
var proto = Object.getPrototypeOf(thing);
|
|
216
|
+
if (!proto || proto === Object.prototype) return false;
|
|
217
|
+
if (!isFunction(thing.append)) return false;
|
|
218
|
+
return toString.call(thing) === pattern ||
|
|
219
|
+
(isFunction(thing.toString) && thing.toString() === pattern);
|
|
206
220
|
}
|
|
207
221
|
|
|
208
222
|
/**
|