axios 0.20.0 → 0.21.3

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.
@@ -16,6 +16,31 @@ var enhanceError = require('../core/enhanceError');
16
16
 
17
17
  var isHttps = /https:?/;
18
18
 
19
+ /**
20
+ *
21
+ * @param {http.ClientRequestArgs} options
22
+ * @param {AxiosProxyConfig} proxy
23
+ * @param {string} location
24
+ */
25
+ function setProxy(options, proxy, location) {
26
+ options.hostname = proxy.host;
27
+ options.host = proxy.host;
28
+ options.port = proxy.port;
29
+ options.path = location;
30
+
31
+ // Basic proxy authorization
32
+ if (proxy.auth) {
33
+ var base64 = Buffer.from(proxy.auth.username + ':' + proxy.auth.password, 'utf8').toString('base64');
34
+ options.headers['Proxy-Authorization'] = 'Basic ' + base64;
35
+ }
36
+
37
+ // If a proxy is used, any redirects must also pass through the proxy
38
+ options.beforeRedirect = function beforeRedirect(redirection) {
39
+ redirection.headers.host = redirection.host;
40
+ setProxy(redirection, proxy, redirection.href);
41
+ };
42
+ }
43
+
19
44
  /*eslint consistent-return:0*/
20
45
  module.exports = function httpAdapter(config) {
21
46
  return new Promise(function dispatchHttpRequest(resolvePromise, rejectPromise) {
@@ -29,9 +54,16 @@ module.exports = function httpAdapter(config) {
29
54
  var headers = config.headers;
30
55
 
31
56
  // Set User-Agent (required by some servers)
32
- // Only set header if it hasn't been set in config
33
57
  // See https://github.com/axios/axios/issues/69
34
- if (!headers['User-Agent'] && !headers['user-agent']) {
58
+ if ('User-Agent' in headers || 'user-agent' in headers) {
59
+ // User-Agent is specified; handle case where no UA header is desired
60
+ if (!headers['User-Agent'] && !headers['user-agent']) {
61
+ delete headers['User-Agent'];
62
+ delete headers['user-agent'];
63
+ }
64
+ // Otherwise, use specified value
65
+ } else {
66
+ // Only set header if it hasn't been set in config
35
67
  headers['User-Agent'] = 'axios/' + pkg.version;
36
68
  }
37
69
 
@@ -126,11 +158,11 @@ module.exports = function httpAdapter(config) {
126
158
  });
127
159
  }
128
160
 
129
-
130
161
  if (shouldProxy) {
131
162
  proxy = {
132
163
  host: parsedProxyUrl.hostname,
133
- port: parsedProxyUrl.port
164
+ port: parsedProxyUrl.port,
165
+ protocol: parsedProxyUrl.protocol
134
166
  };
135
167
 
136
168
  if (parsedProxyUrl.auth) {
@@ -145,17 +177,8 @@ module.exports = function httpAdapter(config) {
145
177
  }
146
178
 
147
179
  if (proxy) {
148
- options.hostname = proxy.host;
149
- options.host = proxy.host;
150
180
  options.headers.host = parsed.hostname + (parsed.port ? ':' + parsed.port : '');
151
- options.port = proxy.port;
152
- options.path = protocol + '//' + parsed.hostname + (parsed.port ? ':' + parsed.port : '') + options.path;
153
-
154
- // Basic proxy authorization
155
- if (proxy.auth) {
156
- var base64 = Buffer.from(proxy.auth.username + ':' + proxy.auth.password, 'utf8').toString('base64');
157
- options.headers['Proxy-Authorization'] = 'Basic ' + base64;
158
- }
181
+ setProxy(options, proxy, protocol + '//' + parsed.hostname + (parsed.port ? ':' + parsed.port : '') + options.path);
159
182
  }
160
183
 
161
184
  var transport;
@@ -215,11 +238,13 @@ module.exports = function httpAdapter(config) {
215
238
  settle(resolve, reject, response);
216
239
  } else {
217
240
  var responseBuffer = [];
241
+ var totalResponseBytes = 0;
218
242
  stream.on('data', function handleStreamData(chunk) {
219
243
  responseBuffer.push(chunk);
244
+ totalResponseBytes += chunk.length;
220
245
 
221
246
  // make sure the content length is not over the maxContentLength if specified
222
- if (config.maxContentLength > -1 && Buffer.concat(responseBuffer).length > config.maxContentLength) {
247
+ if (config.maxContentLength > -1 && totalResponseBytes > config.maxContentLength) {
223
248
  stream.destroy();
224
249
  reject(createError('maxContentLength size of ' + config.maxContentLength + ' exceeded',
225
250
  config, null, lastRequest));
@@ -254,14 +279,33 @@ module.exports = function httpAdapter(config) {
254
279
 
255
280
  // Handle request timeout
256
281
  if (config.timeout) {
282
+ // This is forcing a int timeout to avoid problems if the `req` interface doesn't handle other types.
283
+ var timeout = parseInt(config.timeout, 10);
284
+
285
+ if (isNaN(timeout)) {
286
+ reject(createError(
287
+ 'error trying to parse `config.timeout` to int',
288
+ config,
289
+ 'ERR_PARSE_TIMEOUT',
290
+ req
291
+ ));
292
+
293
+ return;
294
+ }
295
+
257
296
  // Sometime, the response will be very slow, and does not respond, the connect event will be block by event loop system.
258
297
  // And timer callback will be fired, and abort() will be invoked before connection, then get "socket hang up" and code ECONNRESET.
259
298
  // At this time, if we have a large number of request, nodejs will hang up some socket on background. and the number will up and up.
260
299
  // And then these socket which be hang up will devoring CPU little by little.
261
300
  // ClientRequest.setTimeout will be fired on the specify milliseconds, and can make sure that abort() will be fired after connect.
262
- req.setTimeout(config.timeout, function handleRequestTimeout() {
301
+ req.setTimeout(timeout, function handleRequestTimeout() {
263
302
  req.abort();
264
- reject(createError('timeout of ' + config.timeout + 'ms exceeded', config, 'ECONNABORTED', req));
303
+ reject(createError(
304
+ 'timeout of ' + timeout + 'ms exceeded',
305
+ config,
306
+ config.transitional && config.transitional.clarifyTimeoutError ? 'ETIMEDOUT' : 'ECONNABORTED',
307
+ req
308
+ ));
265
309
  });
266
310
  }
267
311
 
@@ -13,24 +13,18 @@ module.exports = function xhrAdapter(config) {
13
13
  return new Promise(function dispatchXhrRequest(resolve, reject) {
14
14
  var requestData = config.data;
15
15
  var requestHeaders = config.headers;
16
+ var responseType = config.responseType;
16
17
 
17
18
  if (utils.isFormData(requestData)) {
18
19
  delete requestHeaders['Content-Type']; // Let the browser set it
19
20
  }
20
21
 
21
- if (
22
- (utils.isBlob(requestData) || utils.isFile(requestData)) &&
23
- requestData.type
24
- ) {
25
- delete requestHeaders['Content-Type']; // Let the browser set it
26
- }
27
-
28
22
  var request = new XMLHttpRequest();
29
23
 
30
24
  // HTTP basic authentication
31
25
  if (config.auth) {
32
26
  var username = config.auth.username || '';
33
- var password = unescape(encodeURIComponent(config.auth.password)) || '';
27
+ var password = config.auth.password ? unescape(encodeURIComponent(config.auth.password)) : '';
34
28
  requestHeaders.Authorization = 'Basic ' + btoa(username + ':' + password);
35
29
  }
36
30
 
@@ -40,23 +34,14 @@ module.exports = function xhrAdapter(config) {
40
34
  // Set the request timeout in MS
41
35
  request.timeout = config.timeout;
42
36
 
43
- // Listen for ready state
44
- request.onreadystatechange = function handleLoad() {
45
- if (!request || request.readyState !== 4) {
46
- return;
47
- }
48
-
49
- // The request errored out and we didn't get a response, this will be
50
- // handled by onerror instead
51
- // With one exception: request that using file: protocol, most browsers
52
- // will return status as 0 even though it's a successful request
53
- if (request.status === 0 && !(request.responseURL && request.responseURL.indexOf('file:') === 0)) {
37
+ function onloadend() {
38
+ if (!request) {
54
39
  return;
55
40
  }
56
-
57
41
  // Prepare the response
58
42
  var responseHeaders = 'getAllResponseHeaders' in request ? parseHeaders(request.getAllResponseHeaders()) : null;
59
- var responseData = !config.responseType || config.responseType === 'text' ? request.responseText : request.response;
43
+ var responseData = !responseType || responseType === 'text' || responseType === 'json' ?
44
+ request.responseText : request.response;
60
45
  var response = {
61
46
  data: responseData,
62
47
  status: request.status,
@@ -70,7 +55,30 @@ module.exports = function xhrAdapter(config) {
70
55
 
71
56
  // Clean up request
72
57
  request = null;
73
- };
58
+ }
59
+
60
+ if ('onloadend' in request) {
61
+ // Use onloadend if available
62
+ request.onloadend = onloadend;
63
+ } else {
64
+ // Listen for ready state to emulate onloadend
65
+ request.onreadystatechange = function handleLoad() {
66
+ if (!request || request.readyState !== 4) {
67
+ return;
68
+ }
69
+
70
+ // The request errored out and we didn't get a response, this will be
71
+ // handled by onerror instead
72
+ // With one exception: request that using file: protocol, most browsers
73
+ // will return status as 0 even though it's a successful request
74
+ if (request.status === 0 && !(request.responseURL && request.responseURL.indexOf('file:') === 0)) {
75
+ return;
76
+ }
77
+ // readystate handler is calling before onerror or ontimeout handlers,
78
+ // so we should call onloadend on the next 'tick'
79
+ setTimeout(onloadend);
80
+ };
81
+ }
74
82
 
75
83
  // Handle browser request cancellation (as opposed to a manual cancellation)
76
84
  request.onabort = function handleAbort() {
@@ -100,7 +108,10 @@ module.exports = function xhrAdapter(config) {
100
108
  if (config.timeoutErrorMessage) {
101
109
  timeoutErrorMessage = config.timeoutErrorMessage;
102
110
  }
103
- reject(createError(timeoutErrorMessage, config, 'ECONNABORTED',
111
+ reject(createError(
112
+ timeoutErrorMessage,
113
+ config,
114
+ config.transitional && config.transitional.clarifyTimeoutError ? 'ETIMEDOUT' : 'ECONNABORTED',
104
115
  request));
105
116
 
106
117
  // Clean up request
@@ -140,16 +151,8 @@ module.exports = function xhrAdapter(config) {
140
151
  }
141
152
 
142
153
  // Add responseType to request if needed
143
- if (config.responseType) {
144
- try {
145
- request.responseType = config.responseType;
146
- } catch (e) {
147
- // Expected DOMException thrown by browsers not compatible XMLHttpRequest Level 2.
148
- // But, this can be suppressed for 'json' type as it can be parsed by default 'transformResponse' function.
149
- if (config.responseType !== 'json') {
150
- throw e;
151
- }
152
- }
154
+ if (responseType && responseType !== 'json') {
155
+ request.responseType = config.responseType;
153
156
  }
154
157
 
155
158
  // Handle progress if needed
package/lib/axios.js CHANGED
@@ -47,6 +47,9 @@ axios.all = function all(promises) {
47
47
  };
48
48
  axios.spread = require('./helpers/spread');
49
49
 
50
+ // Expose isAxiosError
51
+ axios.isAxiosError = require('./helpers/isAxiosError');
52
+
50
53
  module.exports = axios;
51
54
 
52
55
  // Allow use of default import syntax in TypeScript
package/lib/core/Axios.js CHANGED
@@ -5,7 +5,9 @@ var buildURL = require('../helpers/buildURL');
5
5
  var InterceptorManager = require('./InterceptorManager');
6
6
  var dispatchRequest = require('./dispatchRequest');
7
7
  var mergeConfig = require('./mergeConfig');
8
+ var validator = require('../helpers/validator');
8
9
 
10
+ var validators = validator.validators;
9
11
  /**
10
12
  * Create a new instance of Axios
11
13
  *
@@ -45,20 +47,71 @@ Axios.prototype.request = function request(config) {
45
47
  config.method = 'get';
46
48
  }
47
49
 
48
- // Hook up interceptors middleware
49
- var chain = [dispatchRequest, undefined];
50
- var promise = Promise.resolve(config);
50
+ var transitional = config.transitional;
51
51
 
52
+ if (transitional !== undefined) {
53
+ validator.assertOptions(transitional, {
54
+ silentJSONParsing: validators.transitional(validators.boolean, '1.0.0'),
55
+ forcedJSONParsing: validators.transitional(validators.boolean, '1.0.0'),
56
+ clarifyTimeoutError: validators.transitional(validators.boolean, '1.0.0')
57
+ }, false);
58
+ }
59
+
60
+ // filter out skipped interceptors
61
+ var requestInterceptorChain = [];
62
+ var synchronousRequestInterceptors = true;
52
63
  this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) {
53
- chain.unshift(interceptor.fulfilled, interceptor.rejected);
64
+ if (typeof interceptor.runWhen === 'function' && interceptor.runWhen(config) === false) {
65
+ return;
66
+ }
67
+
68
+ synchronousRequestInterceptors = synchronousRequestInterceptors && interceptor.synchronous;
69
+
70
+ requestInterceptorChain.unshift(interceptor.fulfilled, interceptor.rejected);
54
71
  });
55
72
 
73
+ var responseInterceptorChain = [];
56
74
  this.interceptors.response.forEach(function pushResponseInterceptors(interceptor) {
57
- chain.push(interceptor.fulfilled, interceptor.rejected);
75
+ responseInterceptorChain.push(interceptor.fulfilled, interceptor.rejected);
58
76
  });
59
77
 
60
- while (chain.length) {
61
- promise = promise.then(chain.shift(), chain.shift());
78
+ var promise;
79
+
80
+ if (!synchronousRequestInterceptors) {
81
+ var chain = [dispatchRequest, undefined];
82
+
83
+ Array.prototype.unshift.apply(chain, requestInterceptorChain);
84
+ chain = chain.concat(responseInterceptorChain);
85
+
86
+ promise = Promise.resolve(config);
87
+ while (chain.length) {
88
+ promise = promise.then(chain.shift(), chain.shift());
89
+ }
90
+
91
+ return promise;
92
+ }
93
+
94
+
95
+ var newConfig = config;
96
+ while (requestInterceptorChain.length) {
97
+ var onFulfilled = requestInterceptorChain.shift();
98
+ var onRejected = requestInterceptorChain.shift();
99
+ try {
100
+ newConfig = onFulfilled(newConfig);
101
+ } catch (error) {
102
+ onRejected(error);
103
+ break;
104
+ }
105
+ }
106
+
107
+ try {
108
+ promise = dispatchRequest(newConfig);
109
+ } catch (error) {
110
+ return Promise.reject(error);
111
+ }
112
+
113
+ while (responseInterceptorChain.length) {
114
+ promise = promise.then(responseInterceptorChain.shift(), responseInterceptorChain.shift());
62
115
  }
63
116
 
64
117
  return promise;
@@ -75,7 +128,8 @@ utils.forEach(['delete', 'get', 'head', 'options'], function forEachMethodNoData
75
128
  Axios.prototype[method] = function(url, config) {
76
129
  return this.request(mergeConfig(config || {}, {
77
130
  method: method,
78
- url: url
131
+ url: url,
132
+ data: (config || {}).data
79
133
  }));
80
134
  };
81
135
  });
@@ -14,10 +14,12 @@ function InterceptorManager() {
14
14
  *
15
15
  * @return {Number} An ID used to remove interceptor later
16
16
  */
17
- InterceptorManager.prototype.use = function use(fulfilled, rejected) {
17
+ InterceptorManager.prototype.use = function use(fulfilled, rejected, options) {
18
18
  this.handlers.push({
19
19
  fulfilled: fulfilled,
20
- rejected: rejected
20
+ rejected: rejected,
21
+ synchronous: options ? options.synchronous : false,
22
+ runWhen: options ? options.runWhen : null
21
23
  });
22
24
  return this.handlers.length - 1;
23
25
  };
@@ -3,5 +3,6 @@
3
3
  The modules found in `core/` should be modules that are specific to the domain logic of axios. These modules would most likely not make sense to be consumed outside of the axios module, as their logic is too specific. Some examples of core modules are:
4
4
 
5
5
  - Dispatching requests
6
+ - Requests sent via `adapters/` (see lib/adapters/README.md)
6
7
  - Managing interceptors
7
8
  - Handling config
@@ -27,7 +27,8 @@ module.exports = function dispatchRequest(config) {
27
27
  config.headers = config.headers || {};
28
28
 
29
29
  // Transform request data
30
- config.data = transformData(
30
+ config.data = transformData.call(
31
+ config,
31
32
  config.data,
32
33
  config.headers,
33
34
  config.transformRequest
@@ -53,7 +54,8 @@ module.exports = function dispatchRequest(config) {
53
54
  throwIfCancellationRequested(config);
54
55
 
55
56
  // Transform response data
56
- response.data = transformData(
57
+ response.data = transformData.call(
58
+ config,
57
59
  response.data,
58
60
  response.headers,
59
61
  config.transformResponse
@@ -66,7 +68,8 @@ module.exports = function dispatchRequest(config) {
66
68
 
67
69
  // Transform response data
68
70
  if (reason && reason.response) {
69
- reason.response.data = transformData(
71
+ reason.response.data = transformData.call(
72
+ config,
70
73
  reason.response.data,
71
74
  reason.response.headers,
72
75
  config.transformResponse
@@ -1,6 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  var utils = require('./../utils');
4
+ var defaults = require('./../defaults');
4
5
 
5
6
  /**
6
7
  * Transform the data for a request or a response
@@ -11,9 +12,10 @@ var utils = require('./../utils');
11
12
  * @returns {*} The resulting transformed data
12
13
  */
13
14
  module.exports = function transformData(data, headers, fns) {
15
+ var context = this || defaults;
14
16
  /*eslint no-param-reassign:0*/
15
17
  utils.forEach(fns, function transform(fn) {
16
- data = fn(data, headers);
18
+ data = fn.call(context, data, headers);
17
19
  });
18
20
 
19
21
  return data;
package/lib/defaults.js CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  var utils = require('./utils');
4
4
  var normalizeHeaderName = require('./helpers/normalizeHeaderName');
5
+ var enhanceError = require('./core/enhanceError');
5
6
 
6
7
  var DEFAULT_CONTENT_TYPE = {
7
8
  'Content-Type': 'application/x-www-form-urlencoded'
@@ -26,11 +27,19 @@ function getDefaultAdapter() {
26
27
  }
27
28
 
28
29
  var defaults = {
30
+
31
+ transitional: {
32
+ silentJSONParsing: true,
33
+ forcedJSONParsing: true,
34
+ clarifyTimeoutError: false
35
+ },
36
+
29
37
  adapter: getDefaultAdapter(),
30
38
 
31
39
  transformRequest: [function transformRequest(data, headers) {
32
40
  normalizeHeaderName(headers, 'Accept');
33
41
  normalizeHeaderName(headers, 'Content-Type');
42
+
34
43
  if (utils.isFormData(data) ||
35
44
  utils.isArrayBuffer(data) ||
36
45
  utils.isBuffer(data) ||
@@ -47,20 +56,32 @@ var defaults = {
47
56
  setContentTypeIfUnset(headers, 'application/x-www-form-urlencoded;charset=utf-8');
48
57
  return data.toString();
49
58
  }
50
- if (utils.isObject(data)) {
51
- setContentTypeIfUnset(headers, 'application/json;charset=utf-8');
59
+ if (utils.isObject(data) || (headers && headers['Content-Type'] === 'application/json')) {
60
+ setContentTypeIfUnset(headers, 'application/json');
52
61
  return JSON.stringify(data);
53
62
  }
54
63
  return data;
55
64
  }],
56
65
 
57
66
  transformResponse: [function transformResponse(data) {
58
- /*eslint no-param-reassign:0*/
59
- if (typeof data === 'string') {
67
+ var transitional = this.transitional;
68
+ var silentJSONParsing = transitional && transitional.silentJSONParsing;
69
+ var forcedJSONParsing = transitional && transitional.forcedJSONParsing;
70
+ var strictJSONParsing = !silentJSONParsing && this.responseType === 'json';
71
+
72
+ if (strictJSONParsing || (forcedJSONParsing && utils.isString(data) && data.length)) {
60
73
  try {
61
- data = JSON.parse(data);
62
- } catch (e) { /* Ignore */ }
74
+ return JSON.parse(data);
75
+ } catch (e) {
76
+ if (strictJSONParsing) {
77
+ if (e.name === 'SyntaxError') {
78
+ throw enhanceError(e, this, 'E_JSON_PARSE');
79
+ }
80
+ throw e;
81
+ }
82
+ }
63
83
  }
84
+
64
85
  return data;
65
86
  }],
66
87
 
@@ -0,0 +1,11 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * Determines whether the payload is an error thrown by Axios
5
+ *
6
+ * @param {*} payload The value to test
7
+ * @returns {boolean} True if the payload is an error thrown by Axios, otherwise false
8
+ */
9
+ module.exports = function isAxiosError(payload) {
10
+ return (typeof payload === 'object') && (payload.isAxiosError === true);
11
+ };
@@ -0,0 +1,105 @@
1
+ 'use strict';
2
+
3
+ var pkg = require('./../../package.json');
4
+
5
+ var validators = {};
6
+
7
+ // eslint-disable-next-line func-names
8
+ ['object', 'boolean', 'number', 'function', 'string', 'symbol'].forEach(function(type, i) {
9
+ validators[type] = function validator(thing) {
10
+ return typeof thing === type || 'a' + (i < 1 ? 'n ' : ' ') + type;
11
+ };
12
+ });
13
+
14
+ var deprecatedWarnings = {};
15
+ var currentVerArr = pkg.version.split('.');
16
+
17
+ /**
18
+ * Compare package versions
19
+ * @param {string} version
20
+ * @param {string?} thanVersion
21
+ * @returns {boolean}
22
+ */
23
+ function isOlderVersion(version, thanVersion) {
24
+ var pkgVersionArr = thanVersion ? thanVersion.split('.') : currentVerArr;
25
+ var destVer = version.split('.');
26
+ for (var i = 0; i < 3; i++) {
27
+ if (pkgVersionArr[i] > destVer[i]) {
28
+ return true;
29
+ } else if (pkgVersionArr[i] < destVer[i]) {
30
+ return false;
31
+ }
32
+ }
33
+ return false;
34
+ }
35
+
36
+ /**
37
+ * Transitional option validator
38
+ * @param {function|boolean?} validator
39
+ * @param {string?} version
40
+ * @param {string} message
41
+ * @returns {function}
42
+ */
43
+ validators.transitional = function transitional(validator, version, message) {
44
+ var isDeprecated = version && isOlderVersion(version);
45
+
46
+ function formatMessage(opt, desc) {
47
+ return '[Axios v' + pkg.version + '] Transitional option \'' + opt + '\'' + desc + (message ? '. ' + message : '');
48
+ }
49
+
50
+ // eslint-disable-next-line func-names
51
+ return function(value, opt, opts) {
52
+ if (validator === false) {
53
+ throw new Error(formatMessage(opt, ' has been removed in ' + version));
54
+ }
55
+
56
+ if (isDeprecated && !deprecatedWarnings[opt]) {
57
+ deprecatedWarnings[opt] = true;
58
+ // eslint-disable-next-line no-console
59
+ console.warn(
60
+ formatMessage(
61
+ opt,
62
+ ' has been deprecated since v' + version + ' and will be removed in the near future'
63
+ )
64
+ );
65
+ }
66
+
67
+ return validator ? validator(value, opt, opts) : true;
68
+ };
69
+ };
70
+
71
+ /**
72
+ * Assert object's properties type
73
+ * @param {object} options
74
+ * @param {object} schema
75
+ * @param {boolean?} allowUnknown
76
+ */
77
+
78
+ function assertOptions(options, schema, allowUnknown) {
79
+ if (typeof options !== 'object') {
80
+ throw new TypeError('options must be an object');
81
+ }
82
+ var keys = Object.keys(options);
83
+ var i = keys.length;
84
+ while (i-- > 0) {
85
+ var opt = keys[i];
86
+ var validator = schema[opt];
87
+ if (validator) {
88
+ var value = options[opt];
89
+ var result = value === undefined || validator(value, opt, options);
90
+ if (result !== true) {
91
+ throw new TypeError('option ' + opt + ' must be ' + result);
92
+ }
93
+ continue;
94
+ }
95
+ if (allowUnknown !== true) {
96
+ throw Error('Unknown option ' + opt);
97
+ }
98
+ }
99
+ }
100
+
101
+ module.exports = {
102
+ isOlderVersion: isOlderVersion,
103
+ assertOptions: assertOptions,
104
+ validators: validators
105
+ };
package/lib/utils.js CHANGED
@@ -2,8 +2,6 @@
2
2
 
3
3
  var bind = require('./helpers/bind');
4
4
 
5
- /*global toString:true*/
6
-
7
5
  // utils is a library of generic helper functions non-specific to axios
8
6
 
9
7
  var toString = Object.prototype.toString;
@@ -187,7 +185,7 @@ function isURLSearchParams(val) {
187
185
  * @returns {String} The String freed of excess whitespace
188
186
  */
189
187
  function trim(str) {
190
- return str.replace(/^\s*/, '').replace(/\s*$/, '');
188
+ return str.trim ? str.trim() : str.replace(/^\s+|\s+$/g, '');
191
189
  }
192
190
 
193
191
  /**