axios 1.0.0-alpha.1 → 1.0.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.
Potentially problematic release.
This version of axios might be problematic. Click here for more details.
- package/CHANGELOG.md +55 -1
- package/README.md +59 -48
- package/SECURITY.md +3 -2
- package/bin/ssl_hotfix.js +1 -1
- package/dist/axios.js +1552 -975
- 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 +1471 -865
- 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/dist/node/axios.cjs +3750 -0
- package/dist/node/axios.cjs.map +1 -0
- package/gulpfile.js +88 -0
- package/index.d.ts +208 -63
- package/index.js +2 -1
- package/karma.conf.cjs +250 -0
- package/lib/adapters/http.js +251 -131
- package/lib/adapters/index.js +33 -0
- package/lib/adapters/xhr.js +79 -56
- package/lib/axios.js +33 -25
- package/lib/cancel/CancelToken.js +91 -88
- package/lib/cancel/CanceledError.js +5 -4
- package/lib/cancel/isCancel.js +2 -2
- package/lib/core/Axios.js +127 -100
- package/lib/core/AxiosError.js +10 -7
- package/lib/core/AxiosHeaders.js +274 -0
- package/lib/core/InterceptorManager.js +61 -53
- package/lib/core/buildFullPath.js +5 -4
- package/lib/core/dispatchRequest.js +21 -39
- package/lib/core/mergeConfig.js +8 -7
- package/lib/core/settle.js +6 -4
- package/lib/core/transformData.js +15 -10
- package/lib/defaults/index.js +46 -39
- package/lib/defaults/transitional.js +1 -1
- package/lib/env/classes/FormData.js +2 -2
- package/lib/env/data.js +1 -3
- package/lib/helpers/AxiosTransformStream.js +191 -0
- package/lib/helpers/AxiosURLSearchParams.js +23 -7
- package/lib/helpers/bind.js +2 -2
- package/lib/helpers/buildURL.js +16 -7
- package/lib/helpers/combineURLs.js +3 -2
- package/lib/helpers/cookies.js +43 -44
- package/lib/helpers/deprecatedMethod.js +4 -2
- package/lib/helpers/formDataToJSON.js +36 -15
- package/lib/helpers/fromDataURI.js +15 -13
- package/lib/helpers/isAbsoluteURL.js +3 -2
- package/lib/helpers/isAxiosError.js +4 -3
- package/lib/helpers/isURLSameOrigin.js +55 -56
- package/lib/helpers/null.js +1 -1
- package/lib/helpers/parseHeaders.js +24 -22
- package/lib/helpers/parseProtocol.js +3 -3
- package/lib/helpers/speedometer.js +55 -0
- package/lib/helpers/spread.js +3 -2
- package/lib/helpers/throttle.js +33 -0
- package/lib/helpers/toFormData.js +68 -18
- package/lib/helpers/toURLEncodedForm.js +5 -5
- package/lib/helpers/validator.js +20 -15
- package/lib/platform/browser/classes/FormData.js +1 -1
- package/lib/platform/browser/classes/URLSearchParams.js +2 -3
- package/lib/platform/browser/index.js +38 -6
- package/lib/platform/index.js +2 -2
- package/lib/platform/node/classes/FormData.js +2 -2
- package/lib/platform/node/classes/URLSearchParams.js +2 -3
- package/lib/platform/node/index.js +5 -4
- package/lib/utils.js +293 -191
- package/package.json +55 -22
- package/rollup.config.js +36 -6
- package/lib/helpers/normalizeHeaderName.js +0 -12
package/lib/adapters/http.js
CHANGED
@@ -1,30 +1,43 @@
|
|
1
1
|
'use strict';
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
3
|
+
import utils from './../utils.js';
|
4
|
+
import settle from './../core/settle.js';
|
5
|
+
import buildFullPath from '../core/buildFullPath.js';
|
6
|
+
import buildURL from './../helpers/buildURL.js';
|
7
|
+
import {getProxyForUrl} from 'proxy-from-env';
|
8
|
+
import http from 'http';
|
9
|
+
import https from 'https';
|
10
|
+
import followRedirects from 'follow-redirects';
|
11
|
+
import zlib from 'zlib';
|
12
|
+
import {VERSION} from '../env/data.js';
|
13
|
+
import transitionalDefaults from '../defaults/transitional.js';
|
14
|
+
import AxiosError from '../core/AxiosError.js';
|
15
|
+
import CanceledError from '../cancel/CanceledError.js';
|
16
|
+
import platform from '../platform/index.js';
|
17
|
+
import fromDataURI from '../helpers/fromDataURI.js';
|
18
|
+
import stream from 'stream';
|
19
|
+
import AxiosHeaders from '../core/AxiosHeaders.js';
|
20
|
+
import AxiosTransformStream from '../helpers/AxiosTransformStream.js';
|
21
|
+
import EventEmitter from 'events';
|
22
|
+
|
23
|
+
const isBrotliSupported = utils.isFunction(zlib.createBrotliDecompress);
|
24
|
+
|
25
|
+
const {http: httpFollow, https: httpsFollow} = followRedirects;
|
26
|
+
|
27
|
+
const isHttps = /https:?/;
|
28
|
+
|
29
|
+
const supportedProtocols = platform.protocols.map(protocol => {
|
25
30
|
return protocol + ':';
|
26
31
|
});
|
27
32
|
|
33
|
+
/**
|
34
|
+
* If the proxy or config beforeRedirects functions are defined, call them with the options
|
35
|
+
* object.
|
36
|
+
*
|
37
|
+
* @param {Object<string, any>} options - The options object that was passed to the request.
|
38
|
+
*
|
39
|
+
* @returns {Object<string, any>}
|
40
|
+
*/
|
28
41
|
function dispatchBeforeRedirect(options) {
|
29
42
|
if (options.beforeRedirects.proxy) {
|
30
43
|
options.beforeRedirects.proxy(options);
|
@@ -35,37 +48,43 @@ function dispatchBeforeRedirect(options) {
|
|
35
48
|
}
|
36
49
|
|
37
50
|
/**
|
51
|
+
* If the proxy or config afterRedirects functions are defined, call them with the options
|
38
52
|
*
|
39
53
|
* @param {http.ClientRequestArgs} options
|
40
54
|
* @param {AxiosProxyConfig} configProxy
|
41
55
|
* @param {string} location
|
56
|
+
*
|
57
|
+
* @returns {http.ClientRequestArgs}
|
42
58
|
*/
|
43
59
|
function setProxy(options, configProxy, location) {
|
44
|
-
|
60
|
+
let proxy = configProxy;
|
45
61
|
if (!proxy && proxy !== false) {
|
46
|
-
|
62
|
+
const proxyUrl = getProxyForUrl(location);
|
47
63
|
if (proxyUrl) {
|
48
|
-
proxy =
|
49
|
-
// replace 'host' since the proxy object is not a URL object
|
50
|
-
proxy.host = proxy.hostname;
|
64
|
+
proxy = new URL(proxyUrl);
|
51
65
|
}
|
52
66
|
}
|
53
67
|
if (proxy) {
|
54
68
|
// Basic proxy authorization
|
69
|
+
if (proxy.username) {
|
70
|
+
proxy.auth = (proxy.username || '') + ':' + (proxy.password || '');
|
71
|
+
}
|
72
|
+
|
55
73
|
if (proxy.auth) {
|
56
74
|
// Support proxy auth object form
|
57
75
|
if (proxy.auth.username || proxy.auth.password) {
|
58
76
|
proxy.auth = (proxy.auth.username || '') + ':' + (proxy.auth.password || '');
|
59
77
|
}
|
60
|
-
|
78
|
+
const base64 = Buffer
|
61
79
|
.from(proxy.auth, 'utf8')
|
62
80
|
.toString('base64');
|
63
81
|
options.headers['Proxy-Authorization'] = 'Basic ' + base64;
|
64
82
|
}
|
65
83
|
|
66
84
|
options.headers.host = options.hostname + (options.port ? ':' + options.port : '');
|
67
|
-
options.hostname = proxy.
|
68
|
-
|
85
|
+
options.hostname = proxy.hostname;
|
86
|
+
// Replace 'host' since options is not a URL object
|
87
|
+
options.host = proxy.hostname;
|
69
88
|
options.port = proxy.port;
|
70
89
|
options.path = location;
|
71
90
|
if (proxy.protocol) {
|
@@ -81,47 +100,83 @@ function setProxy(options, configProxy, location) {
|
|
81
100
|
}
|
82
101
|
|
83
102
|
/*eslint consistent-return:0*/
|
84
|
-
|
103
|
+
export default function httpAdapter(config) {
|
85
104
|
return new Promise(function dispatchHttpRequest(resolvePromise, rejectPromise) {
|
86
|
-
|
87
|
-
|
105
|
+
let data = config.data;
|
106
|
+
const responseType = config.responseType;
|
107
|
+
const responseEncoding = config.responseEncoding;
|
108
|
+
const method = config.method.toUpperCase();
|
109
|
+
let isFinished;
|
110
|
+
let isDone;
|
111
|
+
let rejected = false;
|
112
|
+
let req;
|
113
|
+
|
114
|
+
// temporary internal emitter until the AxiosRequest class will be implemented
|
115
|
+
const emitter = new EventEmitter();
|
116
|
+
|
117
|
+
function onFinished() {
|
118
|
+
if (isFinished) return;
|
119
|
+
isFinished = true;
|
120
|
+
|
88
121
|
if (config.cancelToken) {
|
89
|
-
config.cancelToken.unsubscribe(
|
122
|
+
config.cancelToken.unsubscribe(abort);
|
90
123
|
}
|
91
124
|
|
92
125
|
if (config.signal) {
|
93
|
-
config.signal.removeEventListener('abort',
|
126
|
+
config.signal.removeEventListener('abort', abort);
|
94
127
|
}
|
128
|
+
|
129
|
+
emitter.removeAllListeners();
|
95
130
|
}
|
96
|
-
|
97
|
-
|
98
|
-
|
131
|
+
|
132
|
+
function done(value, isRejected) {
|
133
|
+
if (isDone) return;
|
134
|
+
|
135
|
+
isDone = true;
|
136
|
+
|
137
|
+
if (isRejected) {
|
138
|
+
rejected = true;
|
139
|
+
onFinished();
|
140
|
+
}
|
141
|
+
|
142
|
+
isRejected ? rejectPromise(value) : resolvePromise(value);
|
143
|
+
}
|
144
|
+
|
145
|
+
const resolve = function resolve(value) {
|
146
|
+
done(value);
|
99
147
|
};
|
100
|
-
|
101
|
-
|
102
|
-
done();
|
103
|
-
rejected = true;
|
104
|
-
rejectPromise(value);
|
148
|
+
|
149
|
+
const reject = function reject(value) {
|
150
|
+
done(value, true);
|
105
151
|
};
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
152
|
+
|
153
|
+
function abort(reason) {
|
154
|
+
emitter.emit('abort', !reason || reason.type ? new CanceledError(null, config, req) : reason);
|
155
|
+
}
|
156
|
+
|
157
|
+
emitter.once('abort', reject);
|
158
|
+
|
159
|
+
if (config.cancelToken || config.signal) {
|
160
|
+
config.cancelToken && config.cancelToken.subscribe(abort);
|
161
|
+
if (config.signal) {
|
162
|
+
config.signal.aborted ? abort() : config.signal.addEventListener('abort', abort);
|
163
|
+
}
|
164
|
+
}
|
110
165
|
|
111
166
|
// Parse url
|
112
|
-
|
113
|
-
|
114
|
-
|
167
|
+
const fullPath = buildFullPath(config.baseURL, config.url);
|
168
|
+
const parsed = new URL(fullPath);
|
169
|
+
const protocol = parsed.protocol || supportedProtocols[0];
|
115
170
|
|
116
171
|
if (protocol === 'data:') {
|
117
|
-
|
172
|
+
let convertedData;
|
118
173
|
|
119
174
|
if (method !== 'GET') {
|
120
175
|
return settle(resolve, reject, {
|
121
176
|
status: 405,
|
122
177
|
statusText: 'method not allowed',
|
123
178
|
headers: {},
|
124
|
-
config
|
179
|
+
config
|
125
180
|
});
|
126
181
|
}
|
127
182
|
|
@@ -148,7 +203,7 @@ module.exports = function httpAdapter(config) {
|
|
148
203
|
status: 200,
|
149
204
|
statusText: 'OK',
|
150
205
|
headers: {},
|
151
|
-
config
|
206
|
+
config
|
152
207
|
});
|
153
208
|
}
|
154
209
|
|
@@ -160,29 +215,23 @@ module.exports = function httpAdapter(config) {
|
|
160
215
|
));
|
161
216
|
}
|
162
217
|
|
163
|
-
|
164
|
-
var headerNames = {};
|
165
|
-
|
166
|
-
Object.keys(headers).forEach(function storeLowerName(name) {
|
167
|
-
headerNames[name.toLowerCase()] = name;
|
168
|
-
});
|
218
|
+
const headers = AxiosHeaders.from(config.headers).normalize();
|
169
219
|
|
170
220
|
// Set User-Agent (required by some servers)
|
171
221
|
// See https://github.com/axios/axios/issues/69
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
}
|
222
|
+
// User-Agent is specified; handle case where no UA header is desired
|
223
|
+
// Only set header if it hasn't been set in config
|
224
|
+
headers.set('User-Agent', 'axios/' + VERSION, false);
|
225
|
+
|
226
|
+
const onDownloadProgress = config.onDownloadProgress;
|
227
|
+
const onUploadProgress = config.onUploadProgress;
|
228
|
+
const maxRate = config.maxRate;
|
229
|
+
let maxUploadRate = undefined;
|
230
|
+
let maxDownloadRate = undefined;
|
182
231
|
|
183
232
|
// support for https://www.npmjs.com/package/form-data api
|
184
233
|
if (utils.isFormData(data) && utils.isFunction(data.getHeaders)) {
|
185
|
-
|
234
|
+
headers.set(data.getHeaders());
|
186
235
|
} else if (data && !utils.isStream(data)) {
|
187
236
|
if (Buffer.isBuffer(data)) {
|
188
237
|
// Nothing to do...
|
@@ -198,6 +247,9 @@ module.exports = function httpAdapter(config) {
|
|
198
247
|
));
|
199
248
|
}
|
200
249
|
|
250
|
+
// Add Content-Length header if data exists
|
251
|
+
headers.set('Content-Length', data.length, false);
|
252
|
+
|
201
253
|
if (config.maxBodyLength > -1 && data.length > config.maxBodyLength) {
|
202
254
|
return reject(new AxiosError(
|
203
255
|
'Request body larger than maxBodyLength limit',
|
@@ -205,49 +257,70 @@ module.exports = function httpAdapter(config) {
|
|
205
257
|
config
|
206
258
|
));
|
207
259
|
}
|
260
|
+
}
|
208
261
|
|
209
|
-
|
210
|
-
|
211
|
-
|
262
|
+
const contentLength = +headers.getContentLength();
|
263
|
+
|
264
|
+
if (utils.isArray(maxRate)) {
|
265
|
+
maxUploadRate = maxRate[0];
|
266
|
+
maxDownloadRate = maxRate[1];
|
267
|
+
} else {
|
268
|
+
maxUploadRate = maxDownloadRate = maxRate;
|
269
|
+
}
|
270
|
+
|
271
|
+
if (data && (onUploadProgress || maxUploadRate)) {
|
272
|
+
if (!utils.isStream(data)) {
|
273
|
+
data = stream.Readable.from(data, {objectMode: false});
|
212
274
|
}
|
275
|
+
|
276
|
+
data = stream.pipeline([data, new AxiosTransformStream({
|
277
|
+
length: utils.toFiniteNumber(contentLength),
|
278
|
+
maxRate: utils.toFiniteNumber(maxUploadRate)
|
279
|
+
})], utils.noop);
|
280
|
+
|
281
|
+
onUploadProgress && data.on('progress', progress => {
|
282
|
+
onUploadProgress(Object.assign(progress, {
|
283
|
+
upload: true
|
284
|
+
}));
|
285
|
+
});
|
213
286
|
}
|
214
287
|
|
215
288
|
// HTTP basic authentication
|
216
|
-
|
289
|
+
let auth = undefined;
|
217
290
|
if (config.auth) {
|
218
|
-
|
219
|
-
|
291
|
+
const username = config.auth.username || '';
|
292
|
+
const password = config.auth.password || '';
|
220
293
|
auth = username + ':' + password;
|
221
294
|
}
|
222
295
|
|
223
|
-
if (!auth && parsed.
|
224
|
-
|
225
|
-
|
226
|
-
var urlPassword = urlAuth[1] || '';
|
296
|
+
if (!auth && parsed.username) {
|
297
|
+
const urlUsername = parsed.username;
|
298
|
+
const urlPassword = parsed.password;
|
227
299
|
auth = urlUsername + ':' + urlPassword;
|
228
300
|
}
|
229
301
|
|
230
|
-
|
231
|
-
delete headers[headerNames.authorization];
|
232
|
-
}
|
302
|
+
auth && headers.delete('authorization');
|
233
303
|
|
304
|
+
const path = parsed.pathname.concat(parsed.searchParams);
|
234
305
|
try {
|
235
|
-
buildURL(
|
306
|
+
buildURL(path, config.params, config.paramsSerializer).replace(/^\?/, '');
|
236
307
|
} catch (err) {
|
237
|
-
|
308
|
+
const customErr = new Error(err.message);
|
238
309
|
customErr.config = config;
|
239
310
|
customErr.url = config.url;
|
240
311
|
customErr.exists = true;
|
241
|
-
reject(customErr);
|
312
|
+
return reject(customErr);
|
242
313
|
}
|
243
314
|
|
244
|
-
|
245
|
-
|
315
|
+
headers.set('Accept-Encoding', 'gzip, deflate, br', false);
|
316
|
+
|
317
|
+
const options = {
|
318
|
+
path: buildURL(path, config.params, config.paramsSerializer).replace(/^\?/, ''),
|
246
319
|
method: method,
|
247
|
-
headers: headers,
|
320
|
+
headers: headers.toJSON(),
|
248
321
|
agents: { http: config.httpAgent, https: config.httpsAgent },
|
249
|
-
auth
|
250
|
-
protocol
|
322
|
+
auth,
|
323
|
+
protocol,
|
251
324
|
beforeRedirect: dispatchBeforeRedirect,
|
252
325
|
beforeRedirects: {}
|
253
326
|
};
|
@@ -260,8 +333,8 @@ module.exports = function httpAdapter(config) {
|
|
260
333
|
setProxy(options, config.proxy, protocol + '//' + parsed.hostname + (parsed.port ? ':' + parsed.port : '') + options.path);
|
261
334
|
}
|
262
335
|
|
263
|
-
|
264
|
-
|
336
|
+
let transport;
|
337
|
+
const isHttpsRequest = isHttps.test(options.protocol);
|
265
338
|
options.agent = isHttpsRequest ? config.httpsAgent : config.httpAgent;
|
266
339
|
if (config.transport) {
|
267
340
|
transport = config.transport;
|
@@ -289,14 +362,16 @@ module.exports = function httpAdapter(config) {
|
|
289
362
|
}
|
290
363
|
|
291
364
|
// Create the request
|
292
|
-
|
293
|
-
if (req.
|
365
|
+
req = transport.request(options, function handleResponse(res) {
|
366
|
+
if (req.destroyed) return;
|
367
|
+
|
368
|
+
const streams = [res];
|
294
369
|
|
295
370
|
// uncompress the response body transparently if required
|
296
|
-
|
371
|
+
let responseStream = res;
|
297
372
|
|
298
373
|
// return the last request in case of redirects
|
299
|
-
|
374
|
+
const lastRequest = res.req || req;
|
300
375
|
|
301
376
|
// if decompress disabled we should not decompress
|
302
377
|
if (config.decompress !== false) {
|
@@ -312,19 +387,48 @@ module.exports = function httpAdapter(config) {
|
|
312
387
|
case 'compress':
|
313
388
|
case 'deflate':
|
314
389
|
// add the unzipper to the body stream processing pipeline
|
315
|
-
|
390
|
+
streams.push(zlib.createUnzip());
|
316
391
|
|
317
392
|
// remove the content-encoding in order to not confuse downstream operations
|
318
393
|
delete res.headers['content-encoding'];
|
319
394
|
break;
|
395
|
+
case 'br':
|
396
|
+
if (isBrotliSupported) {
|
397
|
+
streams.push(zlib.createBrotliDecompress());
|
398
|
+
delete res.headers['content-encoding'];
|
399
|
+
}
|
320
400
|
}
|
321
401
|
}
|
322
402
|
|
323
|
-
|
403
|
+
if (onDownloadProgress) {
|
404
|
+
const responseLength = +res.headers['content-length'];
|
405
|
+
|
406
|
+
const transformStream = new AxiosTransformStream({
|
407
|
+
length: utils.toFiniteNumber(responseLength),
|
408
|
+
maxRate: utils.toFiniteNumber(maxDownloadRate)
|
409
|
+
});
|
410
|
+
|
411
|
+
onDownloadProgress && transformStream.on('progress', progress => {
|
412
|
+
onDownloadProgress(Object.assign(progress, {
|
413
|
+
download: true
|
414
|
+
}));
|
415
|
+
});
|
416
|
+
|
417
|
+
streams.push(transformStream);
|
418
|
+
}
|
419
|
+
|
420
|
+
responseStream = streams.length > 1 ? stream.pipeline(streams, utils.noop) : streams[0];
|
421
|
+
|
422
|
+
const offListeners = stream.finished(responseStream, () => {
|
423
|
+
offListeners();
|
424
|
+
onFinished();
|
425
|
+
});
|
426
|
+
|
427
|
+
const response = {
|
324
428
|
status: res.statusCode,
|
325
429
|
statusText: res.statusMessage,
|
326
|
-
headers: res.headers,
|
327
|
-
config
|
430
|
+
headers: new AxiosHeaders(res.headers),
|
431
|
+
config,
|
328
432
|
request: lastRequest
|
329
433
|
};
|
330
434
|
|
@@ -332,8 +436,9 @@ module.exports = function httpAdapter(config) {
|
|
332
436
|
response.data = responseStream;
|
333
437
|
settle(resolve, reject, response);
|
334
438
|
} else {
|
335
|
-
|
336
|
-
|
439
|
+
const responseBuffer = [];
|
440
|
+
let totalResponseBytes = 0;
|
441
|
+
|
337
442
|
responseStream.on('data', function handleStreamData(chunk) {
|
338
443
|
responseBuffer.push(chunk);
|
339
444
|
totalResponseBytes += chunk.length;
|
@@ -352,23 +457,25 @@ module.exports = function httpAdapter(config) {
|
|
352
457
|
if (rejected) {
|
353
458
|
return;
|
354
459
|
}
|
355
|
-
|
356
|
-
|
460
|
+
|
461
|
+
const err = new AxiosError(
|
357
462
|
'maxContentLength size of ' + config.maxContentLength + ' exceeded',
|
358
463
|
AxiosError.ERR_BAD_RESPONSE,
|
359
464
|
config,
|
360
465
|
lastRequest
|
361
|
-
)
|
466
|
+
);
|
467
|
+
responseStream.destroy(err);
|
468
|
+
reject(err);
|
362
469
|
});
|
363
470
|
|
364
471
|
responseStream.on('error', function handleStreamError(err) {
|
365
|
-
if (req.
|
472
|
+
if (req.destroyed) return;
|
366
473
|
reject(AxiosError.from(err, null, config, lastRequest));
|
367
474
|
});
|
368
475
|
|
369
476
|
responseStream.on('end', function handleStreamEnd() {
|
370
477
|
try {
|
371
|
-
|
478
|
+
let responseData = responseBuffer.length === 1 ? responseBuffer[0] : Buffer.concat(responseBuffer);
|
372
479
|
if (responseType !== 'arraybuffer') {
|
373
480
|
responseData = responseData.toString(responseEncoding);
|
374
481
|
if (!responseEncoding || responseEncoding === 'utf8') {
|
@@ -382,6 +489,18 @@ module.exports = function httpAdapter(config) {
|
|
382
489
|
settle(resolve, reject, response);
|
383
490
|
});
|
384
491
|
}
|
492
|
+
|
493
|
+
emitter.once('abort', err => {
|
494
|
+
if (!responseStream.destroyed) {
|
495
|
+
responseStream.emit('error', err);
|
496
|
+
responseStream.destroy();
|
497
|
+
}
|
498
|
+
});
|
499
|
+
});
|
500
|
+
|
501
|
+
emitter.once('abort', err => {
|
502
|
+
reject(err);
|
503
|
+
req.destroy(err);
|
385
504
|
});
|
386
505
|
|
387
506
|
// Handle errors
|
@@ -400,7 +519,7 @@ module.exports = function httpAdapter(config) {
|
|
400
519
|
// Handle request timeout
|
401
520
|
if (config.timeout) {
|
402
521
|
// This is forcing a int timeout to avoid problems if the `req` interface doesn't handle other types.
|
403
|
-
|
522
|
+
const timeout = parseInt(config.timeout, 10);
|
404
523
|
|
405
524
|
if (isNaN(timeout)) {
|
406
525
|
reject(new AxiosError(
|
@@ -419,9 +538,9 @@ module.exports = function httpAdapter(config) {
|
|
419
538
|
// And then these socket which be hang up will devouring CPU little by little.
|
420
539
|
// ClientRequest.setTimeout will be fired on the specify milliseconds, and can make sure that abort() will be fired after connect.
|
421
540
|
req.setTimeout(timeout, function handleRequestTimeout() {
|
422
|
-
|
423
|
-
|
424
|
-
|
541
|
+
if (isDone) return;
|
542
|
+
let timeoutErrorMessage = config.timeout ? 'timeout of ' + config.timeout + 'ms exceeded' : 'timeout exceeded';
|
543
|
+
const transitional = config.transitional || transitionalDefaults;
|
425
544
|
if (config.timeoutErrorMessage) {
|
426
545
|
timeoutErrorMessage = config.timeoutErrorMessage;
|
427
546
|
}
|
@@ -431,33 +550,34 @@ module.exports = function httpAdapter(config) {
|
|
431
550
|
config,
|
432
551
|
req
|
433
552
|
));
|
553
|
+
abort();
|
434
554
|
});
|
435
555
|
}
|
436
556
|
|
437
|
-
if (config.cancelToken || config.signal) {
|
438
|
-
// Handle cancellation
|
439
|
-
// eslint-disable-next-line func-names
|
440
|
-
onCanceled = function(cancel) {
|
441
|
-
if (req.aborted) return;
|
442
557
|
|
443
|
-
|
444
|
-
|
445
|
-
|
558
|
+
// Send the request
|
559
|
+
if (utils.isStream(data)) {
|
560
|
+
let ended = false;
|
561
|
+
let errored = false;
|
446
562
|
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
}
|
451
|
-
}
|
563
|
+
data.on('end', () => {
|
564
|
+
ended = true;
|
565
|
+
});
|
452
566
|
|
567
|
+
data.once('error', err => {
|
568
|
+
errored = true;
|
569
|
+
req.destroy(err);
|
570
|
+
});
|
453
571
|
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
})
|
572
|
+
data.on('close', () => {
|
573
|
+
if (!ended && !errored) {
|
574
|
+
abort(new CanceledError('Request stream has been aborted', config, req));
|
575
|
+
}
|
576
|
+
});
|
577
|
+
|
578
|
+
data.pipe(req);
|
459
579
|
} else {
|
460
580
|
req.end(data);
|
461
581
|
}
|
462
582
|
});
|
463
|
-
}
|
583
|
+
}
|
@@ -0,0 +1,33 @@
|
|
1
|
+
import utils from '../utils.js';
|
2
|
+
import httpAdapter from './http.js';
|
3
|
+
import xhrAdapter from './xhr.js';
|
4
|
+
|
5
|
+
const adapters = {
|
6
|
+
http: httpAdapter,
|
7
|
+
xhr: xhrAdapter
|
8
|
+
}
|
9
|
+
|
10
|
+
export default {
|
11
|
+
getAdapter: (nameOrAdapter) => {
|
12
|
+
if(utils.isString(nameOrAdapter)){
|
13
|
+
const adapter = adapters[nameOrAdapter];
|
14
|
+
|
15
|
+
if (!nameOrAdapter) {
|
16
|
+
throw Error(
|
17
|
+
utils.hasOwnProp(nameOrAdapter) ?
|
18
|
+
`Adapter '${nameOrAdapter}' is not available in the build` :
|
19
|
+
`Can not resolve adapter '${nameOrAdapter}'`
|
20
|
+
);
|
21
|
+
}
|
22
|
+
|
23
|
+
return adapter
|
24
|
+
}
|
25
|
+
|
26
|
+
if (!utils.isFunction(nameOrAdapter)) {
|
27
|
+
throw new TypeError('adapter is not a function');
|
28
|
+
}
|
29
|
+
|
30
|
+
return nameOrAdapter;
|
31
|
+
},
|
32
|
+
adapters
|
33
|
+
}
|