axios 0.31.0 → 0.32.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +38 -0
- package/CHANGELOG.md +10 -0
- package/CLAUDE.md +1 -0
- package/README.md +46 -7
- package/UPGRADE_GUIDE.md +2 -2
- package/dist/axios.js +328 -93
- 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 +328 -93
- package/dist/esm/axios.js.map +1 -1
- package/dist/esm/axios.min.js +1 -1
- package/dist/esm/axios.min.js.map +1 -1
- package/index.d.ts +4 -0
- package/lib/adapters/http.js +354 -69
- package/lib/adapters/xhr.js +106 -32
- package/lib/core/AxiosError.js +81 -5
- package/lib/core/dispatchRequest.js +10 -5
- package/lib/core/mergeConfig.js +21 -10
- package/lib/defaults/index.js +9 -3
- package/lib/env/data.js +1 -1
- package/lib/helpers/AxiosURLSearchParams.js +20 -12
- package/lib/helpers/cookies.js +15 -2
- package/lib/helpers/defaultRedactKeys.js +3 -0
- package/lib/helpers/shouldBypassProxy.js +55 -1
- package/lib/helpers/toFormData.js +14 -3
- package/lib/utils.js +51 -20
- package/package.json +2 -2
package/index.d.ts
CHANGED
|
@@ -154,11 +154,14 @@ export interface AxiosRequestConfig<D = any> {
|
|
|
154
154
|
onUploadProgress?: (progressEvent: ProgressEvent) => void;
|
|
155
155
|
onDownloadProgress?: (progressEvent: ProgressEvent) => void;
|
|
156
156
|
maxContentLength?: number;
|
|
157
|
+
formDataHeaderPolicy?: 'legacy' | 'content-only';
|
|
158
|
+
redact?: string[];
|
|
157
159
|
validateStatus?: ((status: number) => boolean) | null;
|
|
158
160
|
maxBodyLength?: number;
|
|
159
161
|
maxRedirects?: number;
|
|
160
162
|
beforeRedirect?: (options: Record<string, any>, responseDetails: {headers: Record<string, string>}) => void;
|
|
161
163
|
socketPath?: string | null;
|
|
164
|
+
allowedSocketPaths?: string | string[] | null;
|
|
162
165
|
httpAgent?: any;
|
|
163
166
|
httpsAgent?: any;
|
|
164
167
|
proxy?: AxiosProxyConfig | false;
|
|
@@ -231,6 +234,7 @@ export class AxiosError<T = unknown, D = any> extends Error {
|
|
|
231
234
|
static readonly ERR_BAD_REQUEST = "ERR_BAD_REQUEST";
|
|
232
235
|
static readonly ERR_NOT_SUPPORT = "ERR_NOT_SUPPORT";
|
|
233
236
|
static readonly ERR_INVALID_URL = "ERR_INVALID_URL";
|
|
237
|
+
static readonly ERR_FORM_DATA_DEPTH_EXCEEDED = "ERR_FORM_DATA_DEPTH_EXCEEDED";
|
|
234
238
|
static readonly ERR_CANCELED = "ERR_CANCELED";
|
|
235
239
|
static readonly ECONNABORTED = "ECONNABORTED";
|
|
236
240
|
static readonly ETIMEDOUT = "ETIMEDOUT";
|
package/lib/adapters/http.js
CHANGED
|
@@ -10,6 +10,7 @@ var https = require('https');
|
|
|
10
10
|
var httpFollow = require('follow-redirects/http');
|
|
11
11
|
var httpsFollow = require('follow-redirects/https');
|
|
12
12
|
var url = require('url');
|
|
13
|
+
var path = require('path');
|
|
13
14
|
var zlib = require('zlib');
|
|
14
15
|
var VERSION = require('./../env/data').version;
|
|
15
16
|
var transitionalDefaults = require('../defaults/transitional');
|
|
@@ -36,6 +37,94 @@ function dispatchBeforeRedirect(options) {
|
|
|
36
37
|
}
|
|
37
38
|
}
|
|
38
39
|
|
|
40
|
+
function removeProxyAuthorization(headers) {
|
|
41
|
+
Object.keys(headers).forEach(function removeHeader(header) {
|
|
42
|
+
if (header.toLowerCase() === 'proxy-authorization') {
|
|
43
|
+
delete headers[header];
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function normalizeSocketPath(socketPath) {
|
|
49
|
+
if (/^\\\\[.?]\\pipe\\/i.test(socketPath)) {
|
|
50
|
+
return socketPath;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return path.resolve(socketPath);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function getAllowedSocketPaths(config) {
|
|
57
|
+
var allowedSocketPaths = config.allowedSocketPaths;
|
|
58
|
+
|
|
59
|
+
if (
|
|
60
|
+
allowedSocketPaths === null ||
|
|
61
|
+
typeof allowedSocketPaths === 'undefined'
|
|
62
|
+
) {
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (utils.isString(allowedSocketPaths)) {
|
|
67
|
+
return [allowedSocketPaths];
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (utils.isArray(allowedSocketPaths)) {
|
|
71
|
+
for (var i = 0; i < allowedSocketPaths.length; i++) {
|
|
72
|
+
if (!utils.isString(allowedSocketPaths[i])) {
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return allowedSocketPaths;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function checkSocketPath(config) {
|
|
84
|
+
var socketPath = config.socketPath;
|
|
85
|
+
|
|
86
|
+
if (!socketPath) {
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if (!utils.isString(socketPath)) {
|
|
91
|
+
return new AxiosError(
|
|
92
|
+
'config.socketPath must be a string',
|
|
93
|
+
AxiosError.ERR_BAD_OPTION_VALUE,
|
|
94
|
+
config
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
var allowedSocketPaths = getAllowedSocketPaths(config);
|
|
99
|
+
|
|
100
|
+
if (allowedSocketPaths === false) {
|
|
101
|
+
return new AxiosError(
|
|
102
|
+
'config.allowedSocketPaths must be a string, an array of strings, or null',
|
|
103
|
+
AxiosError.ERR_BAD_OPTION_VALUE,
|
|
104
|
+
config
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if (allowedSocketPaths) {
|
|
109
|
+
var normalizedSocketPath = normalizeSocketPath(socketPath);
|
|
110
|
+
var allowed = allowedSocketPaths.some(
|
|
111
|
+
function isAllowed(allowedSocketPath) {
|
|
112
|
+
return normalizeSocketPath(allowedSocketPath) === normalizedSocketPath;
|
|
113
|
+
}
|
|
114
|
+
);
|
|
115
|
+
|
|
116
|
+
if (!allowed) {
|
|
117
|
+
return new AxiosError(
|
|
118
|
+
'config.socketPath is not allowed by config.allowedSocketPaths',
|
|
119
|
+
AxiosError.ERR_BAD_OPTION_VALUE,
|
|
120
|
+
config
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return null;
|
|
126
|
+
}
|
|
127
|
+
|
|
39
128
|
/**
|
|
40
129
|
*
|
|
41
130
|
* @param {http.ClientRequestArgs} options
|
|
@@ -54,20 +143,37 @@ function setProxy(options, configProxy, location) {
|
|
|
54
143
|
}
|
|
55
144
|
}
|
|
56
145
|
}
|
|
146
|
+
if (!proxy) {
|
|
147
|
+
removeProxyAuthorization(options.headers);
|
|
148
|
+
}
|
|
57
149
|
if (proxy) {
|
|
58
150
|
// Basic proxy authorization
|
|
59
|
-
|
|
151
|
+
var proxyAuth = utils.hasOwnProperty(proxy, 'auth')
|
|
152
|
+
? proxy.auth
|
|
153
|
+
: undefined;
|
|
154
|
+
if (proxyAuth) {
|
|
60
155
|
// Support proxy auth object form
|
|
61
|
-
if (
|
|
62
|
-
|
|
156
|
+
if (utils.isObject(proxyAuth)) {
|
|
157
|
+
var proxyUsername = utils.hasOwnProperty(proxyAuth, 'username')
|
|
158
|
+
? proxyAuth.username
|
|
159
|
+
: '';
|
|
160
|
+
var proxyPassword = utils.hasOwnProperty(proxyAuth, 'password')
|
|
161
|
+
? proxyAuth.password
|
|
162
|
+
: '';
|
|
163
|
+
proxyAuth =
|
|
164
|
+
proxyUsername || proxyPassword
|
|
165
|
+
? proxyUsername + ':' + proxyPassword
|
|
166
|
+
: undefined;
|
|
167
|
+
}
|
|
168
|
+
if (proxyAuth) {
|
|
169
|
+
var base64 = Buffer.from(proxyAuth, 'utf8').toString('base64');
|
|
170
|
+
removeProxyAuthorization(options.headers);
|
|
171
|
+
options.headers['Proxy-Authorization'] = 'Basic ' + base64;
|
|
63
172
|
}
|
|
64
|
-
var base64 = Buffer
|
|
65
|
-
.from(proxy.auth, 'utf8')
|
|
66
|
-
.toString('base64');
|
|
67
|
-
options.headers['Proxy-Authorization'] = 'Basic ' + base64;
|
|
68
173
|
}
|
|
69
174
|
|
|
70
|
-
options.headers.host =
|
|
175
|
+
options.headers.host =
|
|
176
|
+
options.hostname + (options.port ? ':' + options.port : '');
|
|
71
177
|
options.hostname = proxy.host;
|
|
72
178
|
options.host = proxy.host;
|
|
73
179
|
options.port = proxy.port;
|
|
@@ -86,7 +192,10 @@ function setProxy(options, configProxy, location) {
|
|
|
86
192
|
|
|
87
193
|
/*eslint consistent-return:0*/
|
|
88
194
|
module.exports = function httpAdapter(config) {
|
|
89
|
-
return new Promise(function dispatchHttpRequest(
|
|
195
|
+
return new Promise(function dispatchHttpRequest(
|
|
196
|
+
resolvePromise,
|
|
197
|
+
rejectPromise
|
|
198
|
+
) {
|
|
90
199
|
var onCanceled;
|
|
91
200
|
function done() {
|
|
92
201
|
if (config.cancelToken) {
|
|
@@ -113,7 +222,11 @@ module.exports = function httpAdapter(config) {
|
|
|
113
222
|
var method = config.method.toUpperCase();
|
|
114
223
|
|
|
115
224
|
// Parse url
|
|
116
|
-
var fullPath = buildFullPath(
|
|
225
|
+
var fullPath = buildFullPath(
|
|
226
|
+
config.baseURL,
|
|
227
|
+
config.url,
|
|
228
|
+
config.allowAbsoluteUrls
|
|
229
|
+
);
|
|
117
230
|
var parsed = url.parse(fullPath);
|
|
118
231
|
var protocol = parsed.protocol || supportedProtocols[0];
|
|
119
232
|
|
|
@@ -125,11 +238,15 @@ module.exports = function httpAdapter(config) {
|
|
|
125
238
|
var estimated = estimateDataURLDecodedBytes(dataUrl);
|
|
126
239
|
|
|
127
240
|
if (estimated > config.maxContentLength) {
|
|
128
|
-
return reject(
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
241
|
+
return reject(
|
|
242
|
+
new AxiosError(
|
|
243
|
+
'maxContentLength size of ' +
|
|
244
|
+
config.maxContentLength +
|
|
245
|
+
' exceeded',
|
|
246
|
+
AxiosError.ERR_BAD_RESPONSE,
|
|
247
|
+
config
|
|
248
|
+
)
|
|
249
|
+
);
|
|
133
250
|
}
|
|
134
251
|
}
|
|
135
252
|
|
|
@@ -145,8 +262,11 @@ module.exports = function httpAdapter(config) {
|
|
|
145
262
|
}
|
|
146
263
|
|
|
147
264
|
try {
|
|
265
|
+
var envOption = utils.hasOwnProperty(config, 'env')
|
|
266
|
+
? config.env
|
|
267
|
+
: undefined;
|
|
148
268
|
convertedData = fromDataURI(config.url, responseType === 'blob', {
|
|
149
|
-
Blob:
|
|
269
|
+
Blob: envOption && envOption.Blob
|
|
150
270
|
});
|
|
151
271
|
} catch (err) {
|
|
152
272
|
throw AxiosError.from(err, AxiosError.ERR_BAD_REQUEST, config);
|
|
@@ -172,11 +292,13 @@ module.exports = function httpAdapter(config) {
|
|
|
172
292
|
}
|
|
173
293
|
|
|
174
294
|
if (supportedProtocols.indexOf(protocol) === -1) {
|
|
175
|
-
return reject(
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
295
|
+
return reject(
|
|
296
|
+
new AxiosError(
|
|
297
|
+
'Unsupported protocol ' + protocol,
|
|
298
|
+
AxiosError.ERR_BAD_REQUEST,
|
|
299
|
+
config
|
|
300
|
+
)
|
|
301
|
+
);
|
|
180
302
|
}
|
|
181
303
|
|
|
182
304
|
var headers = config.headers;
|
|
@@ -200,8 +322,22 @@ module.exports = function httpAdapter(config) {
|
|
|
200
322
|
}
|
|
201
323
|
|
|
202
324
|
// support for https://www.npmjs.com/package/form-data api
|
|
203
|
-
if (
|
|
204
|
-
|
|
325
|
+
if (
|
|
326
|
+
utils.isFormData(data) &&
|
|
327
|
+
utils.isFunction(data.getHeaders) &&
|
|
328
|
+
data.getHeaders !== Object.prototype.getHeaders
|
|
329
|
+
) {
|
|
330
|
+
var formHeaders = data.getHeaders();
|
|
331
|
+
if (config.formDataHeaderPolicy === 'content-only') {
|
|
332
|
+
Object.keys(formHeaders).forEach(function copyContentHeader(name) {
|
|
333
|
+
var lowerName = name.toLowerCase();
|
|
334
|
+
if (lowerName === 'content-type' || lowerName === 'content-length') {
|
|
335
|
+
headers[name] = formHeaders[name];
|
|
336
|
+
}
|
|
337
|
+
});
|
|
338
|
+
} else {
|
|
339
|
+
Object.assign(headers, formHeaders);
|
|
340
|
+
}
|
|
205
341
|
} else if (data && !utils.isStream(data)) {
|
|
206
342
|
if (Buffer.isBuffer(data)) {
|
|
207
343
|
// Nothing to do...
|
|
@@ -210,19 +346,23 @@ module.exports = function httpAdapter(config) {
|
|
|
210
346
|
} else if (utils.isString(data)) {
|
|
211
347
|
data = Buffer.from(data, 'utf-8');
|
|
212
348
|
} else {
|
|
213
|
-
return reject(
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
349
|
+
return reject(
|
|
350
|
+
new AxiosError(
|
|
351
|
+
'Data after transformation must be a string, an ArrayBuffer, a Buffer, or a Stream',
|
|
352
|
+
AxiosError.ERR_BAD_REQUEST,
|
|
353
|
+
config
|
|
354
|
+
)
|
|
355
|
+
);
|
|
218
356
|
}
|
|
219
357
|
|
|
220
358
|
if (config.maxBodyLength > -1 && data.length > config.maxBodyLength) {
|
|
221
|
-
return reject(
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
359
|
+
return reject(
|
|
360
|
+
new AxiosError(
|
|
361
|
+
'Request body larger than maxBodyLength limit',
|
|
362
|
+
AxiosError.ERR_BAD_REQUEST,
|
|
363
|
+
config
|
|
364
|
+
)
|
|
365
|
+
);
|
|
226
366
|
}
|
|
227
367
|
|
|
228
368
|
// Add Content-Length header if data exists
|
|
@@ -251,7 +391,10 @@ module.exports = function httpAdapter(config) {
|
|
|
251
391
|
}
|
|
252
392
|
|
|
253
393
|
try {
|
|
254
|
-
buildURL(parsed.path, config.params, config.paramsSerializer).replace(
|
|
394
|
+
buildURL(parsed.path, config.params, config.paramsSerializer).replace(
|
|
395
|
+
/^\?/,
|
|
396
|
+
''
|
|
397
|
+
);
|
|
255
398
|
} catch (err) {
|
|
256
399
|
var customErr = new Error(err.message);
|
|
257
400
|
customErr.config = config;
|
|
@@ -261,7 +404,11 @@ module.exports = function httpAdapter(config) {
|
|
|
261
404
|
}
|
|
262
405
|
|
|
263
406
|
var options = {
|
|
264
|
-
path: buildURL(
|
|
407
|
+
path: buildURL(
|
|
408
|
+
parsed.path,
|
|
409
|
+
config.params,
|
|
410
|
+
config.paramsSerializer
|
|
411
|
+
).replace(/^\?/, ''),
|
|
265
412
|
method: method,
|
|
266
413
|
headers: headers,
|
|
267
414
|
agents: { http: config.httpAgent, https: config.httpsAgent },
|
|
@@ -271,18 +418,27 @@ module.exports = function httpAdapter(config) {
|
|
|
271
418
|
beforeRedirects: {}
|
|
272
419
|
};
|
|
273
420
|
|
|
421
|
+
var socketPathError = checkSocketPath(config);
|
|
422
|
+
if (socketPathError) {
|
|
423
|
+
return reject(socketPathError);
|
|
424
|
+
}
|
|
425
|
+
|
|
274
426
|
if (config.socketPath) {
|
|
275
427
|
options.socketPath = config.socketPath;
|
|
276
428
|
} else {
|
|
277
429
|
options.hostname = parsed.hostname;
|
|
278
430
|
options.port = parsed.port;
|
|
279
|
-
setProxy(
|
|
431
|
+
setProxy(
|
|
432
|
+
options,
|
|
433
|
+
config.proxy,
|
|
434
|
+
protocol + '//' + parsed.host + options.path
|
|
435
|
+
);
|
|
280
436
|
}
|
|
281
437
|
|
|
282
438
|
var transport;
|
|
283
439
|
var isHttpsRequest = isHttps.test(options.protocol);
|
|
284
440
|
options.agent = isHttpsRequest ? config.httpsAgent : config.httpAgent;
|
|
285
|
-
if (config.transport) {
|
|
441
|
+
if (utils.hasOwnProperty(config, 'transport') && config.transport) {
|
|
286
442
|
transport = config.transport;
|
|
287
443
|
} else if (config.maxRedirects === 0) {
|
|
288
444
|
transport = isHttpsRequest ? https : http;
|
|
@@ -348,8 +504,51 @@ module.exports = function httpAdapter(config) {
|
|
|
348
504
|
};
|
|
349
505
|
|
|
350
506
|
if (responseType === 'stream') {
|
|
351
|
-
|
|
352
|
-
|
|
507
|
+
// Enforce maxContentLength on streamed responses too.
|
|
508
|
+
// Previously the stream path bypassed the size guard because the check only
|
|
509
|
+
// ran on the buffering branch.
|
|
510
|
+
if (config.maxContentLength > -1) {
|
|
511
|
+
var maxContentLength = config.maxContentLength;
|
|
512
|
+
var streamedBytes = 0;
|
|
513
|
+
var limiter = new stream.Transform({
|
|
514
|
+
transform: function transformChunk(chunk, encoding, callback) {
|
|
515
|
+
streamedBytes += chunk.length;
|
|
516
|
+
if (streamedBytes > maxContentLength) {
|
|
517
|
+
callback(
|
|
518
|
+
new AxiosError(
|
|
519
|
+
'maxContentLength size of ' +
|
|
520
|
+
maxContentLength +
|
|
521
|
+
' exceeded',
|
|
522
|
+
AxiosError.ERR_BAD_RESPONSE,
|
|
523
|
+
config,
|
|
524
|
+
lastRequest
|
|
525
|
+
)
|
|
526
|
+
);
|
|
527
|
+
return;
|
|
528
|
+
}
|
|
529
|
+
callback(null, chunk);
|
|
530
|
+
}
|
|
531
|
+
});
|
|
532
|
+
limiter.on('error', function handleLimiterError() {
|
|
533
|
+
rejected = true;
|
|
534
|
+
responseStream.destroy();
|
|
535
|
+
});
|
|
536
|
+
responseStream.on('error', function forwardError(err) {
|
|
537
|
+
limiter.destroy(err);
|
|
538
|
+
});
|
|
539
|
+
response.data = limiter;
|
|
540
|
+
settle(resolve, reject, response);
|
|
541
|
+
// Defer piping via setImmediate so the caller's `.then` (a microtask)
|
|
542
|
+
// has run and attached any `error`/`data` listeners before chunks flow
|
|
543
|
+
// through the transform. `process.nextTick` would drain before those
|
|
544
|
+
// microtasks and lose the error event.
|
|
545
|
+
setImmediate(function startPipe() {
|
|
546
|
+
responseStream.pipe(limiter);
|
|
547
|
+
});
|
|
548
|
+
} else {
|
|
549
|
+
response.data = responseStream;
|
|
550
|
+
settle(resolve, reject, response);
|
|
551
|
+
}
|
|
353
552
|
} else {
|
|
354
553
|
var responseBuffer = [];
|
|
355
554
|
var totalResponseBytes = 0;
|
|
@@ -358,12 +557,23 @@ module.exports = function httpAdapter(config) {
|
|
|
358
557
|
totalResponseBytes += chunk.length;
|
|
359
558
|
|
|
360
559
|
// make sure the content length is not over the maxContentLength if specified
|
|
361
|
-
if (
|
|
560
|
+
if (
|
|
561
|
+
config.maxContentLength > -1 &&
|
|
562
|
+
totalResponseBytes > config.maxContentLength
|
|
563
|
+
) {
|
|
362
564
|
// stream.destroy() emit aborted event before calling reject() on Node.js v16
|
|
363
565
|
rejected = true;
|
|
364
566
|
responseStream.destroy();
|
|
365
|
-
reject(
|
|
366
|
-
AxiosError
|
|
567
|
+
reject(
|
|
568
|
+
new AxiosError(
|
|
569
|
+
'maxContentLength size of ' +
|
|
570
|
+
config.maxContentLength +
|
|
571
|
+
' exceeded',
|
|
572
|
+
AxiosError.ERR_BAD_RESPONSE,
|
|
573
|
+
config,
|
|
574
|
+
lastRequest
|
|
575
|
+
)
|
|
576
|
+
);
|
|
367
577
|
}
|
|
368
578
|
});
|
|
369
579
|
|
|
@@ -372,12 +582,14 @@ module.exports = function httpAdapter(config) {
|
|
|
372
582
|
return;
|
|
373
583
|
}
|
|
374
584
|
responseStream.destroy();
|
|
375
|
-
reject(
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
585
|
+
reject(
|
|
586
|
+
new AxiosError(
|
|
587
|
+
'response stream aborted',
|
|
588
|
+
AxiosError.ECONNABORTED,
|
|
589
|
+
config,
|
|
590
|
+
lastRequest
|
|
591
|
+
)
|
|
592
|
+
);
|
|
381
593
|
});
|
|
382
594
|
|
|
383
595
|
responseStream.on('error', function handleStreamError(err) {
|
|
@@ -387,7 +599,10 @@ module.exports = function httpAdapter(config) {
|
|
|
387
599
|
|
|
388
600
|
responseStream.on('end', function handleStreamEnd() {
|
|
389
601
|
try {
|
|
390
|
-
var responseData =
|
|
602
|
+
var responseData =
|
|
603
|
+
responseBuffer.length === 1
|
|
604
|
+
? responseBuffer[0]
|
|
605
|
+
: Buffer.concat(responseBuffer);
|
|
391
606
|
if (responseType !== 'arraybuffer') {
|
|
392
607
|
responseData = responseData.toString(responseEncoding);
|
|
393
608
|
if (!responseEncoding || responseEncoding === 'utf8') {
|
|
@@ -396,7 +611,9 @@ module.exports = function httpAdapter(config) {
|
|
|
396
611
|
}
|
|
397
612
|
response.data = responseData;
|
|
398
613
|
} catch (err) {
|
|
399
|
-
reject(
|
|
614
|
+
reject(
|
|
615
|
+
AxiosError.from(err, null, config, response.request, response)
|
|
616
|
+
);
|
|
400
617
|
}
|
|
401
618
|
settle(resolve, reject, response);
|
|
402
619
|
});
|
|
@@ -418,16 +635,28 @@ module.exports = function httpAdapter(config) {
|
|
|
418
635
|
|
|
419
636
|
// Handle request timeout
|
|
420
637
|
if (config.timeout) {
|
|
421
|
-
//
|
|
422
|
-
|
|
638
|
+
// Force an int timeout so the `req` interface gets a clean number.
|
|
639
|
+
// The try/catch is required: merged config values have a null prototype,
|
|
640
|
+
// and parseInt on a null-prototype object throws "Cannot convert object
|
|
641
|
+
// to primitive value" because there is no inherited toString. Treating
|
|
642
|
+
// that as NaN routes to the same ERR_BAD_OPTION_VALUE rejection as any
|
|
643
|
+
// other unparsable value.
|
|
644
|
+
var timeout;
|
|
645
|
+
try {
|
|
646
|
+
timeout = parseInt(config.timeout, 10);
|
|
647
|
+
} catch (err) {
|
|
648
|
+
timeout = NaN;
|
|
649
|
+
}
|
|
423
650
|
|
|
424
651
|
if (isNaN(timeout)) {
|
|
425
|
-
reject(
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
652
|
+
reject(
|
|
653
|
+
new AxiosError(
|
|
654
|
+
'error trying to parse `config.timeout` to int',
|
|
655
|
+
AxiosError.ERR_BAD_OPTION_VALUE,
|
|
656
|
+
config,
|
|
657
|
+
req
|
|
658
|
+
)
|
|
659
|
+
);
|
|
431
660
|
|
|
432
661
|
return;
|
|
433
662
|
}
|
|
@@ -439,17 +668,23 @@ module.exports = function httpAdapter(config) {
|
|
|
439
668
|
// ClientRequest.setTimeout will be fired on the specify milliseconds, and can make sure that abort() will be fired after connect.
|
|
440
669
|
req.setTimeout(timeout, function handleRequestTimeout() {
|
|
441
670
|
req.abort();
|
|
442
|
-
var timeoutErrorMessage = config.timeout
|
|
671
|
+
var timeoutErrorMessage = config.timeout
|
|
672
|
+
? 'timeout of ' + config.timeout + 'ms exceeded'
|
|
673
|
+
: 'timeout exceeded';
|
|
443
674
|
var transitional = config.transitional || transitionalDefaults;
|
|
444
675
|
if (config.timeoutErrorMessage) {
|
|
445
676
|
timeoutErrorMessage = config.timeoutErrorMessage;
|
|
446
677
|
}
|
|
447
|
-
reject(
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
678
|
+
reject(
|
|
679
|
+
new AxiosError(
|
|
680
|
+
timeoutErrorMessage,
|
|
681
|
+
transitional.clarifyTimeoutError
|
|
682
|
+
? AxiosError.ETIMEDOUT
|
|
683
|
+
: AxiosError.ECONNABORTED,
|
|
684
|
+
config,
|
|
685
|
+
req
|
|
686
|
+
)
|
|
687
|
+
);
|
|
453
688
|
});
|
|
454
689
|
}
|
|
455
690
|
|
|
@@ -460,21 +695,71 @@ module.exports = function httpAdapter(config) {
|
|
|
460
695
|
if (req.aborted) return;
|
|
461
696
|
|
|
462
697
|
req.abort();
|
|
463
|
-
reject(
|
|
698
|
+
reject(
|
|
699
|
+
!cancel || cancel.type
|
|
700
|
+
? new CanceledError(null, config, req)
|
|
701
|
+
: cancel
|
|
702
|
+
);
|
|
464
703
|
};
|
|
465
704
|
|
|
466
705
|
config.cancelToken && config.cancelToken.subscribe(onCanceled);
|
|
467
706
|
if (config.signal) {
|
|
468
|
-
config.signal.aborted
|
|
707
|
+
config.signal.aborted
|
|
708
|
+
? onCanceled()
|
|
709
|
+
: config.signal.addEventListener('abort', onCanceled);
|
|
469
710
|
}
|
|
470
711
|
}
|
|
471
712
|
|
|
472
|
-
|
|
473
713
|
// Send the request
|
|
474
714
|
if (utils.isStream(data)) {
|
|
475
715
|
data.on('error', function handleStreamError(err) {
|
|
476
716
|
reject(AxiosError.from(err, config, null, req));
|
|
477
|
-
})
|
|
717
|
+
});
|
|
718
|
+
|
|
719
|
+
// follow-redirects enforces options.maxBodyLength for stream uploads, but the
|
|
720
|
+
// native http/https transport (used when maxRedirects === 0) does not.
|
|
721
|
+
// Count bytes ourselves so the limit is always honored.
|
|
722
|
+
var nativeTransport = transport === http || transport === https;
|
|
723
|
+
if (nativeTransport && config.maxBodyLength > -1) {
|
|
724
|
+
var maxBodyLength = config.maxBodyLength;
|
|
725
|
+
var uploadedBytes = 0;
|
|
726
|
+
var bodyLimiter = new stream.Transform({
|
|
727
|
+
transform: function transformChunk(chunk, encoding, callback) {
|
|
728
|
+
uploadedBytes += chunk.length;
|
|
729
|
+
if (uploadedBytes > maxBodyLength) {
|
|
730
|
+
callback(
|
|
731
|
+
new AxiosError(
|
|
732
|
+
'Request body larger than maxBodyLength limit',
|
|
733
|
+
AxiosError.ERR_BAD_REQUEST,
|
|
734
|
+
config,
|
|
735
|
+
req
|
|
736
|
+
)
|
|
737
|
+
);
|
|
738
|
+
return;
|
|
739
|
+
}
|
|
740
|
+
callback(null, chunk);
|
|
741
|
+
}
|
|
742
|
+
});
|
|
743
|
+
bodyLimiter.on('error', function handleLimiterError(err) {
|
|
744
|
+
if (rejected) return;
|
|
745
|
+
rejected = true;
|
|
746
|
+
try {
|
|
747
|
+
data.unpipe(bodyLimiter);
|
|
748
|
+
} catch (e) {
|
|
749
|
+
/* noop */
|
|
750
|
+
}
|
|
751
|
+
try {
|
|
752
|
+
bodyLimiter.unpipe(req);
|
|
753
|
+
} catch (e) {
|
|
754
|
+
/* noop */
|
|
755
|
+
}
|
|
756
|
+
req.destroy();
|
|
757
|
+
reject(err);
|
|
758
|
+
});
|
|
759
|
+
data.pipe(bodyLimiter).pipe(req);
|
|
760
|
+
} else {
|
|
761
|
+
data.pipe(req);
|
|
762
|
+
}
|
|
478
763
|
} else {
|
|
479
764
|
req.end(data);
|
|
480
765
|
}
|