axios 0.31.1 → 0.32.0
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/AGENTS.md +38 -0
- package/CHANGELOG.md +10 -0
- package/CLAUDE.md +1 -0
- package/README.md +24 -4
- package/dist/axios.js +276 -77
- 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 +276 -77
- 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 -0
- package/lib/adapters/http.js +291 -82
- package/lib/adapters/xhr.js +103 -33
- package/lib/core/AxiosError.js +79 -4
- package/lib/core/dispatchRequest.js +10 -5
- package/lib/core/mergeConfig.js +1 -0
- package/lib/defaults/index.js +3 -0
- package/lib/env/data.js +1 -1
- package/lib/helpers/AxiosURLSearchParams.js +18 -11
- package/lib/helpers/cookies.js +15 -2
- package/lib/helpers/defaultRedactKeys.js +3 -0
- package/lib/helpers/shouldBypassProxy.js +55 -1
- package/lib/utils.js +46 -21
- package/package.json +1 -1
package/lib/adapters/xhr.js
CHANGED
|
@@ -18,8 +18,10 @@ module.exports = function xhrAdapter(config) {
|
|
|
18
18
|
var requestData = config.data;
|
|
19
19
|
var requestHeaders = config.headers;
|
|
20
20
|
var responseType = config.responseType;
|
|
21
|
-
// Guard against prototype pollution
|
|
22
|
-
var withXSRFToken = utils.hasOwnProperty(config, 'withXSRFToken')
|
|
21
|
+
// Guard against prototype pollution: only honor own properties.
|
|
22
|
+
var withXSRFToken = utils.hasOwnProperty(config, 'withXSRFToken')
|
|
23
|
+
? config.withXSRFToken
|
|
24
|
+
: undefined;
|
|
23
25
|
var onCanceled;
|
|
24
26
|
function done() {
|
|
25
27
|
if (config.cancelToken) {
|
|
@@ -40,13 +42,23 @@ module.exports = function xhrAdapter(config) {
|
|
|
40
42
|
// HTTP basic authentication
|
|
41
43
|
if (config.auth) {
|
|
42
44
|
var username = config.auth.username || '';
|
|
43
|
-
var password = config.auth.password
|
|
45
|
+
var password = config.auth.password
|
|
46
|
+
? unescape(encodeURIComponent(config.auth.password))
|
|
47
|
+
: '';
|
|
44
48
|
requestHeaders.Authorization = 'Basic ' + btoa(username + ':' + password);
|
|
45
49
|
}
|
|
46
50
|
|
|
47
|
-
var fullPath = buildFullPath(
|
|
51
|
+
var fullPath = buildFullPath(
|
|
52
|
+
config.baseURL,
|
|
53
|
+
config.url,
|
|
54
|
+
config.allowAbsoluteUrls
|
|
55
|
+
);
|
|
48
56
|
|
|
49
|
-
request.open(
|
|
57
|
+
request.open(
|
|
58
|
+
config.method.toUpperCase(),
|
|
59
|
+
buildURL(fullPath, config.params, config.paramsSerializer),
|
|
60
|
+
true
|
|
61
|
+
);
|
|
50
62
|
|
|
51
63
|
// Set the request timeout in MS
|
|
52
64
|
request.timeout = config.timeout;
|
|
@@ -56,9 +68,14 @@ module.exports = function xhrAdapter(config) {
|
|
|
56
68
|
return;
|
|
57
69
|
}
|
|
58
70
|
// Prepare the response
|
|
59
|
-
var responseHeaders =
|
|
60
|
-
|
|
61
|
-
|
|
71
|
+
var responseHeaders =
|
|
72
|
+
'getAllResponseHeaders' in request
|
|
73
|
+
? parseHeaders(request.getAllResponseHeaders())
|
|
74
|
+
: null;
|
|
75
|
+
var responseData =
|
|
76
|
+
!responseType || responseType === 'text' || responseType === 'json'
|
|
77
|
+
? request.responseText
|
|
78
|
+
: request.response;
|
|
62
79
|
var response = {
|
|
63
80
|
data: responseData,
|
|
64
81
|
status: request.status,
|
|
@@ -68,13 +85,17 @@ module.exports = function xhrAdapter(config) {
|
|
|
68
85
|
request: request
|
|
69
86
|
};
|
|
70
87
|
|
|
71
|
-
settle(
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
88
|
+
settle(
|
|
89
|
+
function _resolve(value) {
|
|
90
|
+
resolve(value);
|
|
91
|
+
done();
|
|
92
|
+
},
|
|
93
|
+
function _reject(err) {
|
|
94
|
+
reject(err);
|
|
95
|
+
done();
|
|
96
|
+
},
|
|
97
|
+
response
|
|
98
|
+
);
|
|
78
99
|
|
|
79
100
|
// Clean up request
|
|
80
101
|
request = null;
|
|
@@ -94,7 +115,10 @@ module.exports = function xhrAdapter(config) {
|
|
|
94
115
|
// handled by onerror instead
|
|
95
116
|
// With one exception: request that using file: protocol, most browsers
|
|
96
117
|
// will return status as 0 even though it's a successful request
|
|
97
|
-
if (
|
|
118
|
+
if (
|
|
119
|
+
request.status === 0 &&
|
|
120
|
+
!(request.responseURL && request.responseURL.indexOf('file:') === 0)
|
|
121
|
+
) {
|
|
98
122
|
return;
|
|
99
123
|
}
|
|
100
124
|
// readystate handler is calling before onerror or ontimeout handlers,
|
|
@@ -109,7 +133,14 @@ module.exports = function xhrAdapter(config) {
|
|
|
109
133
|
return;
|
|
110
134
|
}
|
|
111
135
|
|
|
112
|
-
reject(
|
|
136
|
+
reject(
|
|
137
|
+
new AxiosError(
|
|
138
|
+
'Request aborted',
|
|
139
|
+
AxiosError.ECONNABORTED,
|
|
140
|
+
config,
|
|
141
|
+
request
|
|
142
|
+
)
|
|
143
|
+
);
|
|
113
144
|
|
|
114
145
|
// Clean up request
|
|
115
146
|
request = null;
|
|
@@ -119,7 +150,14 @@ module.exports = function xhrAdapter(config) {
|
|
|
119
150
|
request.onerror = function handleError() {
|
|
120
151
|
// Real errors are hidden from us by the browser
|
|
121
152
|
// onerror should only fire if it's a network error
|
|
122
|
-
reject(
|
|
153
|
+
reject(
|
|
154
|
+
new AxiosError(
|
|
155
|
+
'Network Error',
|
|
156
|
+
AxiosError.ERR_NETWORK,
|
|
157
|
+
config,
|
|
158
|
+
request
|
|
159
|
+
)
|
|
160
|
+
);
|
|
123
161
|
|
|
124
162
|
// Clean up request
|
|
125
163
|
request = null;
|
|
@@ -127,16 +165,23 @@ module.exports = function xhrAdapter(config) {
|
|
|
127
165
|
|
|
128
166
|
// Handle timeout
|
|
129
167
|
request.ontimeout = function handleTimeout() {
|
|
130
|
-
var timeoutErrorMessage = config.timeout
|
|
168
|
+
var timeoutErrorMessage = config.timeout
|
|
169
|
+
? 'timeout of ' + config.timeout + 'ms exceeded'
|
|
170
|
+
: 'timeout exceeded';
|
|
131
171
|
var transitional = config.transitional || transitionalDefaults;
|
|
132
172
|
if (config.timeoutErrorMessage) {
|
|
133
173
|
timeoutErrorMessage = config.timeoutErrorMessage;
|
|
134
174
|
}
|
|
135
|
-
reject(
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
175
|
+
reject(
|
|
176
|
+
new AxiosError(
|
|
177
|
+
timeoutErrorMessage,
|
|
178
|
+
transitional.clarifyTimeoutError
|
|
179
|
+
? AxiosError.ETIMEDOUT
|
|
180
|
+
: AxiosError.ECONNABORTED,
|
|
181
|
+
config,
|
|
182
|
+
request
|
|
183
|
+
)
|
|
184
|
+
);
|
|
140
185
|
|
|
141
186
|
// Clean up request
|
|
142
187
|
request = null;
|
|
@@ -150,10 +195,16 @@ module.exports = function xhrAdapter(config) {
|
|
|
150
195
|
if (utils.isFunction(withXSRFToken)) {
|
|
151
196
|
withXSRFToken = withXSRFToken(config);
|
|
152
197
|
}
|
|
153
|
-
// Strict boolean check
|
|
154
|
-
if (
|
|
198
|
+
// Strict boolean check: only `true` short-circuits the same-origin guard.
|
|
199
|
+
if (
|
|
200
|
+
withXSRFToken === true ||
|
|
201
|
+
(withXSRFToken !== false && isURLSameOrigin(fullPath))
|
|
202
|
+
) {
|
|
155
203
|
// Add xsrf header
|
|
156
|
-
var xsrfValue =
|
|
204
|
+
var xsrfValue =
|
|
205
|
+
config.xsrfHeaderName &&
|
|
206
|
+
config.xsrfCookieName &&
|
|
207
|
+
cookies.read(config.xsrfCookieName);
|
|
157
208
|
if (xsrfValue) {
|
|
158
209
|
requestHeaders[config.xsrfHeaderName] = xsrfValue;
|
|
159
210
|
}
|
|
@@ -163,7 +214,10 @@ module.exports = function xhrAdapter(config) {
|
|
|
163
214
|
// Add headers to the request
|
|
164
215
|
if ('setRequestHeader' in request) {
|
|
165
216
|
utils.forEach(requestHeaders, function setRequestHeader(val, key) {
|
|
166
|
-
if (
|
|
217
|
+
if (
|
|
218
|
+
typeof requestData === 'undefined' &&
|
|
219
|
+
key.toLowerCase() === 'content-type'
|
|
220
|
+
) {
|
|
167
221
|
// Remove Content-Type if data is undefined
|
|
168
222
|
delete requestHeaders[key];
|
|
169
223
|
} else {
|
|
@@ -200,30 +254,46 @@ module.exports = function xhrAdapter(config) {
|
|
|
200
254
|
if (!request) {
|
|
201
255
|
return;
|
|
202
256
|
}
|
|
203
|
-
reject(
|
|
257
|
+
reject(
|
|
258
|
+
!cancel || cancel.type
|
|
259
|
+
? new CanceledError(null, config, request)
|
|
260
|
+
: cancel
|
|
261
|
+
);
|
|
204
262
|
request.abort();
|
|
205
263
|
request = null;
|
|
206
264
|
};
|
|
207
265
|
|
|
208
266
|
config.cancelToken && config.cancelToken.subscribe(onCanceled);
|
|
209
267
|
if (config.signal) {
|
|
210
|
-
config.signal.aborted
|
|
268
|
+
config.signal.aborted
|
|
269
|
+
? onCanceled()
|
|
270
|
+
: config.signal.addEventListener('abort', onCanceled);
|
|
211
271
|
}
|
|
212
272
|
}
|
|
213
273
|
|
|
214
274
|
// false, 0 (zero number), and '' (empty string) are valid JSON values
|
|
215
|
-
if (
|
|
275
|
+
if (
|
|
276
|
+
!requestData &&
|
|
277
|
+
requestData !== false &&
|
|
278
|
+
requestData !== 0 &&
|
|
279
|
+
requestData !== ''
|
|
280
|
+
) {
|
|
216
281
|
requestData = null;
|
|
217
282
|
}
|
|
218
283
|
|
|
219
284
|
var protocol = parseProtocol(fullPath);
|
|
220
285
|
|
|
221
286
|
if (protocol && platform.protocols.indexOf(protocol) === -1) {
|
|
222
|
-
reject(
|
|
287
|
+
reject(
|
|
288
|
+
new AxiosError(
|
|
289
|
+
'Unsupported protocol ' + protocol + ':',
|
|
290
|
+
AxiosError.ERR_BAD_REQUEST,
|
|
291
|
+
config
|
|
292
|
+
)
|
|
293
|
+
);
|
|
223
294
|
return;
|
|
224
295
|
}
|
|
225
296
|
|
|
226
|
-
|
|
227
297
|
// Send the request
|
|
228
298
|
request.send(requestData);
|
|
229
299
|
});
|
package/lib/core/AxiosError.js
CHANGED
|
@@ -1,6 +1,81 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var utils = require('../utils');
|
|
4
|
+
var DEFAULT_REDACT_KEYS = require('../helpers/defaultRedactKeys');
|
|
5
|
+
|
|
6
|
+
var REDACTED_VALUE = '[REDACTED ****]';
|
|
7
|
+
|
|
8
|
+
function makeValueDescriptor(value) {
|
|
9
|
+
var descriptor = Object.create(null);
|
|
10
|
+
descriptor.value = value;
|
|
11
|
+
return descriptor;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function getRedactKeys(config) {
|
|
15
|
+
// An empty array is treated as "no override" so an upstream `redact: []` cannot
|
|
16
|
+
// silently disable redaction. To opt out, pass non-string values or unset keys.
|
|
17
|
+
var override = config && utils.isArray(config.redact) && config.redact.length ? config.redact : null;
|
|
18
|
+
var redact = override || DEFAULT_REDACT_KEYS;
|
|
19
|
+
var keys = {};
|
|
20
|
+
|
|
21
|
+
utils.forEach(redact, function eachRedactKey(key) {
|
|
22
|
+
if (typeof key === 'string') {
|
|
23
|
+
keys[key.toLowerCase()] = true;
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
return keys;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function shouldRedact(key, keys) {
|
|
31
|
+
return typeof key === 'string' && keys[key.toLowerCase()];
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
var CIRCULAR_VALUE = '[Circular]';
|
|
35
|
+
|
|
36
|
+
function serializeConfigValue(value, keys, key, seen) {
|
|
37
|
+
var result;
|
|
38
|
+
|
|
39
|
+
if (shouldRedact(key, keys)) {
|
|
40
|
+
return REDACTED_VALUE;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (utils.isArray(value)) {
|
|
44
|
+
if (seen.indexOf(value) !== -1) {
|
|
45
|
+
return CIRCULAR_VALUE;
|
|
46
|
+
}
|
|
47
|
+
seen.push(value);
|
|
48
|
+
result = [];
|
|
49
|
+
utils.forEach(value, function eachArrayValue(item, index) {
|
|
50
|
+
result[index] = serializeConfigValue(item, keys, index, seen);
|
|
51
|
+
});
|
|
52
|
+
seen.pop();
|
|
53
|
+
return result;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (utils.isPlainObject(value)) {
|
|
57
|
+
if (seen.indexOf(value) !== -1) {
|
|
58
|
+
return CIRCULAR_VALUE;
|
|
59
|
+
}
|
|
60
|
+
seen.push(value);
|
|
61
|
+
result = {};
|
|
62
|
+
utils.forEach(value, function eachObjectValue(item, itemKey) {
|
|
63
|
+
result[itemKey] = serializeConfigValue(item, keys, itemKey, seen);
|
|
64
|
+
});
|
|
65
|
+
seen.pop();
|
|
66
|
+
return result;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return value;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function serializeConfig(config) {
|
|
73
|
+
if (!config) {
|
|
74
|
+
return config;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return serializeConfigValue(config, getRedactKeys(config), undefined, []);
|
|
78
|
+
}
|
|
4
79
|
|
|
5
80
|
/**
|
|
6
81
|
* Create an Error with the specified message, config, error code, request and response.
|
|
@@ -44,7 +119,7 @@ utils.inherits(AxiosError, Error, {
|
|
|
44
119
|
columnNumber: this.columnNumber,
|
|
45
120
|
stack: this.stack,
|
|
46
121
|
// Axios
|
|
47
|
-
config: this.config,
|
|
122
|
+
config: serializeConfig(this.config),
|
|
48
123
|
code: this.code,
|
|
49
124
|
status: this.response && this.response.status ? this.response.status : null
|
|
50
125
|
};
|
|
@@ -52,7 +127,7 @@ utils.inherits(AxiosError, Error, {
|
|
|
52
127
|
});
|
|
53
128
|
|
|
54
129
|
var prototype = AxiosError.prototype;
|
|
55
|
-
var descriptors =
|
|
130
|
+
var descriptors = Object.create(null);
|
|
56
131
|
|
|
57
132
|
[
|
|
58
133
|
'ERR_BAD_OPTION_VALUE',
|
|
@@ -70,11 +145,11 @@ var descriptors = {};
|
|
|
70
145
|
'ERR_FORM_DATA_DEPTH_EXCEEDED'
|
|
71
146
|
// eslint-disable-next-line func-names
|
|
72
147
|
].forEach(function(code) {
|
|
73
|
-
descriptors[code] =
|
|
148
|
+
descriptors[code] = makeValueDescriptor(code);
|
|
74
149
|
});
|
|
75
150
|
|
|
76
151
|
Object.defineProperties(AxiosError, descriptors);
|
|
77
|
-
Object.defineProperty(prototype, 'isAxiosError',
|
|
152
|
+
Object.defineProperty(prototype, 'isAxiosError', makeValueDescriptor(true));
|
|
78
153
|
|
|
79
154
|
// eslint-disable-next-line func-names
|
|
80
155
|
AxiosError.from = function(error, code, config, request, response, customProps) {
|
|
@@ -46,11 +46,16 @@ module.exports = function dispatchRequest(config) {
|
|
|
46
46
|
normalizeHeaderName(config.headers, 'Content-Type');
|
|
47
47
|
|
|
48
48
|
// Flatten headers
|
|
49
|
-
config.headers
|
|
50
|
-
config.headers.common
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
49
|
+
var commonHeaders = utils.hasOwnProperty(config.headers, 'common') && config.headers.common
|
|
50
|
+
? config.headers.common
|
|
51
|
+
: {};
|
|
52
|
+
var methodHeaders = config.method &&
|
|
53
|
+
utils.hasOwnProperty(config.headers, config.method) &&
|
|
54
|
+
config.headers[config.method]
|
|
55
|
+
? config.headers[config.method]
|
|
56
|
+
: {};
|
|
57
|
+
|
|
58
|
+
config.headers = utils.merge(commonHeaders, methodHeaders, config.headers);
|
|
54
59
|
|
|
55
60
|
utils.forEach(
|
|
56
61
|
['delete', 'get', 'head', 'post', 'put', 'patch', 'common'],
|
package/lib/core/mergeConfig.js
CHANGED
|
@@ -99,6 +99,7 @@ module.exports = function mergeConfig(config1, config2) {
|
|
|
99
99
|
'httpsAgent': defaultToConfig2,
|
|
100
100
|
'cancelToken': defaultToConfig2,
|
|
101
101
|
'socketPath': defaultToConfig2,
|
|
102
|
+
'allowedSocketPaths': defaultToConfig2,
|
|
102
103
|
'responseEncoding': defaultToConfig2,
|
|
103
104
|
'validateStatus': mergeDirectKeys
|
|
104
105
|
};
|
package/lib/defaults/index.js
CHANGED
|
@@ -8,6 +8,7 @@ var toFormData = require('../helpers/toFormData');
|
|
|
8
8
|
var toURLEncodedForm = require('../helpers/toURLEncodedForm');
|
|
9
9
|
var platform = require('../platform');
|
|
10
10
|
var formDataToJSON = require('../helpers/formDataToJSON');
|
|
11
|
+
var defaultRedactKeys = require('../helpers/defaultRedactKeys');
|
|
11
12
|
|
|
12
13
|
var DEFAULT_CONTENT_TYPE = {
|
|
13
14
|
'Content-Type': 'application/x-www-form-urlencoded'
|
|
@@ -151,6 +152,8 @@ var defaults = {
|
|
|
151
152
|
maxContentLength: -1,
|
|
152
153
|
maxBodyLength: -1,
|
|
153
154
|
|
|
155
|
+
redact: defaultRedactKeys.slice(),
|
|
156
|
+
|
|
154
157
|
env: {
|
|
155
158
|
FormData: platform.classes.FormData,
|
|
156
159
|
Blob: platform.classes.Blob
|
package/lib/env/data.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
var toFormData = require('./toFormData');
|
|
4
4
|
|
|
5
5
|
function encode(str) {
|
|
6
|
-
// Do not map `%00` back to a raw null byte
|
|
6
|
+
// Do not map `%00` back to a raw null byte: that reversed
|
|
7
7
|
// the safe percent-encoding from encodeURIComponent and enabled null byte injection.
|
|
8
8
|
var charMap = {
|
|
9
9
|
'!': '%21',
|
|
@@ -13,9 +13,12 @@ function encode(str) {
|
|
|
13
13
|
'~': '%7E',
|
|
14
14
|
'%20': '+'
|
|
15
15
|
};
|
|
16
|
-
return encodeURIComponent(str).replace(
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
return encodeURIComponent(str).replace(
|
|
17
|
+
/[!'\(\)~]|%20/g,
|
|
18
|
+
function replacer(match) {
|
|
19
|
+
return charMap[match];
|
|
20
|
+
}
|
|
21
|
+
);
|
|
19
22
|
}
|
|
20
23
|
|
|
21
24
|
function AxiosURLSearchParams(params, options) {
|
|
@@ -31,13 +34,17 @@ prototype.append = function append(name, value) {
|
|
|
31
34
|
};
|
|
32
35
|
|
|
33
36
|
prototype.toString = function toString(encoder) {
|
|
34
|
-
var _encode = encoder
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
37
|
+
var _encode = encoder
|
|
38
|
+
? function(value) {
|
|
39
|
+
return encoder.call(this, value, encode);
|
|
40
|
+
}
|
|
41
|
+
: encode;
|
|
42
|
+
|
|
43
|
+
return this._pairs
|
|
44
|
+
.map(function each(pair) {
|
|
45
|
+
return _encode(pair[0]) + '=' + _encode(pair[1]);
|
|
46
|
+
}, '')
|
|
47
|
+
.join('&');
|
|
41
48
|
};
|
|
42
49
|
|
|
43
50
|
module.exports = AxiosURLSearchParams;
|
package/lib/helpers/cookies.js
CHANGED
|
@@ -32,8 +32,21 @@ module.exports = (
|
|
|
32
32
|
},
|
|
33
33
|
|
|
34
34
|
read: function read(name) {
|
|
35
|
-
var
|
|
36
|
-
|
|
35
|
+
var nameEQ = name + '=';
|
|
36
|
+
var cookies = document.cookie.split(';');
|
|
37
|
+
var cookie;
|
|
38
|
+
|
|
39
|
+
for (var i = 0; i < cookies.length; i++) {
|
|
40
|
+
cookie = cookies[i];
|
|
41
|
+
while (cookie.charAt(0) === ' ') {
|
|
42
|
+
cookie = cookie.substring(1);
|
|
43
|
+
}
|
|
44
|
+
if (cookie.indexOf(nameEQ) === 0) {
|
|
45
|
+
return decodeURIComponent(cookie.substring(nameEQ.length));
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return null;
|
|
37
50
|
},
|
|
38
51
|
|
|
39
52
|
remove: function remove(name) {
|
|
@@ -40,6 +40,58 @@ function parseNoProxyEntry(entry) {
|
|
|
40
40
|
return [entryHost, entryPort];
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
+
function parseIPv4Octets(hostname) {
|
|
44
|
+
var octets = hostname.split('.');
|
|
45
|
+
|
|
46
|
+
if (octets.length !== 4) {
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
for (var i = 0; i < octets.length; i++) {
|
|
51
|
+
if (!/^\d+$/.test(octets[i]) || Number(octets[i]) > 255) {
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return octets;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Recognises the canonical IPv4-mapped IPv6 forms the Node URL parser produces:
|
|
60
|
+
// ::ffff:127.0.0.1 (dotted-quad tail)
|
|
61
|
+
// ::ffff:7f00:1 (compressed two-group hex tail)
|
|
62
|
+
// Fully-expanded forms like 0:0:0:0:0:ffff:7f00:1 or single-group tails like
|
|
63
|
+
// ::ffff:1 are not normalised here. URL inputs are canonicalised by the parser
|
|
64
|
+
// before reaching this helper, but hand-crafted no_proxy entries in those
|
|
65
|
+
// shapes will not match an IPv4 listing.
|
|
66
|
+
function normalizeIPv4MappedIPv6(hostname) {
|
|
67
|
+
// Match against the lowercased form so a hand-crafted no_proxy entry like
|
|
68
|
+
// `[::FFFF:7F00:1]` still resolves to its IPv4 alias. Callers that route via
|
|
69
|
+
// URL parsing already lowercase, but the helper stays robust on its own.
|
|
70
|
+
var lower = hostname.toLowerCase();
|
|
71
|
+
var dottedMatch = /^::ffff:(\d+\.\d+\.\d+\.\d+)$/.exec(lower);
|
|
72
|
+
|
|
73
|
+
if (dottedMatch) {
|
|
74
|
+
var octets = parseIPv4Octets(dottedMatch[1]);
|
|
75
|
+
return octets ? octets.join('.') : hostname;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
var hexMatch = /^::ffff:([0-9a-f]{1,4}):([0-9a-f]{1,4})$/.exec(lower);
|
|
79
|
+
|
|
80
|
+
if (hexMatch) {
|
|
81
|
+
var high = parseInt(hexMatch[1], 16);
|
|
82
|
+
var low = parseInt(hexMatch[2], 16);
|
|
83
|
+
|
|
84
|
+
return [
|
|
85
|
+
(high >> 8) & 0xff,
|
|
86
|
+
high & 0xff,
|
|
87
|
+
(low >> 8) & 0xff,
|
|
88
|
+
low & 0xff
|
|
89
|
+
].join('.');
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return hostname;
|
|
93
|
+
}
|
|
94
|
+
|
|
43
95
|
function normalizeNoProxyHost(hostname) {
|
|
44
96
|
if (!hostname) {
|
|
45
97
|
return hostname;
|
|
@@ -49,7 +101,9 @@ function normalizeNoProxyHost(hostname) {
|
|
|
49
101
|
hostname = hostname.slice(1, -1);
|
|
50
102
|
}
|
|
51
103
|
|
|
52
|
-
|
|
104
|
+
hostname = hostname.replace(/\.+$/, '');
|
|
105
|
+
|
|
106
|
+
return normalizeIPv4MappedIPv6(hostname);
|
|
53
107
|
}
|
|
54
108
|
|
|
55
109
|
function isLoopbackIPv4(hostname) {
|