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/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";
@@ -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
- if (proxy.auth) {
151
+ var proxyAuth = utils.hasOwnProperty(proxy, 'auth')
152
+ ? proxy.auth
153
+ : undefined;
154
+ if (proxyAuth) {
60
155
  // Support proxy auth object form
61
- if (proxy.auth.username || proxy.auth.password) {
62
- proxy.auth = (proxy.auth.username || '') + ':' + (proxy.auth.password || '');
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 = options.hostname + (options.port ? ':' + options.port : '');
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(resolvePromise, rejectPromise) {
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(config.baseURL, config.url, config.allowAbsoluteUrls);
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(new AxiosError(
129
- 'maxContentLength size of ' + config.maxContentLength + ' exceeded',
130
- AxiosError.ERR_BAD_RESPONSE,
131
- config
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: config.env && config.env.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(new AxiosError(
176
- 'Unsupported protocol ' + protocol,
177
- AxiosError.ERR_BAD_REQUEST,
178
- config
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 (utils.isFormData(data) && utils.isFunction(data.getHeaders)) {
204
- Object.assign(headers, data.getHeaders());
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(new AxiosError(
214
- 'Data after transformation must be a string, an ArrayBuffer, a Buffer, or a Stream',
215
- AxiosError.ERR_BAD_REQUEST,
216
- config
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(new AxiosError(
222
- 'Request body larger than maxBodyLength limit',
223
- AxiosError.ERR_BAD_REQUEST,
224
- config
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(parsed.path, config.params, config.paramsSerializer).replace(/^\?/, ''),
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(options, config.proxy, protocol + '//' + parsed.host + options.path);
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
- response.data = responseStream;
352
- settle(resolve, reject, response);
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 (config.maxContentLength > -1 && totalResponseBytes > config.maxContentLength) {
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(new AxiosError('maxContentLength size of ' + config.maxContentLength + ' exceeded',
366
- AxiosError.ERR_BAD_RESPONSE, config, lastRequest));
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(new AxiosError(
376
- 'response stream aborted',
377
- AxiosError.ECONNABORTED,
378
- config,
379
- lastRequest
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 = responseBuffer.length === 1 ? responseBuffer[0] : Buffer.concat(responseBuffer);
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(AxiosError.from(err, null, config, response.request, response));
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
- // This is forcing a int timeout to avoid problems if the `req` interface doesn't handle other types.
422
- var timeout = parseInt(config.timeout, 10);
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(new AxiosError(
426
- 'error trying to parse `config.timeout` to int',
427
- AxiosError.ERR_BAD_OPTION_VALUE,
428
- config,
429
- req
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 ? 'timeout of ' + config.timeout + 'ms exceeded' : 'timeout exceeded';
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(new AxiosError(
448
- timeoutErrorMessage,
449
- transitional.clarifyTimeoutError ? AxiosError.ETIMEDOUT : AxiosError.ECONNABORTED,
450
- config,
451
- req
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(!cancel || cancel.type ? new CanceledError(null, config, req) : cancel);
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 ? onCanceled() : config.signal.addEventListener('abort', onCanceled);
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
- }).pipe(req);
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
  }