@e-mc/request 0.10.1 → 0.10.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.js CHANGED
@@ -11,13 +11,13 @@ const dns = require("dns");
11
11
  const net = require("net");
12
12
  const stream = require("stream");
13
13
  const zlib = require("zlib");
14
- const qs = require("querystring");
14
+ const qs = require("node:querystring");
15
15
  const combined = require("combined-stream");
16
16
  const pm = require("picomatch");
17
17
  const yaml = require("js-yaml");
18
18
  const which = require("which");
19
- const module_1 = require("@e-mc/module");
20
19
  const types_1 = require("@e-mc/types");
20
+ const module_1 = require("@e-mc/module");
21
21
  const util_1 = require("@e-mc/request/util");
22
22
  const host_1 = require("@e-mc/request/http/host");
23
23
  const kSession = Symbol('session');
@@ -96,7 +96,7 @@ function getBaseHeaders(uri, headers) {
96
96
  let result;
97
97
  for (const pathname in headers) {
98
98
  if (pathname === uri || uri.startsWith(pathname + '/')) {
99
- (result || (result = [])).push([pathname, headers[pathname]]);
99
+ (result ||= []).push([pathname, headers[pathname]]);
100
100
  }
101
101
  }
102
102
  if (result) {
@@ -107,7 +107,7 @@ function getBaseHeaders(uri, headers) {
107
107
  }
108
108
  }
109
109
  function setDnsCache(hostname, value, expires) {
110
- expires ?? (expires = DNS.EXPIRES);
110
+ expires ??= DNS.EXPIRES;
111
111
  if (expires > 0 && !DNS.CACHE[hostname]) {
112
112
  DNS.CACHE[hostname] = value;
113
113
  if (expires !== Infinity) {
@@ -331,8 +331,8 @@ function decompressEncoding(value, chunkSize) {
331
331
  break;
332
332
  }
333
333
  }
334
- function abortHeaders(href, request, options) {
335
- const reason = (0, types_1.errorValue)("Aborted by client", href);
334
+ function abortHeaders(href, request, options, statusCode = '') {
335
+ const reason = (0, types_1.errorMessage)(statusCode, "Aborted by client", href);
336
336
  const outAbort = options.outAbort;
337
337
  if (outAbort) {
338
338
  outAbort.abort(reason);
@@ -413,12 +413,13 @@ class Fetch {
413
413
  }
414
414
  async start() {
415
415
  return new Promise((resolve, reject) => {
416
- this.promise = [resolve, reject];
416
+ this.resolve = resolve;
417
+ this.reject = reject;
417
418
  this.init();
418
419
  });
419
420
  }
420
421
  init() {
421
- if (this.retries > 0) {
422
+ if (this.aborted || this.retries > 0) {
422
423
  this.cleanup();
423
424
  this.aborted = false;
424
425
  }
@@ -445,7 +446,7 @@ class Fetch {
445
446
  statusCode === 404 ||
446
447
  statusCode === 407 ||
447
448
  statusCode === 410) {
448
- this.rejectError(this.formatStatus(statusCode));
449
+ this.terminate(this.formatStatus(statusCode));
449
450
  }
450
451
  else if (this.isRetry(statusCode)) {
451
452
  this.retryResponse(statusCode, headers['retry-after']);
@@ -473,7 +474,7 @@ class Fetch {
473
474
  })
474
475
  .on('aborted', () => {
475
476
  this.aborted = true;
476
- this.rejectError((0, types_1.createAbortError)());
477
+ this.terminate((0, types_1.createAbortError)());
477
478
  })
478
479
  .on('error', async (err) => {
479
480
  if (this.aborted) {
@@ -514,13 +515,12 @@ class Fetch {
514
515
  this.retryResponse(statusCode, res.headers['retry-after']);
515
516
  }
516
517
  else {
517
- this.abortResponse();
518
- this.rejectError(this.formatStatus(statusCode));
518
+ this.terminate(this.formatStatus(statusCode));
519
519
  }
520
520
  })
521
521
  .on('abort', () => {
522
522
  this.aborted = true;
523
- this.rejectError((0, types_1.createAbortError)());
523
+ this.terminate((0, types_1.createAbortError)());
524
524
  })
525
525
  .on('error', err => {
526
526
  if (!this.aborted) {
@@ -532,12 +532,12 @@ class Fetch {
532
532
  if (this.aborted) {
533
533
  return;
534
534
  }
535
- this.abortResponse();
536
535
  if (++this.retries <= this.retryLimit) {
536
+ this.abortResponse();
537
537
  this.retryTimeout();
538
538
  }
539
539
  else {
540
- this.rejectError(this.formatStatus(408));
540
+ this.terminate(this.formatStatus(408));
541
541
  }
542
542
  });
543
543
  }
@@ -553,7 +553,7 @@ class Fetch {
553
553
  this.config.outStream = this.outStream;
554
554
  }
555
555
  catch (err) {
556
- this.rejectError(err);
556
+ this.terminate(err);
557
557
  }
558
558
  }
559
559
  else {
@@ -568,12 +568,6 @@ class Fetch {
568
568
  clearTimeout(this.timeout);
569
569
  }
570
570
  this.aborted = true;
571
- if (this.outAbort) {
572
- if (!this.client.aborted) {
573
- this.outAbort.abort();
574
- }
575
- this.downloading.delete(this.outAbort);
576
- }
577
571
  this.client.destroy();
578
572
  }
579
573
  retryDownload(downgrade, message) {
@@ -613,8 +607,7 @@ class Fetch {
613
607
  client.once('readable', () => {
614
608
  if (instance.readTimeout > 0) {
615
609
  this.timeout = setTimeout(() => {
616
- this.abortResponse();
617
- this.rejectError((0, types_1.errorValue)("Timeout was exceeded", this.uri.toString()));
610
+ this.terminate((0, types_1.errorValue)("Timeout was exceeded", this.uri.toString()));
618
611
  }, instance.readTimeout);
619
612
  }
620
613
  if (log) {
@@ -664,8 +657,7 @@ class Fetch {
664
657
  dataLength += Buffer.byteLength(chunk, encoding);
665
658
  }
666
659
  if (dataLength > maxBufferSize) {
667
- this.abortResponse();
668
- this.rejectError((0, types_1.errorValue)("Size limit was exceeded", this.uri.toString()));
660
+ this.terminate((0, types_1.errorValue)("Size limit was exceeded", this.uri.toString()));
669
661
  }
670
662
  }
671
663
  });
@@ -674,13 +666,7 @@ class Fetch {
674
666
  if (this.closed || this.aborted) {
675
667
  return;
676
668
  }
677
- if (this.timeout) {
678
- clearTimeout(this.timeout);
679
- }
680
- if (this.outAbort) {
681
- this.downloading.delete(this.outAbort);
682
- }
683
- this.closed = true;
669
+ this.close();
684
670
  const encoding = opts.encoding;
685
671
  let result, messageUnit, titleBgColor;
686
672
  if (buffer) {
@@ -743,7 +729,7 @@ class Fetch {
743
729
  parent.updateProgress("request", progressId, 0, contentLength);
744
730
  }
745
731
  if (enabled && instance.readExpect === 'always') {
746
- this.rejectError("No data received");
732
+ this.terminate("No data received");
747
733
  return;
748
734
  }
749
735
  result = encoding && !pipeline ? '' : null;
@@ -752,34 +738,34 @@ class Fetch {
752
738
  if (log) {
753
739
  instance.writeTimeProcess('HTTP' + config.httpVersion, config.statusMessage || this.uri.toString(), this.startTime, { type: 1024, queue: !!parent, titleBgColor, messageUnit, messageUnitMinWidth: 9, delayTime, bypassLog: LOG_STDOUT });
754
740
  }
755
- this.promise[0](result);
741
+ this.resolve(result);
756
742
  });
757
743
  config.host.success(this.httpVersion);
758
744
  }
759
745
  redirectResponse(statusCode, location) {
760
- this.abortResponse();
761
746
  if (location) {
762
- if (this.config.follow_redirect === false) {
763
- this.rejectError(this.formatStatus(statusCode, "Follow redirect was disabled"));
747
+ if (this.config.follow_redirect === false || this.config.followRedirect === false) {
748
+ this.terminate(this.formatStatus(statusCode, "Follow redirect was disabled"));
764
749
  }
765
750
  else if (++this.redirects <= this.redirectLimit) {
751
+ this.abortResponse();
766
752
  this.setConfig(Request.fromURL(this.config.url, location));
767
753
  this.init();
768
754
  }
769
755
  else {
770
- this.rejectError(this.formatStatus(statusCode, "Exceeded redirect limit"));
756
+ this.terminate(this.formatStatus(statusCode, "Exceeded redirect limit"));
771
757
  }
772
758
  }
773
759
  else {
774
- this.rejectError(this.formatStatus(statusCode, "Missing redirect location"));
760
+ this.terminate(this.formatStatus(statusCode, "Missing redirect location"));
775
761
  }
776
762
  }
777
763
  errorResponse(err) {
778
- this.abortResponse();
779
764
  if (Fetch.wasAborted(err)) {
780
- this.rejectError(err);
765
+ this.terminate(err);
781
766
  }
782
767
  else if ((0, util_1.checkRetryable)(err) && ++this.retries <= this.retryLimit) {
768
+ this.abortResponse();
783
769
  if (Fetch.isConnectionTimeout(err)) {
784
770
  this.retryTimeout();
785
771
  }
@@ -791,7 +777,7 @@ class Fetch {
791
777
  }
792
778
  else {
793
779
  this.config.host.error(this.httpVersion);
794
- this.rejectError(err);
780
+ this.terminate(err);
795
781
  }
796
782
  }
797
783
  retryResponse(statusCode, retryAfter) {
@@ -812,7 +798,7 @@ class Fetch {
812
798
  }, offset);
813
799
  }
814
800
  else {
815
- this.rejectError(this.formatStatus(statusCode));
801
+ this.terminate(this.formatStatus(statusCode));
816
802
  }
817
803
  return;
818
804
  }
@@ -834,17 +820,14 @@ class Fetch {
834
820
  this.sendWarning(this.formatRetry("HTTP connection timeout"));
835
821
  this.init();
836
822
  }
837
- rejectError(err) {
823
+ terminate(err) {
838
824
  if (this.timeout) {
839
825
  clearTimeout(this.timeout);
840
826
  }
841
827
  if (!this.closed) {
842
- this.closed = true;
843
828
  this.cleanup();
844
- this.promise[1](typeof err === 'string' ? new Error(err) : err);
845
- }
846
- if (this.outAbort) {
847
- this.downloading.delete(this.outAbort);
829
+ this.close();
830
+ this.reject(typeof err === 'string' ? new Error(err) : err);
848
831
  }
849
832
  }
850
833
  sendWarning(message) {
@@ -862,6 +845,19 @@ class Fetch {
862
845
  formatRetry(message) {
863
846
  return message + ` (${this.retries} / ${this.retryLimit})`;
864
847
  }
848
+ close() {
849
+ if (this.timeout) {
850
+ clearTimeout(this.timeout);
851
+ }
852
+ this.closed = true;
853
+ const outAbort = this.opts.outAbort;
854
+ if (outAbort) {
855
+ this.downloading.delete(outAbort);
856
+ if (this.aborted && !this.client.aborted && !this.client.destroyed) {
857
+ outAbort.abort();
858
+ }
859
+ }
860
+ }
865
861
  cleanup() {
866
862
  if ((0, types_1.isString)(this.pipeTo) && this.outStream) {
867
863
  (0, util_1.cleanupStream)(this.outStream, this.pipeTo);
@@ -1342,7 +1338,6 @@ class Request extends module_1 {
1342
1338
  const output = [];
1343
1339
  let count = 0;
1344
1340
  this[kConnectHttp].forEach((protocol, index) => {
1345
- var _p;
1346
1341
  const title = 'HTTP' + (index + 1);
1347
1342
  for (const origin in protocol) {
1348
1343
  const value = protocol[origin];
@@ -1352,7 +1347,7 @@ class Request extends module_1 {
1352
1347
  if (item[1] === title && Array.isArray(item[2]) && item[2][0].startsWith(origin)) {
1353
1348
  item[1] = '';
1354
1349
  item[2][0] = item[2][0].substring(origin.length);
1355
- (_p = item[4]).titleBgColor && (_p.titleBgColor = undefined);
1350
+ item[4].titleBgColor &&= undefined;
1356
1351
  item[4].titleJustify = 'right';
1357
1352
  args.push(item);
1358
1353
  log.splice(i--, 1);
@@ -1414,7 +1409,7 @@ class Request extends module_1 {
1414
1409
  if (config) {
1415
1410
  const { headers, httpVersion, ipVersion, readTimeout } = config;
1416
1411
  if ((0, types_1.isObject)(headers)) {
1417
- setOutgoingHeaders(this[kHeaders] || (this[kHeaders] = {}), headers);
1412
+ setOutgoingHeaders(this[kHeaders] ||= {}, headers);
1418
1413
  }
1419
1414
  if (httpVersion !== undefined) {
1420
1415
  this.httpVersion = httpVersion;
@@ -1504,7 +1499,6 @@ class Request extends module_1 {
1504
1499
  setDnsCache(hostname, this[kConnectDns][hostname] = [{ address, family }], timeout);
1505
1500
  }
1506
1501
  lookupDns(hostname) {
1507
- var _p;
1508
1502
  const resolved = this[kConnectDns][hostname] || DNS.CACHE[hostname];
1509
1503
  if (resolved) {
1510
1504
  return (...args) => {
@@ -1516,7 +1510,7 @@ class Request extends module_1 {
1516
1510
  }
1517
1511
  };
1518
1512
  }
1519
- const pending = (_p = this[kPendingDns])[hostname] || (_p[hostname] = []);
1513
+ const pending = this[kPendingDns][hostname] ||= [];
1520
1514
  return (value, options, callback) => {
1521
1515
  if (pending.push(callback) === 1) {
1522
1516
  let ipVersion = this.ipVersion;
@@ -1576,7 +1570,7 @@ class Request extends module_1 {
1576
1570
  globUrl = '*';
1577
1571
  }
1578
1572
  if ((0, types_1.isString)(globUrl) && typeof callback === 'function') {
1579
- const on = this[kStatusOn] || (this[kStatusOn] = new Map());
1573
+ const on = this[kStatusOn] ||= new Map();
1580
1574
  for (const item of !Array.isArray(code) ? [code] : code) {
1581
1575
  let status = on.get(item);
1582
1576
  if (!status) {
@@ -1592,7 +1586,7 @@ class Request extends module_1 {
1592
1586
  globUrl = '*';
1593
1587
  }
1594
1588
  if ((0, types_1.isString)(globUrl) && typeof callback === 'function') {
1595
- const on = this[kHeadersOn] || (this[kHeadersOn] = new Map());
1589
+ const on = this[kHeadersOn] ||= new Map();
1596
1590
  for (const item of !Array.isArray(name) ? [name] : name) {
1597
1591
  let headers = on.get(item);
1598
1592
  if (!headers) {
@@ -1613,13 +1607,14 @@ class Request extends module_1 {
1613
1607
  if (typeof uri === 'string' && module_1.isURL(uri)) {
1614
1608
  uri = new URL(uri);
1615
1609
  }
1616
- let pathname, headers, binOpts, silent;
1610
+ let pathname, headers, binOpts, signal, silent;
1617
1611
  if (options) {
1618
1612
  if (typeof options === 'string') {
1619
1613
  pathname = options;
1620
1614
  }
1621
1615
  else {
1622
- ({ pathname, headers, binOpts, silent } = options);
1616
+ ({ pathname, binOpts, signal, silent } = options);
1617
+ headers = (0, util_1.parseOutgoingHeaders)(options.headers);
1623
1618
  if ((0, types_1.isArray)(binOpts)) {
1624
1619
  let next = false;
1625
1620
  binOpts = binOpts.filter(opt => !((0, types_1.isString)(opt) && /^-[a-z].*$/i.test(opt.trim()))).map((opt) => {
@@ -1681,7 +1676,7 @@ class Request extends module_1 {
1681
1676
  if (!module_1.createDir(pathname)) {
1682
1677
  return Promise.reject((0, types_1.errorMessage)("aria2", "Path is not a directory", pathname));
1683
1678
  }
1684
- silent ?? (silent = this[kSingleton]);
1679
+ silent ??= this[kSingleton];
1685
1680
  return new Promise((resolve, reject) => {
1686
1681
  let protocol, origin, username, password;
1687
1682
  if (uri instanceof URL) {
@@ -1886,7 +1881,7 @@ class Request extends module_1 {
1886
1881
  if (match[3] === '100') {
1887
1882
  result.push(file);
1888
1883
  }
1889
- messageUnit || (messageUnit = match[2]);
1884
+ messageUnit ||= match[2];
1890
1885
  break;
1891
1886
  case 'INPR':
1892
1887
  if (ARIA2.ALWAYS_RESUME) {
@@ -1922,7 +1917,13 @@ class Request extends module_1 {
1922
1917
  }
1923
1918
  for (const item of ARIA2.PID_QUEUE) {
1924
1919
  try {
1925
- process.kill(item[0], 0);
1920
+ if (pid === item[0] && signal?.aborted) {
1921
+ process.kill(item[0]);
1922
+ closeTorrent(item[0]);
1923
+ }
1924
+ else {
1925
+ process.kill(item[0], 0);
1926
+ }
1926
1927
  }
1927
1928
  catch {
1928
1929
  closeTorrent(item[0]);
@@ -1962,7 +1963,6 @@ class Request extends module_1 {
1962
1963
  return this.get(uri, options);
1963
1964
  }
1964
1965
  opts(url, options) {
1965
- var _p, _q, _r, _s;
1966
1966
  const base = this[kBaseURL];
1967
1967
  if (base) {
1968
1968
  if (typeof url === 'string') {
@@ -1977,18 +1977,25 @@ class Request extends module_1 {
1977
1977
  }
1978
1978
  let host;
1979
1979
  if (this.host) {
1980
- host = (_p = HTTP.HOST)[_q = url.origin] || (_p[_q] = new host_1(url, HTTP.VERSION));
1980
+ host = HTTP.HOST[url.origin] ||= new host_1(url, HTTP.VERSION);
1981
1981
  }
1982
1982
  else {
1983
- host = (_r = this[kHostInfo])[_s = url.origin] || (_r[_s] = new host_1(url, this.httpVersion || 1));
1983
+ host = this[kHostInfo][url.origin] ||= new host_1(url, this.httpVersion || 1);
1984
1984
  }
1985
1985
  return { ...options, host, url };
1986
1986
  }
1987
1987
  open(uri, options) {
1988
- var _p, _q;
1989
- let { host, url, httpVersion, method = 'GET', search, encoding, format, headers, postData, keepAlive, agentTimeout, socketPath, timeout = this._config.connectTimeout, outStream } = options;
1990
- const getting = method === 'GET';
1991
- const posting = method === 'POST';
1988
+ let { host, url, httpVersion, method = 'GET', search, encoding, format, headers: outgoing, postData, keepAlive, agentTimeout, socketPath, timeout = this._config.connectTimeout, outStream } = options, headers = (0, util_1.parseOutgoingHeaders)(outgoing), getting = false, posting = false;
1989
+ switch (method = method.toUpperCase()) {
1990
+ case 'GET':
1991
+ case 'DELETE':
1992
+ getting = true;
1993
+ break;
1994
+ case 'POST':
1995
+ case 'PUT':
1996
+ posting = true;
1997
+ break;
1998
+ }
1992
1999
  if (format) {
1993
2000
  let parser;
1994
2001
  if ((0, types_1.isObject)(format)) {
@@ -1997,7 +2004,7 @@ class Request extends module_1 {
1997
2004
  if (format.includes('/')) {
1998
2005
  format = format.split('/').pop().split('-').pop();
1999
2006
  }
2000
- headers || (headers = {});
2007
+ headers ||= {};
2001
2008
  switch (format = format.trim().toLowerCase()) {
2002
2009
  case 'yaml':
2003
2010
  headers.accept = 'application/yaml, application/x-yaml, text/yaml, text/x-yaml';
@@ -2046,7 +2053,7 @@ class Request extends module_1 {
2046
2053
  this[kBaseURL] = [url, httpVersion, headers];
2047
2054
  }
2048
2055
  else if (base) {
2049
- httpVersion ?? (httpVersion = base[1]);
2056
+ httpVersion ??= base[1];
2050
2057
  if (base[2]) {
2051
2058
  headers = { ...base[2], ...headers };
2052
2059
  }
@@ -2057,13 +2064,13 @@ class Request extends module_1 {
2057
2064
  }
2058
2065
  uri = url.href;
2059
2066
  }
2060
- const { hostname, origin, secure, localhost } = host;
2067
+ const { hostname, origin, secure } = host;
2061
2068
  const pathname = url.pathname + (socketPath ? '' : url.search);
2062
- const proxy = this.proxyOf(uri, localhost);
2069
+ const proxy = this.proxyOf(uri, host.localhost);
2063
2070
  const version = this.httpVersion;
2064
2071
  let request, ca, cert, key, ciphers, minVersion, baseHeaders = this.headersOf(uri);
2065
- if (getting && this.acceptEncoding && !localhost && !baseHeaders?.['accept-encoding']) {
2066
- (_p = (headers || (headers = {})))['accept-encoding'] || (_p['accept-encoding'] = 'gzip, deflate, br' + (LIB_ZSTD ? ', zstd' : ''));
2072
+ if (getting && this.acceptEncoding && !host.localhost && !baseHeaders?.['accept-encoding']) {
2073
+ (headers ||= {})['accept-encoding'] ||= 'gzip, deflate, br' + (LIB_ZSTD ? ', zstd' : '');
2067
2074
  }
2068
2075
  if (secure) {
2069
2076
  const certs = this[kCerts]?.[0][origin] || this.host && TLS.TEXT[origin];
@@ -2072,7 +2079,7 @@ class Request extends module_1 {
2072
2079
  }
2073
2080
  }
2074
2081
  if (!proxy && httpVersion !== 1 && ((httpVersion || host.version) === 2 && version !== 1 || secure && version === 2 && host.failed(2, true) === 0)) {
2075
- request = ((_q = this[kSession][0])[origin] || (_q[origin] = http2.connect(origin, { lookup: this.lookupDns(hostname), ca, cert, key, ciphers, minVersion, settings: localhost ? { maxFrameSize: 16777215, enablePush: false } : { enablePush: false } }))).request({ ...baseHeaders, ...host_1.getBasicAuth(url), ...headers, ':path': pathname, ':method': method });
2082
+ request = (this[kSession][0][origin] ||= http2.connect(origin, { lookup: this.lookupDns(hostname), ca, cert, key, ciphers, minVersion, settings: host.localhost ? { maxFrameSize: 16777215, enablePush: false } : { enablePush: false } })).request({ ...baseHeaders, ...host_1.getBasicAuth(url), ...headers, ':path': pathname, ':method': method });
2076
2083
  if (getting) {
2077
2084
  const listenerMap = {};
2078
2085
  const onEvent = request.on.bind(request);
@@ -2113,7 +2120,6 @@ class Request extends module_1 {
2113
2120
  this.matchHeaders(url, response, request, options);
2114
2121
  });
2115
2122
  request.on = function (event, listener) {
2116
- var _p;
2117
2123
  switch (event) {
2118
2124
  case 'data':
2119
2125
  case 'error':
@@ -2123,7 +2129,7 @@ class Request extends module_1 {
2123
2129
  break;
2124
2130
  }
2125
2131
  if (!connected) {
2126
- (listenerMap[_p = event + '-on'] || (listenerMap[_p] = [])).push(listener);
2132
+ (listenerMap[event + '-on'] ||= []).push(listener);
2127
2133
  }
2128
2134
  default:
2129
2135
  onEvent(event, listener);
@@ -2132,7 +2138,6 @@ class Request extends module_1 {
2132
2138
  return this;
2133
2139
  };
2134
2140
  request.once = function (event, listener) {
2135
- var _p;
2136
2141
  switch (event) {
2137
2142
  case 'data':
2138
2143
  case 'error':
@@ -2142,7 +2147,7 @@ class Request extends module_1 {
2142
2147
  break;
2143
2148
  }
2144
2149
  if (!connected) {
2145
- (listenerMap[_p = event + '-once'] || (listenerMap[_p] = [])).push(listener);
2150
+ (listenerMap[event + '-once'] ||= []).push(listener);
2146
2151
  }
2147
2152
  default:
2148
2153
  onceEvent(event, listener);
@@ -2159,8 +2164,8 @@ class Request extends module_1 {
2159
2164
  if (proxy) {
2160
2165
  const pkg = secure ? 'https-proxy-agent' : 'http-proxy-agent';
2161
2166
  try {
2162
- keepAlive ?? (keepAlive = proxy.keepAlive);
2163
- agentTimeout ?? (agentTimeout = proxy.agentTimeout);
2167
+ keepAlive ??= proxy.keepAlive;
2168
+ agentTimeout ??= proxy.agentTimeout;
2164
2169
  const proxyHeaders = this[kHeaders] && getBaseHeaders(proxy.host.href, this[kHeaders]) || getBaseHeaders(proxy.host.href, HTTP.HEADERS);
2165
2170
  agent = require(pkg)(proxy.host, typeof keepAlive === 'boolean' || agentTimeout > 0 || proxyHeaders ? { keepAlive: keepAlive ?? true, timeout: agentTimeout, headers: proxyHeaders } : undefined);
2166
2171
  if (proxyHeaders) {
@@ -2178,7 +2183,7 @@ class Request extends module_1 {
2178
2183
  agent = new (secure ? https.Agent : http.Agent)({ keepAlive: true, timeout: agentTimeout });
2179
2184
  }
2180
2185
  else if (agentTimeout !== 0) {
2181
- agentTimeout ?? (agentTimeout = this.agentTimeout);
2186
+ agentTimeout ??= this.agentTimeout;
2182
2187
  if (this.keepAlive !== null || agentTimeout > 0) {
2183
2188
  agent = new (secure ? https.Agent : http.Agent)({ keepAlive: this.keepAlive ?? true, timeout: agentTimeout });
2184
2189
  }
@@ -2285,6 +2290,9 @@ class Request extends module_1 {
2285
2290
  const ac = new AbortController();
2286
2291
  this[kDownloading].add(options.outAbort = ac);
2287
2292
  stream.addAbortSignal(ac.signal, request);
2293
+ if (options.signal) {
2294
+ stream.addAbortSignal(options.signal, request);
2295
+ }
2288
2296
  this.signal.addEventListener('abort', () => {
2289
2297
  ac.abort(new Error("Aborted by process"));
2290
2298
  }, { once: true });
@@ -2306,8 +2314,21 @@ class Request extends module_1 {
2306
2314
  out.httpVersion = 1;
2307
2315
  return this.open(out.url, out);
2308
2316
  }
2317
+ async put(uri, data, contentType, options) {
2318
+ if ((0, types_1.isPlainObject)(contentType)) {
2319
+ options = contentType;
2320
+ }
2321
+ else {
2322
+ (options ||= {}).contentType = contentType;
2323
+ }
2324
+ options.method = 'PUT';
2325
+ if (options.contentType === "multipart/form-data") {
2326
+ options.contentType = "application/x-www-form-urlencoded";
2327
+ }
2328
+ return this.post(uri, data, options);
2329
+ }
2309
2330
  async post(uri, data, contentType, options) {
2310
- let parts;
2331
+ let putting = false, parts;
2311
2332
  if (Array.isArray(contentType)) {
2312
2333
  parts = contentType;
2313
2334
  contentType = undefined;
@@ -2315,9 +2336,10 @@ class Request extends module_1 {
2315
2336
  else {
2316
2337
  if ((0, types_1.isPlainObject)(contentType)) {
2317
2338
  options = contentType;
2339
+ putting = options.method === 'PUT';
2318
2340
  contentType = undefined;
2319
2341
  }
2320
- if (Array.isArray(data) && (!contentType || contentType === "multipart/form-data")) {
2342
+ if (!putting && Array.isArray(data) && (!contentType || contentType === "multipart/form-data")) {
2321
2343
  parts = data;
2322
2344
  data = undefined;
2323
2345
  }
@@ -2326,24 +2348,24 @@ class Request extends module_1 {
2326
2348
  if ((0, types_1.isPlainObject)(options)) {
2327
2349
  let formData;
2328
2350
  ({ formData, dataEncoding } = options);
2329
- if (formData) {
2330
- (parts || (parts = [])).push(...Array.isArray(formData) ? formData : [formData]);
2351
+ if (!putting && formData) {
2352
+ (parts ||= []).push(...Array.isArray(formData) ? formData : [formData]);
2331
2353
  }
2332
2354
  else {
2333
- contentType || (contentType = options.contentType);
2355
+ contentType ||= options.contentType;
2334
2356
  }
2335
2357
  }
2336
2358
  else {
2337
2359
  options = {};
2338
2360
  }
2339
- const headers = options.headers || (options.headers = {});
2361
+ const headers = (0, util_1.parseOutgoingHeaders)(options.headers ||= {});
2340
2362
  for (const attr in headers) {
2341
2363
  const name = attr.toLowerCase();
2342
2364
  if (name === 'content-type' || name === 'content-length') {
2343
2365
  delete headers[attr];
2344
2366
  }
2345
2367
  }
2346
- if (parts || contentType === "multipart/form-data" || contentType === 'form-data') {
2368
+ if (!putting && (parts || contentType === "multipart/form-data" || contentType === 'form-data')) {
2347
2369
  let valid;
2348
2370
  if ((0, types_1.isArray)(parts)) {
2349
2371
  const write = combined.create();
@@ -2375,8 +2397,8 @@ class Request extends module_1 {
2375
2397
  }
2376
2398
  if (target) {
2377
2399
  if (typeof target === 'string') {
2378
- filename || (filename = path.basename(target));
2379
- type || (type = module_1.lookupMime(filename));
2400
+ filename ||= path.basename(target);
2401
+ type ||= module_1.lookupMime(filename);
2380
2402
  target = fs.readFileSync(target);
2381
2403
  }
2382
2404
  else if (target instanceof stream.Readable) {
@@ -2393,7 +2415,7 @@ class Request extends module_1 {
2393
2415
  const result = await module_1.resolveMime(target);
2394
2416
  let ext;
2395
2417
  if (result) {
2396
- type || (type = result.mime);
2418
+ type ||= result.mime;
2397
2419
  ext = result.ext;
2398
2420
  }
2399
2421
  else if (type) {
@@ -2436,11 +2458,13 @@ class Request extends module_1 {
2436
2458
  }
2437
2459
  else {
2438
2460
  data = JSON.stringify(data);
2439
- contentType || (contentType = "application/json");
2461
+ contentType ||= "application/json";
2440
2462
  }
2441
2463
  headers['content-length'] = Buffer.byteLength(data, (0, types_1.getEncoding)(dataEncoding)).toString();
2442
2464
  }
2443
- options.method = 'POST';
2465
+ if (!putting) {
2466
+ options.method = 'POST';
2467
+ }
2444
2468
  options.httpVersion = 1;
2445
2469
  options.postData = data;
2446
2470
  headers['content-type'] = contentType || "text/plain";
@@ -2480,7 +2504,7 @@ class Request extends module_1 {
2480
2504
  for (const callback of called) {
2481
2505
  try {
2482
2506
  if (callback(code, headers, url) === true) {
2483
- abortHeaders.call(this, href, request, options);
2507
+ abortHeaders.call(this, href, request, options, code);
2484
2508
  return false;
2485
2509
  }
2486
2510
  }
@@ -2526,11 +2550,11 @@ class Request extends module_1 {
2526
2550
  set agentTimeout(value) {
2527
2551
  if (value > 0) {
2528
2552
  this[kAgentTimeout] = value;
2529
- this.keepAlive ?? (this.keepAlive = true);
2553
+ this.keepAlive ??= true;
2530
2554
  }
2531
2555
  else {
2532
2556
  this[kAgentTimeout] = 0;
2533
- this.keepAlive ?? (this.keepAlive = false);
2557
+ this.keepAlive ??= false;
2534
2558
  }
2535
2559
  }
2536
2560
  get agentTimeout() {
@@ -2560,8 +2584,7 @@ class Request extends module_1 {
2560
2584
  return this[kIpVersion];
2561
2585
  }
2562
2586
  get settings() {
2563
- var _p;
2564
- return (_p = this.module).settings || (_p.settings = {});
2587
+ return this.module.settings ||= {};
2565
2588
  }
2566
2589
  }
2567
2590
  _a = kSingleton, _b = kHttpVersion, _c = kHeaders, _d = kCerts, _e = kBaseURL, _f = kConnectDns, _g = kPendingDns, _h = kConnectHttp, _j = kStatusOn, _k = kHeadersOn, _l = kDownloading, _m = kHostInfo, _o = kSession;