axios 0.21.4 → 0.30.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/CHANGELOG.md +318 -54
- package/README.md +378 -64
- package/SECURITY.md +3 -3
- package/UPGRADE_GUIDE.md +41 -13
- package/bin/check-build-version.js +19 -0
- package/bin/ssl_hotfix.js +22 -0
- package/dist/axios.js +2072 -1878
- package/dist/axios.js.map +1 -0
- package/dist/axios.min.js +2 -3
- package/dist/axios.min.js.map +1 -0
- package/dist/esm/axios.js +2379 -0
- package/dist/esm/axios.js.map +1 -0
- package/dist/esm/axios.min.js +2 -0
- package/dist/esm/axios.min.js.map +1 -0
- package/index.d.ts +219 -46
- package/lib/adapters/http.js +262 -130
- package/lib/adapters/xhr.js +59 -22
- package/lib/axios.js +19 -7
- package/lib/cancel/CancelToken.js +65 -4
- package/lib/cancel/CanceledError.js +24 -0
- package/lib/core/Axios.js +45 -17
- package/lib/core/AxiosError.js +97 -0
- package/lib/core/InterceptorManager.js +9 -0
- package/lib/core/buildFullPath.js +5 -2
- package/lib/core/dispatchRequest.js +13 -1
- package/lib/core/mergeConfig.js +54 -38
- package/lib/core/settle.js +3 -3
- package/lib/core/transformData.js +4 -3
- package/lib/{defaults.js → defaults/index.js} +64 -23
- package/lib/defaults/transitional.js +7 -0
- package/lib/env/README.md +3 -0
- package/lib/env/classes/FormData.js +2 -0
- package/lib/env/data.js +3 -0
- package/lib/helpers/AxiosURLSearchParams.js +42 -0
- package/lib/helpers/bind.js +1 -5
- package/lib/helpers/buildURL.js +18 -33
- package/lib/helpers/combineURLs.js +1 -1
- package/lib/helpers/formDataToJSON.js +74 -0
- package/lib/helpers/fromDataURI.js +51 -0
- package/lib/helpers/isAbsoluteURL.js +1 -1
- package/lib/helpers/isAxiosError.js +3 -1
- package/lib/helpers/isURLSameOrigin.js +12 -12
- package/lib/helpers/null.js +2 -0
- package/lib/helpers/parseHeaders.js +2 -2
- package/lib/helpers/parseProtocol.js +6 -0
- package/lib/helpers/toFormData.js +179 -0
- package/lib/helpers/toURLEncodedForm.js +18 -0
- package/lib/helpers/validator.js +14 -33
- package/lib/platform/browser/classes/FormData.js +3 -0
- package/lib/platform/browser/classes/URLSearchParams.js +5 -0
- package/lib/platform/browser/index.js +11 -0
- package/lib/platform/index.js +3 -0
- package/lib/platform/node/classes/FormData.js +3 -0
- package/lib/platform/node/classes/URLSearchParams.js +5 -0
- package/lib/platform/node/index.js +11 -0
- package/lib/utils.js +210 -37
- package/package.json +42 -26
- package/rollup.config.js +60 -0
- package/tsconfig.json +14 -0
- package/tslint.json +6 -0
- package/dist/axios.map +0 -1
- package/dist/axios.min.map +0 -1
- package/lib/cancel/Cancel.js +0 -19
- package/lib/core/createError.js +0 -18
- package/lib/core/enhanceError.js +0 -42
package/lib/adapters/http.js
CHANGED
@@ -4,70 +4,186 @@ var utils = require('./../utils');
|
|
4
4
|
var settle = require('./../core/settle');
|
5
5
|
var buildFullPath = require('../core/buildFullPath');
|
6
6
|
var buildURL = require('./../helpers/buildURL');
|
7
|
+
var getProxyForUrl = require('proxy-from-env').getProxyForUrl;
|
7
8
|
var http = require('http');
|
8
9
|
var https = require('https');
|
9
|
-
var httpFollow = require('follow-redirects')
|
10
|
-
var httpsFollow = require('follow-redirects')
|
10
|
+
var httpFollow = require('follow-redirects/http');
|
11
|
+
var httpsFollow = require('follow-redirects/https');
|
11
12
|
var url = require('url');
|
12
13
|
var zlib = require('zlib');
|
13
|
-
var
|
14
|
-
var
|
15
|
-
var
|
14
|
+
var VERSION = require('./../env/data').version;
|
15
|
+
var transitionalDefaults = require('../defaults/transitional');
|
16
|
+
var AxiosError = require('../core/AxiosError');
|
17
|
+
var CanceledError = require('../cancel/CanceledError');
|
18
|
+
var platform = require('../platform');
|
19
|
+
var fromDataURI = require('../helpers/fromDataURI');
|
20
|
+
var stream = require('stream');
|
16
21
|
|
17
22
|
var isHttps = /https:?/;
|
18
23
|
|
24
|
+
var supportedProtocols = platform.protocols.map(function(protocol) {
|
25
|
+
return protocol + ':';
|
26
|
+
});
|
27
|
+
|
28
|
+
function dispatchBeforeRedirect(options) {
|
29
|
+
if (options.beforeRedirects.proxy) {
|
30
|
+
options.beforeRedirects.proxy(options);
|
31
|
+
}
|
32
|
+
if (options.beforeRedirects.config) {
|
33
|
+
options.beforeRedirects.config(options);
|
34
|
+
}
|
35
|
+
}
|
36
|
+
|
19
37
|
/**
|
20
38
|
*
|
21
39
|
* @param {http.ClientRequestArgs} options
|
22
|
-
* @param {AxiosProxyConfig}
|
40
|
+
* @param {AxiosProxyConfig} configProxy
|
23
41
|
* @param {string} location
|
24
42
|
*/
|
25
|
-
function setProxy(options,
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
43
|
+
function setProxy(options, configProxy, location) {
|
44
|
+
var proxy = configProxy;
|
45
|
+
if (!proxy && proxy !== false) {
|
46
|
+
var proxyUrl = getProxyForUrl(location);
|
47
|
+
if (proxyUrl) {
|
48
|
+
proxy = url.parse(proxyUrl);
|
49
|
+
// replace 'host' since the proxy object is not a URL object
|
50
|
+
proxy.host = proxy.hostname;
|
51
|
+
}
|
52
|
+
}
|
53
|
+
if (proxy) {
|
54
|
+
// Basic proxy authorization
|
55
|
+
if (proxy.auth) {
|
56
|
+
// Support proxy auth object form
|
57
|
+
if (proxy.auth.username || proxy.auth.password) {
|
58
|
+
proxy.auth = (proxy.auth.username || '') + ':' + (proxy.auth.password || '');
|
59
|
+
}
|
60
|
+
var base64 = Buffer
|
61
|
+
.from(proxy.auth, 'utf8')
|
62
|
+
.toString('base64');
|
63
|
+
options.headers['Proxy-Authorization'] = 'Basic ' + base64;
|
64
|
+
}
|
65
|
+
|
66
|
+
options.headers.host = options.hostname + (options.port ? ':' + options.port : '');
|
67
|
+
options.hostname = proxy.host;
|
68
|
+
options.host = proxy.host;
|
69
|
+
options.port = proxy.port;
|
70
|
+
options.path = location;
|
71
|
+
if (proxy.protocol) {
|
72
|
+
options.protocol = proxy.protocol;
|
73
|
+
}
|
35
74
|
}
|
36
75
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
setProxy(
|
76
|
+
options.beforeRedirects.proxy = function beforeRedirect(redirectOptions) {
|
77
|
+
// Configure proxy for redirected request, passing the original config proxy to apply
|
78
|
+
// the exact same logic as if the redirected request was performed by axios directly.
|
79
|
+
setProxy(redirectOptions, configProxy, redirectOptions.href);
|
41
80
|
};
|
42
81
|
}
|
43
82
|
|
44
83
|
/*eslint consistent-return:0*/
|
45
84
|
module.exports = function httpAdapter(config) {
|
46
85
|
return new Promise(function dispatchHttpRequest(resolvePromise, rejectPromise) {
|
86
|
+
var onCanceled;
|
87
|
+
function done() {
|
88
|
+
if (config.cancelToken) {
|
89
|
+
config.cancelToken.unsubscribe(onCanceled);
|
90
|
+
}
|
91
|
+
|
92
|
+
if (config.signal) {
|
93
|
+
config.signal.removeEventListener('abort', onCanceled);
|
94
|
+
}
|
95
|
+
}
|
47
96
|
var resolve = function resolve(value) {
|
97
|
+
done();
|
48
98
|
resolvePromise(value);
|
49
99
|
};
|
100
|
+
var rejected = false;
|
50
101
|
var reject = function reject(value) {
|
102
|
+
done();
|
103
|
+
rejected = true;
|
51
104
|
rejectPromise(value);
|
52
105
|
};
|
53
106
|
var data = config.data;
|
107
|
+
var responseType = config.responseType;
|
108
|
+
var responseEncoding = config.responseEncoding;
|
109
|
+
var method = config.method.toUpperCase();
|
110
|
+
|
111
|
+
// Parse url
|
112
|
+
var fullPath = buildFullPath(config.baseURL, config.url, config.allowAbsoluteUrls);
|
113
|
+
var parsed = url.parse(fullPath);
|
114
|
+
var protocol = parsed.protocol || supportedProtocols[0];
|
115
|
+
|
116
|
+
if (protocol === 'data:') {
|
117
|
+
var convertedData;
|
118
|
+
|
119
|
+
if (method !== 'GET') {
|
120
|
+
return settle(resolve, reject, {
|
121
|
+
status: 405,
|
122
|
+
statusText: 'method not allowed',
|
123
|
+
headers: {},
|
124
|
+
config: config
|
125
|
+
});
|
126
|
+
}
|
127
|
+
|
128
|
+
try {
|
129
|
+
convertedData = fromDataURI(config.url, responseType === 'blob', {
|
130
|
+
Blob: config.env && config.env.Blob
|
131
|
+
});
|
132
|
+
} catch (err) {
|
133
|
+
throw AxiosError.from(err, AxiosError.ERR_BAD_REQUEST, config);
|
134
|
+
}
|
135
|
+
|
136
|
+
if (responseType === 'text') {
|
137
|
+
convertedData = convertedData.toString(responseEncoding);
|
138
|
+
|
139
|
+
if (!responseEncoding || responseEncoding === 'utf8') {
|
140
|
+
data = utils.stripBOM(convertedData);
|
141
|
+
}
|
142
|
+
} else if (responseType === 'stream') {
|
143
|
+
convertedData = stream.Readable.from(convertedData);
|
144
|
+
}
|
145
|
+
|
146
|
+
return settle(resolve, reject, {
|
147
|
+
data: convertedData,
|
148
|
+
status: 200,
|
149
|
+
statusText: 'OK',
|
150
|
+
headers: {},
|
151
|
+
config: config
|
152
|
+
});
|
153
|
+
}
|
154
|
+
|
155
|
+
if (supportedProtocols.indexOf(protocol) === -1) {
|
156
|
+
return reject(new AxiosError(
|
157
|
+
'Unsupported protocol ' + protocol,
|
158
|
+
AxiosError.ERR_BAD_REQUEST,
|
159
|
+
config
|
160
|
+
));
|
161
|
+
}
|
162
|
+
|
54
163
|
var headers = config.headers;
|
164
|
+
var headerNames = {};
|
165
|
+
|
166
|
+
Object.keys(headers).forEach(function storeLowerName(name) {
|
167
|
+
headerNames[name.toLowerCase()] = name;
|
168
|
+
});
|
55
169
|
|
56
170
|
// Set User-Agent (required by some servers)
|
57
171
|
// See https://github.com/axios/axios/issues/69
|
58
|
-
if ('
|
172
|
+
if ('user-agent' in headerNames) {
|
59
173
|
// User-Agent is specified; handle case where no UA header is desired
|
60
|
-
if (!headers[
|
61
|
-
delete headers['
|
62
|
-
delete headers['user-agent'];
|
174
|
+
if (!headers[headerNames['user-agent']]) {
|
175
|
+
delete headers[headerNames['user-agent']];
|
63
176
|
}
|
64
177
|
// Otherwise, use specified value
|
65
178
|
} else {
|
66
179
|
// Only set header if it hasn't been set in config
|
67
|
-
headers['User-Agent'] = 'axios/' +
|
180
|
+
headers['User-Agent'] = 'axios/' + VERSION;
|
68
181
|
}
|
69
182
|
|
70
|
-
|
183
|
+
// support for https://www.npmjs.com/package/form-data api
|
184
|
+
if (utils.isFormData(data) && utils.isFunction(data.getHeaders)) {
|
185
|
+
Object.assign(headers, data.getHeaders());
|
186
|
+
} else if (data && !utils.isStream(data)) {
|
71
187
|
if (Buffer.isBuffer(data)) {
|
72
188
|
// Nothing to do...
|
73
189
|
} else if (utils.isArrayBuffer(data)) {
|
@@ -75,14 +191,25 @@ module.exports = function httpAdapter(config) {
|
|
75
191
|
} else if (utils.isString(data)) {
|
76
192
|
data = Buffer.from(data, 'utf-8');
|
77
193
|
} else {
|
78
|
-
return reject(
|
194
|
+
return reject(new AxiosError(
|
79
195
|
'Data after transformation must be a string, an ArrayBuffer, a Buffer, or a Stream',
|
196
|
+
AxiosError.ERR_BAD_REQUEST,
|
197
|
+
config
|
198
|
+
));
|
199
|
+
}
|
200
|
+
|
201
|
+
if (config.maxBodyLength > -1 && data.length > config.maxBodyLength) {
|
202
|
+
return reject(new AxiosError(
|
203
|
+
'Request body larger than maxBodyLength limit',
|
204
|
+
AxiosError.ERR_BAD_REQUEST,
|
80
205
|
config
|
81
206
|
));
|
82
207
|
}
|
83
208
|
|
84
209
|
// Add Content-Length header if data exists
|
85
|
-
|
210
|
+
if (!headerNames['content-length']) {
|
211
|
+
headers['Content-Length'] = data.length;
|
212
|
+
}
|
86
213
|
}
|
87
214
|
|
88
215
|
// HTTP basic authentication
|
@@ -93,11 +220,6 @@ module.exports = function httpAdapter(config) {
|
|
93
220
|
auth = username + ':' + password;
|
94
221
|
}
|
95
222
|
|
96
|
-
// Parse url
|
97
|
-
var fullPath = buildFullPath(config.baseURL, config.url);
|
98
|
-
var parsed = url.parse(fullPath);
|
99
|
-
var protocol = parsed.protocol || 'http:';
|
100
|
-
|
101
223
|
if (!auth && parsed.auth) {
|
102
224
|
var urlAuth = parsed.auth.split(':');
|
103
225
|
var urlUsername = urlAuth[0] || '';
|
@@ -105,20 +227,29 @@ module.exports = function httpAdapter(config) {
|
|
105
227
|
auth = urlUsername + ':' + urlPassword;
|
106
228
|
}
|
107
229
|
|
108
|
-
if (auth) {
|
109
|
-
delete headers.
|
230
|
+
if (auth && headerNames.authorization) {
|
231
|
+
delete headers[headerNames.authorization];
|
110
232
|
}
|
111
233
|
|
112
|
-
|
113
|
-
|
234
|
+
try {
|
235
|
+
buildURL(parsed.path, config.params, config.paramsSerializer).replace(/^\?/, '');
|
236
|
+
} catch (err) {
|
237
|
+
var customErr = new Error(err.message);
|
238
|
+
customErr.config = config;
|
239
|
+
customErr.url = config.url;
|
240
|
+
customErr.exists = true;
|
241
|
+
reject(customErr);
|
242
|
+
}
|
114
243
|
|
115
244
|
var options = {
|
116
245
|
path: buildURL(parsed.path, config.params, config.paramsSerializer).replace(/^\?/, ''),
|
117
|
-
method:
|
246
|
+
method: method,
|
118
247
|
headers: headers,
|
119
|
-
agent: agent,
|
120
248
|
agents: { http: config.httpAgent, https: config.httpsAgent },
|
121
|
-
auth: auth
|
249
|
+
auth: auth,
|
250
|
+
protocol: protocol,
|
251
|
+
beforeRedirect: dispatchBeforeRedirect,
|
252
|
+
beforeRedirects: {}
|
122
253
|
};
|
123
254
|
|
124
255
|
if (config.socketPath) {
|
@@ -126,76 +257,35 @@ module.exports = function httpAdapter(config) {
|
|
126
257
|
} else {
|
127
258
|
options.hostname = parsed.hostname;
|
128
259
|
options.port = parsed.port;
|
129
|
-
|
130
|
-
|
131
|
-
var proxy = config.proxy;
|
132
|
-
if (!proxy && proxy !== false) {
|
133
|
-
var proxyEnv = protocol.slice(0, -1) + '_proxy';
|
134
|
-
var proxyUrl = process.env[proxyEnv] || process.env[proxyEnv.toUpperCase()];
|
135
|
-
if (proxyUrl) {
|
136
|
-
var parsedProxyUrl = url.parse(proxyUrl);
|
137
|
-
var noProxyEnv = process.env.no_proxy || process.env.NO_PROXY;
|
138
|
-
var shouldProxy = true;
|
139
|
-
|
140
|
-
if (noProxyEnv) {
|
141
|
-
var noProxy = noProxyEnv.split(',').map(function trim(s) {
|
142
|
-
return s.trim();
|
143
|
-
});
|
144
|
-
|
145
|
-
shouldProxy = !noProxy.some(function proxyMatch(proxyElement) {
|
146
|
-
if (!proxyElement) {
|
147
|
-
return false;
|
148
|
-
}
|
149
|
-
if (proxyElement === '*') {
|
150
|
-
return true;
|
151
|
-
}
|
152
|
-
if (proxyElement[0] === '.' &&
|
153
|
-
parsed.hostname.substr(parsed.hostname.length - proxyElement.length) === proxyElement) {
|
154
|
-
return true;
|
155
|
-
}
|
156
|
-
|
157
|
-
return parsed.hostname === proxyElement;
|
158
|
-
});
|
159
|
-
}
|
160
|
-
|
161
|
-
if (shouldProxy) {
|
162
|
-
proxy = {
|
163
|
-
host: parsedProxyUrl.hostname,
|
164
|
-
port: parsedProxyUrl.port,
|
165
|
-
protocol: parsedProxyUrl.protocol
|
166
|
-
};
|
167
|
-
|
168
|
-
if (parsedProxyUrl.auth) {
|
169
|
-
var proxyUrlAuth = parsedProxyUrl.auth.split(':');
|
170
|
-
proxy.auth = {
|
171
|
-
username: proxyUrlAuth[0],
|
172
|
-
password: proxyUrlAuth[1]
|
173
|
-
};
|
174
|
-
}
|
175
|
-
}
|
176
|
-
}
|
177
|
-
}
|
178
|
-
|
179
|
-
if (proxy) {
|
180
|
-
options.headers.host = parsed.hostname + (parsed.port ? ':' + parsed.port : '');
|
181
|
-
setProxy(options, proxy, protocol + '//' + parsed.hostname + (parsed.port ? ':' + parsed.port : '') + options.path);
|
260
|
+
setProxy(options, config.proxy, protocol + '//' + parsed.hostname + (parsed.port ? ':' + parsed.port : '') + options.path);
|
182
261
|
}
|
183
262
|
|
184
263
|
var transport;
|
185
|
-
var
|
264
|
+
var isHttpsRequest = isHttps.test(options.protocol);
|
265
|
+
options.agent = isHttpsRequest ? config.httpsAgent : config.httpAgent;
|
186
266
|
if (config.transport) {
|
187
267
|
transport = config.transport;
|
188
268
|
} else if (config.maxRedirects === 0) {
|
189
|
-
transport =
|
269
|
+
transport = isHttpsRequest ? https : http;
|
190
270
|
} else {
|
191
271
|
if (config.maxRedirects) {
|
192
272
|
options.maxRedirects = config.maxRedirects;
|
193
273
|
}
|
194
|
-
|
274
|
+
if (config.beforeRedirect) {
|
275
|
+
options.beforeRedirects.config = config.beforeRedirect;
|
276
|
+
}
|
277
|
+
transport = isHttpsRequest ? httpsFollow : httpFollow;
|
195
278
|
}
|
196
279
|
|
197
280
|
if (config.maxBodyLength > -1) {
|
198
281
|
options.maxBodyLength = config.maxBodyLength;
|
282
|
+
} else {
|
283
|
+
// follow-redirects does not skip comparison, so it should always succeed for axios -1 unlimited
|
284
|
+
options.maxBodyLength = Infinity;
|
285
|
+
}
|
286
|
+
|
287
|
+
if (config.insecureHTTPParser) {
|
288
|
+
options.insecureHTTPParser = config.insecureHTTPParser;
|
199
289
|
}
|
200
290
|
|
201
291
|
// Create the request
|
@@ -203,21 +293,26 @@ module.exports = function httpAdapter(config) {
|
|
203
293
|
if (req.aborted) return;
|
204
294
|
|
205
295
|
// uncompress the response body transparently if required
|
206
|
-
var
|
296
|
+
var responseStream = res;
|
207
297
|
|
208
298
|
// return the last request in case of redirects
|
209
299
|
var lastRequest = res.req || req;
|
210
300
|
|
301
|
+
// if decompress disabled we should not decompress
|
302
|
+
if (config.decompress !== false) {
|
303
|
+
// if no content, but headers still say that it is encoded,
|
304
|
+
// remove the header not confuse downstream operations
|
305
|
+
if (data && data.length === 0 && res.headers['content-encoding']) {
|
306
|
+
delete res.headers['content-encoding'];
|
307
|
+
}
|
211
308
|
|
212
|
-
// if no content, is HEAD request or decompress disabled we should not decompress
|
213
|
-
if (res.statusCode !== 204 && lastRequest.method !== 'HEAD' && config.decompress !== false) {
|
214
309
|
switch (res.headers['content-encoding']) {
|
215
310
|
/*eslint default-case:0*/
|
216
311
|
case 'gzip':
|
217
312
|
case 'compress':
|
218
313
|
case 'deflate':
|
219
|
-
|
220
|
-
|
314
|
+
// add the unzipper to the body stream processing pipeline
|
315
|
+
responseStream = responseStream.pipe(zlib.createUnzip());
|
221
316
|
|
222
317
|
// remove the content-encoding in order to not confuse downstream operations
|
223
318
|
delete res.headers['content-encoding'];
|
@@ -233,39 +328,57 @@ module.exports = function httpAdapter(config) {
|
|
233
328
|
request: lastRequest
|
234
329
|
};
|
235
330
|
|
236
|
-
if (
|
237
|
-
response.data =
|
331
|
+
if (responseType === 'stream') {
|
332
|
+
response.data = responseStream;
|
238
333
|
settle(resolve, reject, response);
|
239
334
|
} else {
|
240
335
|
var responseBuffer = [];
|
241
336
|
var totalResponseBytes = 0;
|
242
|
-
|
337
|
+
responseStream.on('data', function handleStreamData(chunk) {
|
243
338
|
responseBuffer.push(chunk);
|
244
339
|
totalResponseBytes += chunk.length;
|
245
340
|
|
246
341
|
// make sure the content length is not over the maxContentLength if specified
|
247
342
|
if (config.maxContentLength > -1 && totalResponseBytes > config.maxContentLength) {
|
248
|
-
stream.destroy()
|
249
|
-
|
250
|
-
|
343
|
+
// stream.destroy() emit aborted event before calling reject() on Node.js v16
|
344
|
+
rejected = true;
|
345
|
+
responseStream.destroy();
|
346
|
+
reject(new AxiosError('maxContentLength size of ' + config.maxContentLength + ' exceeded',
|
347
|
+
AxiosError.ERR_BAD_RESPONSE, config, lastRequest));
|
348
|
+
}
|
349
|
+
});
|
350
|
+
|
351
|
+
responseStream.on('aborted', function handlerStreamAborted() {
|
352
|
+
if (rejected) {
|
353
|
+
return;
|
251
354
|
}
|
355
|
+
responseStream.destroy();
|
356
|
+
reject(new AxiosError(
|
357
|
+
'response stream aborted',
|
358
|
+
AxiosError.ECONNABORTED,
|
359
|
+
config,
|
360
|
+
lastRequest
|
361
|
+
));
|
252
362
|
});
|
253
363
|
|
254
|
-
|
364
|
+
responseStream.on('error', function handleStreamError(err) {
|
255
365
|
if (req.aborted) return;
|
256
|
-
reject(
|
366
|
+
reject(AxiosError.from(err, null, config, lastRequest));
|
257
367
|
});
|
258
368
|
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
369
|
+
responseStream.on('end', function handleStreamEnd() {
|
370
|
+
try {
|
371
|
+
var responseData = responseBuffer.length === 1 ? responseBuffer[0] : Buffer.concat(responseBuffer);
|
372
|
+
if (responseType !== 'arraybuffer') {
|
373
|
+
responseData = responseData.toString(responseEncoding);
|
374
|
+
if (!responseEncoding || responseEncoding === 'utf8') {
|
375
|
+
responseData = utils.stripBOM(responseData);
|
376
|
+
}
|
265
377
|
}
|
378
|
+
response.data = responseData;
|
379
|
+
} catch (err) {
|
380
|
+
reject(AxiosError.from(err, null, config, response.request, response));
|
266
381
|
}
|
267
|
-
|
268
|
-
response.data = responseData;
|
269
382
|
settle(resolve, reject, response);
|
270
383
|
});
|
271
384
|
}
|
@@ -273,8 +386,15 @@ module.exports = function httpAdapter(config) {
|
|
273
386
|
|
274
387
|
// Handle errors
|
275
388
|
req.on('error', function handleRequestError(err) {
|
276
|
-
|
277
|
-
|
389
|
+
// @todo remove
|
390
|
+
// if (req.aborted && err.code !== AxiosError.ERR_FR_TOO_MANY_REDIRECTS) return;
|
391
|
+
reject(AxiosError.from(err, null, config, req));
|
392
|
+
});
|
393
|
+
|
394
|
+
// set tcp keep alive to prevent drop connection by peer
|
395
|
+
req.on('socket', function handleRequestSocket(socket) {
|
396
|
+
// default interval of sending ack packet is 1 minute
|
397
|
+
socket.setKeepAlive(true, 1000 * 60);
|
278
398
|
});
|
279
399
|
|
280
400
|
// Handle request timeout
|
@@ -283,10 +403,10 @@ module.exports = function httpAdapter(config) {
|
|
283
403
|
var timeout = parseInt(config.timeout, 10);
|
284
404
|
|
285
405
|
if (isNaN(timeout)) {
|
286
|
-
reject(
|
406
|
+
reject(new AxiosError(
|
287
407
|
'error trying to parse `config.timeout` to int',
|
408
|
+
AxiosError.ERR_BAD_OPTION_VALUE,
|
288
409
|
config,
|
289
|
-
'ERR_PARSE_TIMEOUT',
|
290
410
|
req
|
291
411
|
));
|
292
412
|
|
@@ -296,33 +416,45 @@ module.exports = function httpAdapter(config) {
|
|
296
416
|
// Sometime, the response will be very slow, and does not respond, the connect event will be block by event loop system.
|
297
417
|
// And timer callback will be fired, and abort() will be invoked before connection, then get "socket hang up" and code ECONNRESET.
|
298
418
|
// 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.
|
299
|
-
// And then these socket which be hang up will
|
419
|
+
// And then these socket which be hang up will devouring CPU little by little.
|
300
420
|
// ClientRequest.setTimeout will be fired on the specify milliseconds, and can make sure that abort() will be fired after connect.
|
301
421
|
req.setTimeout(timeout, function handleRequestTimeout() {
|
302
422
|
req.abort();
|
303
|
-
|
304
|
-
|
423
|
+
var timeoutErrorMessage = config.timeout ? 'timeout of ' + config.timeout + 'ms exceeded' : 'timeout exceeded';
|
424
|
+
var transitional = config.transitional || transitionalDefaults;
|
425
|
+
if (config.timeoutErrorMessage) {
|
426
|
+
timeoutErrorMessage = config.timeoutErrorMessage;
|
427
|
+
}
|
428
|
+
reject(new AxiosError(
|
429
|
+
timeoutErrorMessage,
|
430
|
+
transitional.clarifyTimeoutError ? AxiosError.ETIMEDOUT : AxiosError.ECONNABORTED,
|
305
431
|
config,
|
306
|
-
config.transitional && config.transitional.clarifyTimeoutError ? 'ETIMEDOUT' : 'ECONNABORTED',
|
307
432
|
req
|
308
433
|
));
|
309
434
|
});
|
310
435
|
}
|
311
436
|
|
312
|
-
if (config.cancelToken) {
|
437
|
+
if (config.cancelToken || config.signal) {
|
313
438
|
// Handle cancellation
|
314
|
-
|
439
|
+
// eslint-disable-next-line func-names
|
440
|
+
onCanceled = function(cancel) {
|
315
441
|
if (req.aborted) return;
|
316
442
|
|
317
443
|
req.abort();
|
318
|
-
reject(cancel);
|
319
|
-
}
|
444
|
+
reject(!cancel || cancel.type ? new CanceledError(null, config, req) : cancel);
|
445
|
+
};
|
446
|
+
|
447
|
+
config.cancelToken && config.cancelToken.subscribe(onCanceled);
|
448
|
+
if (config.signal) {
|
449
|
+
config.signal.aborted ? onCanceled() : config.signal.addEventListener('abort', onCanceled);
|
450
|
+
}
|
320
451
|
}
|
321
452
|
|
453
|
+
|
322
454
|
// Send the request
|
323
455
|
if (utils.isStream(data)) {
|
324
456
|
data.on('error', function handleStreamError(err) {
|
325
|
-
reject(
|
457
|
+
reject(AxiosError.from(err, config, null, req));
|
326
458
|
}).pipe(req);
|
327
459
|
} else {
|
328
460
|
req.end(data);
|