axios 0.31.1 → 0.33.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.
@@ -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 (GHSA-xx6v-rp6x-q39c): only honor own properties.
22
- var withXSRFToken = utils.hasOwnProperty(config, 'withXSRFToken') ? config.withXSRFToken : undefined;
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) {
@@ -38,15 +40,30 @@ module.exports = function xhrAdapter(config) {
38
40
  var request = new XMLHttpRequest();
39
41
 
40
42
  // HTTP basic authentication
41
- if (config.auth) {
42
- var username = config.auth.username || '';
43
- var password = config.auth.password ? unescape(encodeURIComponent(config.auth.password)) : '';
43
+ var configAuth = utils.hasOwnProperty(config, 'auth') ? config.auth : undefined;
44
+ if (configAuth) {
45
+ var username = utils.hasOwnProperty(configAuth, 'username') ? configAuth.username || '' : '';
46
+ var password = utils.hasOwnProperty(configAuth, 'password') && configAuth.password
47
+ ? unescape(encodeURIComponent(configAuth.password))
48
+ : '';
44
49
  requestHeaders.Authorization = 'Basic ' + btoa(username + ':' + password);
45
50
  }
46
51
 
47
- var fullPath = buildFullPath(config.baseURL, config.url, config.allowAbsoluteUrls);
48
-
49
- request.open(config.method.toUpperCase(), buildURL(fullPath, config.params, config.paramsSerializer), true);
52
+ var fullPath = buildFullPath(
53
+ config.baseURL,
54
+ config.url,
55
+ config.allowAbsoluteUrls
56
+ );
57
+
58
+ request.open(
59
+ config.method.toUpperCase(),
60
+ buildURL(
61
+ fullPath,
62
+ config.params,
63
+ utils.hasOwnProperty(config, 'paramsSerializer') ? config.paramsSerializer : undefined
64
+ ),
65
+ true
66
+ );
50
67
 
51
68
  // Set the request timeout in MS
52
69
  request.timeout = config.timeout;
@@ -56,9 +73,14 @@ module.exports = function xhrAdapter(config) {
56
73
  return;
57
74
  }
58
75
  // Prepare the response
59
- var responseHeaders = 'getAllResponseHeaders' in request ? parseHeaders(request.getAllResponseHeaders()) : null;
60
- var responseData = !responseType || responseType === 'text' || responseType === 'json' ?
61
- request.responseText : request.response;
76
+ var responseHeaders =
77
+ 'getAllResponseHeaders' in request
78
+ ? parseHeaders(request.getAllResponseHeaders())
79
+ : null;
80
+ var responseData =
81
+ !responseType || responseType === 'text' || responseType === 'json'
82
+ ? request.responseText
83
+ : request.response;
62
84
  var response = {
63
85
  data: responseData,
64
86
  status: request.status,
@@ -68,13 +90,17 @@ module.exports = function xhrAdapter(config) {
68
90
  request: request
69
91
  };
70
92
 
71
- settle(function _resolve(value) {
72
- resolve(value);
73
- done();
74
- }, function _reject(err) {
75
- reject(err);
76
- done();
77
- }, response);
93
+ settle(
94
+ function _resolve(value) {
95
+ resolve(value);
96
+ done();
97
+ },
98
+ function _reject(err) {
99
+ reject(err);
100
+ done();
101
+ },
102
+ response
103
+ );
78
104
 
79
105
  // Clean up request
80
106
  request = null;
@@ -94,7 +120,10 @@ module.exports = function xhrAdapter(config) {
94
120
  // handled by onerror instead
95
121
  // With one exception: request that using file: protocol, most browsers
96
122
  // will return status as 0 even though it's a successful request
97
- if (request.status === 0 && !(request.responseURL && request.responseURL.indexOf('file:') === 0)) {
123
+ if (
124
+ request.status === 0 &&
125
+ !(request.responseURL && request.responseURL.indexOf('file:') === 0)
126
+ ) {
98
127
  return;
99
128
  }
100
129
  // readystate handler is calling before onerror or ontimeout handlers,
@@ -109,7 +138,14 @@ module.exports = function xhrAdapter(config) {
109
138
  return;
110
139
  }
111
140
 
112
- reject(new AxiosError('Request aborted', AxiosError.ECONNABORTED, config, request));
141
+ reject(
142
+ new AxiosError(
143
+ 'Request aborted',
144
+ AxiosError.ECONNABORTED,
145
+ config,
146
+ request
147
+ )
148
+ );
113
149
 
114
150
  // Clean up request
115
151
  request = null;
@@ -119,7 +155,14 @@ module.exports = function xhrAdapter(config) {
119
155
  request.onerror = function handleError() {
120
156
  // Real errors are hidden from us by the browser
121
157
  // onerror should only fire if it's a network error
122
- reject(new AxiosError('Network Error', AxiosError.ERR_NETWORK, config, request));
158
+ reject(
159
+ new AxiosError(
160
+ 'Network Error',
161
+ AxiosError.ERR_NETWORK,
162
+ config,
163
+ request
164
+ )
165
+ );
123
166
 
124
167
  // Clean up request
125
168
  request = null;
@@ -127,16 +170,23 @@ module.exports = function xhrAdapter(config) {
127
170
 
128
171
  // Handle timeout
129
172
  request.ontimeout = function handleTimeout() {
130
- var timeoutErrorMessage = config.timeout ? 'timeout of ' + config.timeout + 'ms exceeded' : 'timeout exceeded';
173
+ var timeoutErrorMessage = config.timeout
174
+ ? 'timeout of ' + config.timeout + 'ms exceeded'
175
+ : 'timeout exceeded';
131
176
  var transitional = config.transitional || transitionalDefaults;
132
177
  if (config.timeoutErrorMessage) {
133
178
  timeoutErrorMessage = config.timeoutErrorMessage;
134
179
  }
135
- reject(new AxiosError(
136
- timeoutErrorMessage,
137
- transitional.clarifyTimeoutError ? AxiosError.ETIMEDOUT : AxiosError.ECONNABORTED,
138
- config,
139
- request));
180
+ reject(
181
+ new AxiosError(
182
+ timeoutErrorMessage,
183
+ transitional.clarifyTimeoutError
184
+ ? AxiosError.ETIMEDOUT
185
+ : AxiosError.ECONNABORTED,
186
+ config,
187
+ request
188
+ )
189
+ );
140
190
 
141
191
  // Clean up request
142
192
  request = null;
@@ -150,10 +200,16 @@ module.exports = function xhrAdapter(config) {
150
200
  if (utils.isFunction(withXSRFToken)) {
151
201
  withXSRFToken = withXSRFToken(config);
152
202
  }
153
- // Strict boolean check (GHSA-xx6v-rp6x-q39c): only `true` short-circuits the same-origin guard.
154
- if (withXSRFToken === true || (withXSRFToken !== false && isURLSameOrigin(fullPath))) {
203
+ // Strict boolean check: only `true` short-circuits the same-origin guard.
204
+ if (
205
+ withXSRFToken === true ||
206
+ (withXSRFToken !== false && isURLSameOrigin(fullPath))
207
+ ) {
155
208
  // Add xsrf header
156
- var xsrfValue = config.xsrfHeaderName && config.xsrfCookieName && cookies.read(config.xsrfCookieName);
209
+ var xsrfValue =
210
+ config.xsrfHeaderName &&
211
+ config.xsrfCookieName &&
212
+ cookies.read(config.xsrfCookieName);
157
213
  if (xsrfValue) {
158
214
  requestHeaders[config.xsrfHeaderName] = xsrfValue;
159
215
  }
@@ -163,7 +219,10 @@ module.exports = function xhrAdapter(config) {
163
219
  // Add headers to the request
164
220
  if ('setRequestHeader' in request) {
165
221
  utils.forEach(requestHeaders, function setRequestHeader(val, key) {
166
- if (typeof requestData === 'undefined' && key.toLowerCase() === 'content-type') {
222
+ if (
223
+ typeof requestData === 'undefined' &&
224
+ key.toLowerCase() === 'content-type'
225
+ ) {
167
226
  // Remove Content-Type if data is undefined
168
227
  delete requestHeaders[key];
169
228
  } else {
@@ -200,30 +259,46 @@ module.exports = function xhrAdapter(config) {
200
259
  if (!request) {
201
260
  return;
202
261
  }
203
- reject(!cancel || cancel.type ? new CanceledError(null, config, request) : cancel);
262
+ reject(
263
+ !cancel || cancel.type
264
+ ? new CanceledError(null, config, request)
265
+ : cancel
266
+ );
204
267
  request.abort();
205
268
  request = null;
206
269
  };
207
270
 
208
271
  config.cancelToken && config.cancelToken.subscribe(onCanceled);
209
272
  if (config.signal) {
210
- config.signal.aborted ? onCanceled() : config.signal.addEventListener('abort', onCanceled);
273
+ config.signal.aborted
274
+ ? onCanceled()
275
+ : config.signal.addEventListener('abort', onCanceled);
211
276
  }
212
277
  }
213
278
 
214
279
  // false, 0 (zero number), and '' (empty string) are valid JSON values
215
- if (!requestData && requestData !== false && requestData !== 0 && requestData !== '') {
280
+ if (
281
+ !requestData &&
282
+ requestData !== false &&
283
+ requestData !== 0 &&
284
+ requestData !== ''
285
+ ) {
216
286
  requestData = null;
217
287
  }
218
288
 
219
289
  var protocol = parseProtocol(fullPath);
220
290
 
221
291
  if (protocol && platform.protocols.indexOf(protocol) === -1) {
222
- reject(new AxiosError('Unsupported protocol ' + protocol + ':', AxiosError.ERR_BAD_REQUEST, config));
292
+ reject(
293
+ new AxiosError(
294
+ 'Unsupported protocol ' + protocol + ':',
295
+ AxiosError.ERR_BAD_REQUEST,
296
+ config
297
+ )
298
+ );
223
299
  return;
224
300
  }
225
301
 
226
-
227
302
  // Send the request
228
303
  request.send(requestData);
229
304
  });
package/lib/core/Axios.js CHANGED
@@ -144,10 +144,12 @@ Axios.prototype.getUri = function getUri(config) {
144
144
  utils.forEach(['delete', 'get', 'head', 'options'], function forEachMethodNoData(method) {
145
145
  /*eslint func-names:0*/
146
146
  Axios.prototype[method] = function(url, config) {
147
- return this.request(mergeConfig(config || {}, {
147
+ var requestConfig = config || {};
148
+
149
+ return this.request(mergeConfig(requestConfig, {
148
150
  method: method,
149
151
  url: url,
150
- data: (config || {}).data
152
+ data: utils.hasOwnProperty(requestConfig, 'data') ? requestConfig.data : undefined
151
153
  }));
152
154
  };
153
155
  });
@@ -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] = {value: code};
148
+ descriptors[code] = makeValueDescriptor(code);
74
149
  });
75
150
 
76
151
  Object.defineProperties(AxiosError, descriptors);
77
- Object.defineProperty(prototype, 'isAxiosError', {value: true});
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 = utils.merge(
50
- config.headers.common || {},
51
- config.headers[config.method] || {},
52
- config.headers
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'],
@@ -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
  };
@@ -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
@@ -1,3 +1,3 @@
1
1
  module.exports = {
2
- "version": "0.31.1"
2
+ "version": "0.33.0"
3
3
  };
@@ -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 (GHSA-xhjh-pmcv-23jw): that reversed
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(/[!'\(\)~]|%20/g, function replacer(match) {
17
- return charMap[match];
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 ? function(value) {
35
- return encoder.call(this, value, encode);
36
- } : encode;
37
-
38
- return this._pairs.map(function each(pair) {
39
- return _encode(pair[0]) + '=' + _encode(pair[1]);
40
- }, '').join('&');
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;
@@ -33,9 +33,17 @@ module.exports = function buildURL(url, params, options) {
33
33
  url = url.slice(0, hashmarkIndex);
34
34
  }
35
35
 
36
- var _encode = options && options.encode || encode;
37
-
38
- var serializeFn = options && options.serialize;
36
+ var _encode = encode;
37
+ var serializeFn;
38
+
39
+ if (options) {
40
+ if (utils.isFunction(options)) {
41
+ serializeFn = options;
42
+ } else {
43
+ _encode = utils.hasOwnProperty(options, 'encode') && options.encode || encode;
44
+ serializeFn = utils.hasOwnProperty(options, 'serialize') ? options.serialize : undefined;
45
+ }
46
+ }
39
47
 
40
48
  var serializedParams;
41
49
 
@@ -32,8 +32,21 @@ module.exports = (
32
32
  },
33
33
 
34
34
  read: function read(name) {
35
- var match = document.cookie.match(new RegExp('(^|;\\s*)(' + name + ')=([^;]*)'));
36
- return (match ? decodeURIComponent(match[3]) : null);
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) {
@@ -0,0 +1,3 @@
1
+ 'use strict';
2
+
3
+ module.exports = ['authorization', 'proxy-authorization', 'cookie', 'set-cookie', 'x-api-key', 'password'];
@@ -1,6 +1,20 @@
1
1
  'use strict';
2
2
 
3
3
  var utils = require('../utils');
4
+ var AxiosError = require('../core/AxiosError');
5
+
6
+ var MAX_FORM_DATA_TO_JSON_DEPTH = 100;
7
+
8
+ function assertPathDepth(path) {
9
+ var depth = path.length - 1;
10
+
11
+ if (depth > MAX_FORM_DATA_TO_JSON_DEPTH) {
12
+ throw new AxiosError(
13
+ 'Maximum object depth of ' + MAX_FORM_DATA_TO_JSON_DEPTH + ' exceeded (got ' + depth + ' levels)',
14
+ AxiosError.ERR_FORM_DATA_DEPTH_EXCEEDED
15
+ );
16
+ }
17
+ }
4
18
 
5
19
  function parsePropPath(name) {
6
20
  // foo[x][y][z]
@@ -62,7 +76,10 @@ function formDataToJSON(formData) {
62
76
  var obj = {};
63
77
 
64
78
  utils.forEachEntry(formData, function(name, value) {
65
- buildPath(parsePropPath(name), value, obj, 0);
79
+ var path = parsePropPath(name);
80
+
81
+ assertPathDepth(path);
82
+ buildPath(path, value, obj, 0);
66
83
  });
67
84
 
68
85
  return obj;
@@ -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
- return hostname.replace(/\.+$/, '');
104
+ hostname = hostname.replace(/\.+$/, '');
105
+
106
+ return normalizeIPv4MappedIPv6(hostname);
53
107
  }
54
108
 
55
109
  function isLoopbackIPv4(hostname) {
@@ -69,7 +123,7 @@ function isLoopbackIPv4(hostname) {
69
123
  }
70
124
 
71
125
  function isLoopbackHost(hostname) {
72
- return hostname === 'localhost' || hostname === '::1' || isLoopbackIPv4(hostname);
126
+ return hostname === 'localhost' || hostname === '::1' || hostname === '0.0.0.0' || isLoopbackIPv4(hostname);
73
127
  }
74
128
 
75
129
  module.exports = function shouldBypassProxy(location) {