domain-alive 0.1.14 → 0.1.15

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.
Files changed (3) hide show
  1. package/dist/index.js +1536 -44
  2. package/dist/index.mjs +1528 -37
  3. package/package.json +2 -1
package/dist/index.js CHANGED
@@ -4,13 +4,14 @@ var tldts = require('tldts');
4
4
  var require$$0$1 = require('dgram');
5
5
  var require$$0 = require('util');
6
6
  var require$$0$2 = require('net');
7
- var require$$0$3 = require('http');
7
+ var require$$0$4 = require('http');
8
8
  var require$$1 = require('https');
9
- var require$$2 = require('url');
10
- var require$$4 = require('events');
11
- var require$$0$4 = require('tls');
12
- var require$$2$1 = require('http2');
13
- var require$$2$2 = require('assert');
9
+ var require$$0$3 = require('url');
10
+ var require$$1$1 = require('events');
11
+ var require$$0$5 = require('tls');
12
+ var require$$3 = require('http2');
13
+ var require$$0$6 = require('stream');
14
+ var require$$2 = require('assert');
14
15
  var asyncRetry = require('foxts/async-retry');
15
16
  var net = require('node:net');
16
17
  var retrie = require('foxts/retrie');
@@ -23,13 +24,14 @@ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
23
24
  var require$$0__default$1 = /*#__PURE__*/_interopDefault(require$$0$1);
24
25
  var require$$0__default = /*#__PURE__*/_interopDefault(require$$0);
25
26
  var require$$0__default$2 = /*#__PURE__*/_interopDefault(require$$0$2);
26
- var require$$0__default$3 = /*#__PURE__*/_interopDefault(require$$0$3);
27
+ var require$$0__default$4 = /*#__PURE__*/_interopDefault(require$$0$4);
27
28
  var require$$1__default = /*#__PURE__*/_interopDefault(require$$1);
29
+ var require$$0__default$3 = /*#__PURE__*/_interopDefault(require$$0$3);
30
+ var require$$1__default$1 = /*#__PURE__*/_interopDefault(require$$1$1);
31
+ var require$$0__default$5 = /*#__PURE__*/_interopDefault(require$$0$5);
32
+ var require$$3__default = /*#__PURE__*/_interopDefault(require$$3);
33
+ var require$$0__default$6 = /*#__PURE__*/_interopDefault(require$$0$6);
28
34
  var require$$2__default = /*#__PURE__*/_interopDefault(require$$2);
29
- var require$$4__default = /*#__PURE__*/_interopDefault(require$$4);
30
- var require$$0__default$4 = /*#__PURE__*/_interopDefault(require$$0$4);
31
- var require$$2__default$1 = /*#__PURE__*/_interopDefault(require$$2$1);
32
- var require$$2__default$2 = /*#__PURE__*/_interopDefault(require$$2$2);
33
35
  var net__default = /*#__PURE__*/_interopDefault(net);
34
36
  var debug__default = /*#__PURE__*/_interopDefault(debug);
35
37
 
@@ -1208,11 +1210,11 @@ var hasRequiredDoh$1;
1208
1210
  function requireDoh$1 () {
1209
1211
  if (hasRequiredDoh$1) return doh$1;
1210
1212
  hasRequiredDoh$1 = 1;
1211
- const http = require$$0__default$3.default;
1213
+ const http = require$$0__default$4.default;
1212
1214
  const https = require$$1__default.default;
1213
- const { URL } = require$$2__default.default;
1215
+ const { URL } = require$$0__default$3.default;
1214
1216
  const Packet = requirePacket();
1215
- const EventEmitter = require$$4__default.default;
1217
+ const EventEmitter = require$$1__default$1.default;
1216
1218
  const { debuglog } = require$$0__default.default;
1217
1219
  const debug = debuglog('dns2-server');
1218
1220
  const decodeBase64URL = (str)=>{
@@ -1356,7 +1358,7 @@ var hasRequiredDns;
1356
1358
  function requireDns () {
1357
1359
  if (hasRequiredDns) return dns;
1358
1360
  hasRequiredDns = 1;
1359
- const EventEmitter = require$$4__default.default;
1361
+ const EventEmitter = require$$1__default$1.default;
1360
1362
  const DOHServer = requireDoh$1();
1361
1363
  const TCPServer = requireTcp$1();
1362
1364
  const UDPServer = requireUdp$1();
@@ -1477,7 +1479,7 @@ var hasRequiredTcp;
1477
1479
  function requireTcp () {
1478
1480
  if (hasRequiredTcp) return tcp_1;
1479
1481
  hasRequiredTcp = 1;
1480
- const tls = require$$0__default$4.default;
1482
+ const tls = require$$0__default$5.default;
1481
1483
  const tcp = require$$0__default$2.default;
1482
1484
  const Packet = requirePacket();
1483
1485
  const makeQuery = ({ name, type = 'A', cls = Packet.CLASS.IN, clientIp, recursive = true })=>{
@@ -1538,41 +1540,1531 @@ function requireTcp () {
1538
1540
  return tcp_1;
1539
1541
  }
1540
1542
 
1543
+ var quickLru;
1544
+ var hasRequiredQuickLru;
1545
+
1546
+ function requireQuickLru () {
1547
+ if (hasRequiredQuickLru) return quickLru;
1548
+ hasRequiredQuickLru = 1;
1549
+ var _computedKey;
1550
+ _computedKey = Symbol.iterator;
1551
+ class QuickLRU {
1552
+ constructor(options = {}){
1553
+ if (!(options.maxSize && options.maxSize > 0)) {
1554
+ throw new TypeError('`maxSize` must be a number greater than 0');
1555
+ }
1556
+ this.maxSize = options.maxSize;
1557
+ this.onEviction = options.onEviction;
1558
+ this.cache = new Map();
1559
+ this.oldCache = new Map();
1560
+ this._size = 0;
1561
+ }
1562
+ _set(key, value) {
1563
+ this.cache.set(key, value);
1564
+ this._size++;
1565
+ if (this._size >= this.maxSize) {
1566
+ this._size = 0;
1567
+ if (typeof this.onEviction === 'function') {
1568
+ for (const [key, value] of this.oldCache.entries()){
1569
+ this.onEviction(key, value);
1570
+ }
1571
+ }
1572
+ this.oldCache = this.cache;
1573
+ this.cache = new Map();
1574
+ }
1575
+ }
1576
+ get(key) {
1577
+ if (this.cache.has(key)) {
1578
+ return this.cache.get(key);
1579
+ }
1580
+ if (this.oldCache.has(key)) {
1581
+ const value = this.oldCache.get(key);
1582
+ this.oldCache.delete(key);
1583
+ this._set(key, value);
1584
+ return value;
1585
+ }
1586
+ }
1587
+ set(key, value) {
1588
+ if (this.cache.has(key)) {
1589
+ this.cache.set(key, value);
1590
+ } else {
1591
+ this._set(key, value);
1592
+ }
1593
+ return this;
1594
+ }
1595
+ has(key) {
1596
+ return this.cache.has(key) || this.oldCache.has(key);
1597
+ }
1598
+ peek(key) {
1599
+ if (this.cache.has(key)) {
1600
+ return this.cache.get(key);
1601
+ }
1602
+ if (this.oldCache.has(key)) {
1603
+ return this.oldCache.get(key);
1604
+ }
1605
+ }
1606
+ delete(key) {
1607
+ const deleted = this.cache.delete(key);
1608
+ if (deleted) {
1609
+ this._size--;
1610
+ }
1611
+ return this.oldCache.delete(key) || deleted;
1612
+ }
1613
+ clear() {
1614
+ this.cache.clear();
1615
+ this.oldCache.clear();
1616
+ this._size = 0;
1617
+ }
1618
+ *keys() {
1619
+ for (const [key] of this){
1620
+ yield key;
1621
+ }
1622
+ }
1623
+ *values() {
1624
+ for (const [, value] of this){
1625
+ yield value;
1626
+ }
1627
+ }
1628
+ *[_computedKey]() {
1629
+ for (const item of this.cache){
1630
+ yield item;
1631
+ }
1632
+ for (const item of this.oldCache){
1633
+ const [key] = item;
1634
+ if (!this.cache.has(key)) {
1635
+ yield item;
1636
+ }
1637
+ }
1638
+ }
1639
+ get size() {
1640
+ let oldCacheSize = 0;
1641
+ for (const key of this.oldCache.keys()){
1642
+ if (!this.cache.has(key)) {
1643
+ oldCacheSize++;
1644
+ }
1645
+ }
1646
+ return Math.min(this._size + oldCacheSize, this.maxSize);
1647
+ }
1648
+ }
1649
+ quickLru = QuickLRU;
1650
+ return quickLru;
1651
+ }
1652
+
1653
+ var delayAsyncDestroy;
1654
+ var hasRequiredDelayAsyncDestroy;
1655
+
1656
+ function requireDelayAsyncDestroy () {
1657
+ if (hasRequiredDelayAsyncDestroy) return delayAsyncDestroy;
1658
+ hasRequiredDelayAsyncDestroy = 1;
1659
+ delayAsyncDestroy = (stream)=>{
1660
+ if (stream.listenerCount('error') !== 0) {
1661
+ return stream;
1662
+ }
1663
+ stream.__destroy = stream._destroy;
1664
+ stream._destroy = (...args)=>{
1665
+ const callback = args.pop();
1666
+ stream.__destroy(...args, async (error)=>{
1667
+ await Promise.resolve();
1668
+ callback(error);
1669
+ });
1670
+ };
1671
+ const onError = (error)=>{
1672
+ // eslint-disable-next-line promise/prefer-await-to-then
1673
+ Promise.resolve().then(()=>{
1674
+ stream.emit('error', error);
1675
+ });
1676
+ };
1677
+ stream.once('error', onError);
1678
+ // eslint-disable-next-line promise/prefer-await-to-then
1679
+ Promise.resolve().then(()=>{
1680
+ stream.off('error', onError);
1681
+ });
1682
+ return stream;
1683
+ };
1684
+ return delayAsyncDestroy;
1685
+ }
1686
+
1687
+ var agent;
1688
+ var hasRequiredAgent;
1689
+
1690
+ function requireAgent () {
1691
+ if (hasRequiredAgent) return agent;
1692
+ hasRequiredAgent = 1;
1693
+ // See https://github.com/facebook/jest/issues/2549
1694
+ // eslint-disable-next-line node/prefer-global/url
1695
+ const { URL } = require$$0__default$3.default;
1696
+ const EventEmitter = require$$1__default$1.default;
1697
+ const tls = require$$0__default$5.default;
1698
+ const http2 = require$$3__default.default;
1699
+ const QuickLRU = requireQuickLru();
1700
+ const delayAsyncDestroy = requireDelayAsyncDestroy();
1701
+ const kCurrentStreamCount = Symbol('currentStreamCount');
1702
+ const kRequest = Symbol('request');
1703
+ const kOriginSet = Symbol('cachedOriginSet');
1704
+ const kGracefullyClosing = Symbol('gracefullyClosing');
1705
+ const kLength = Symbol('length');
1706
+ const nameKeys = [
1707
+ // Not an Agent option actually
1708
+ 'createConnection',
1709
+ // `http2.connect()` options
1710
+ 'maxDeflateDynamicTableSize',
1711
+ 'maxSettings',
1712
+ 'maxSessionMemory',
1713
+ 'maxHeaderListPairs',
1714
+ 'maxOutstandingPings',
1715
+ 'maxReservedRemoteStreams',
1716
+ 'maxSendHeaderBlockLength',
1717
+ 'paddingStrategy',
1718
+ 'peerMaxConcurrentStreams',
1719
+ 'settings',
1720
+ // `tls.connect()` source options
1721
+ 'family',
1722
+ 'localAddress',
1723
+ 'rejectUnauthorized',
1724
+ // `tls.connect()` secure context options
1725
+ 'pskCallback',
1726
+ 'minDHSize',
1727
+ // `tls.connect()` destination options
1728
+ // - `servername` is automatically validated, skip it
1729
+ // - `host` and `port` just describe the destination server,
1730
+ 'path',
1731
+ 'socket',
1732
+ // `tls.createSecureContext()` options
1733
+ 'ca',
1734
+ 'cert',
1735
+ 'sigalgs',
1736
+ 'ciphers',
1737
+ 'clientCertEngine',
1738
+ 'crl',
1739
+ 'dhparam',
1740
+ 'ecdhCurve',
1741
+ 'honorCipherOrder',
1742
+ 'key',
1743
+ 'privateKeyEngine',
1744
+ 'privateKeyIdentifier',
1745
+ 'maxVersion',
1746
+ 'minVersion',
1747
+ 'pfx',
1748
+ 'secureOptions',
1749
+ 'secureProtocol',
1750
+ 'sessionIdContext',
1751
+ 'ticketKeys'
1752
+ ];
1753
+ const getSortedIndex = (array, value, compare)=>{
1754
+ let low = 0;
1755
+ let high = array.length;
1756
+ while(low < high){
1757
+ const mid = low + high >>> 1;
1758
+ if (compare(array[mid], value)) {
1759
+ low = mid + 1;
1760
+ } else {
1761
+ high = mid;
1762
+ }
1763
+ }
1764
+ return low;
1765
+ };
1766
+ const compareSessions = (a, b)=>a.remoteSettings.maxConcurrentStreams > b.remoteSettings.maxConcurrentStreams;
1767
+ // See https://tools.ietf.org/html/rfc8336
1768
+ const closeCoveredSessions = (where, session)=>{
1769
+ // Clients SHOULD NOT emit new requests on any connection whose Origin
1770
+ // Set is a proper subset of another connection's Origin Set, and they
1771
+ // SHOULD close it once all outstanding requests are satisfied.
1772
+ for(let index = 0; index < where.length; index++){
1773
+ const coveredSession = where[index];
1774
+ if (// Unfortunately `.every()` returns true for an empty array
1775
+ coveredSession[kOriginSet].length > 0 && coveredSession[kOriginSet].length < session[kOriginSet].length && coveredSession[kOriginSet].every((origin)=>session[kOriginSet].includes(origin)) && coveredSession[kCurrentStreamCount] + session[kCurrentStreamCount] <= session.remoteSettings.maxConcurrentStreams) {
1776
+ // This allows pending requests to finish and prevents making new requests.
1777
+ gracefullyClose(coveredSession);
1778
+ }
1779
+ }
1780
+ };
1781
+ // This is basically inverted `closeCoveredSessions(...)`.
1782
+ const closeSessionIfCovered = (where, coveredSession)=>{
1783
+ for(let index = 0; index < where.length; index++){
1784
+ const session = where[index];
1785
+ if (coveredSession[kOriginSet].length > 0 && coveredSession[kOriginSet].length < session[kOriginSet].length && coveredSession[kOriginSet].every((origin)=>session[kOriginSet].includes(origin)) && coveredSession[kCurrentStreamCount] + session[kCurrentStreamCount] <= session.remoteSettings.maxConcurrentStreams) {
1786
+ gracefullyClose(coveredSession);
1787
+ return true;
1788
+ }
1789
+ }
1790
+ return false;
1791
+ };
1792
+ const gracefullyClose = (session)=>{
1793
+ session[kGracefullyClosing] = true;
1794
+ if (session[kCurrentStreamCount] === 0) {
1795
+ session.close();
1796
+ }
1797
+ };
1798
+ class Agent extends EventEmitter {
1799
+ constructor({ timeout = 0, maxSessions = Number.POSITIVE_INFINITY, maxEmptySessions = 10, maxCachedTlsSessions = 100 } = {}){
1800
+ super();
1801
+ // SESSIONS[NORMALIZED_OPTIONS] = [];
1802
+ this.sessions = {};
1803
+ // The queue for creating new sessions. It looks like this:
1804
+ // QUEUE[NORMALIZED_OPTIONS][NORMALIZED_ORIGIN] = ENTRY_FUNCTION
1805
+ //
1806
+ // It's faster when there are many origins. If there's only one, then QUEUE[`${options}:${origin}`] is faster.
1807
+ // I guess object creation / deletion is causing the slowdown.
1808
+ //
1809
+ // The entry function has `listeners`, `completed` and `destroyed` properties.
1810
+ // `listeners` is an array of objects containing `resolve` and `reject` functions.
1811
+ // `completed` is a boolean. It's set to true after ENTRY_FUNCTION is executed.
1812
+ // `destroyed` is a boolean. If it's set to true, the session will be destroyed if hasn't connected yet.
1813
+ this.queue = {};
1814
+ // Each session will use this timeout value.
1815
+ this.timeout = timeout;
1816
+ // Max sessions in total
1817
+ this.maxSessions = maxSessions;
1818
+ // Max empty sessions in total
1819
+ this.maxEmptySessions = maxEmptySessions;
1820
+ this._emptySessionCount = 0;
1821
+ this._sessionCount = 0;
1822
+ // We don't support push streams by default.
1823
+ this.settings = {
1824
+ enablePush: false,
1825
+ initialWindowSize: 1024 * 1024 * 32 // 32MB, see https://github.com/nodejs/node/issues/38426
1826
+ };
1827
+ // Reusing TLS sessions increases performance.
1828
+ this.tlsSessionCache = new QuickLRU({
1829
+ maxSize: maxCachedTlsSessions
1830
+ });
1831
+ }
1832
+ get protocol() {
1833
+ return 'https:';
1834
+ }
1835
+ normalizeOptions(options) {
1836
+ let normalized = '';
1837
+ for(let index = 0; index < nameKeys.length; index++){
1838
+ const key = nameKeys[index];
1839
+ normalized += ':';
1840
+ if (options && options[key] !== undefined) {
1841
+ normalized += options[key];
1842
+ }
1843
+ }
1844
+ return normalized;
1845
+ }
1846
+ _processQueue() {
1847
+ if (this._sessionCount >= this.maxSessions) {
1848
+ this.closeEmptySessions(this.maxSessions - this._sessionCount + 1);
1849
+ return;
1850
+ }
1851
+ // eslint-disable-next-line guard-for-in
1852
+ for(const normalizedOptions in this.queue){
1853
+ // eslint-disable-next-line guard-for-in
1854
+ for(const normalizedOrigin in this.queue[normalizedOptions]){
1855
+ const item = this.queue[normalizedOptions][normalizedOrigin];
1856
+ // The entry function can be run only once.
1857
+ if (!item.completed) {
1858
+ item.completed = true;
1859
+ item();
1860
+ }
1861
+ }
1862
+ }
1863
+ }
1864
+ _isBetterSession(thisStreamCount, thatStreamCount) {
1865
+ return thisStreamCount > thatStreamCount;
1866
+ }
1867
+ _accept(session, listeners, normalizedOrigin, options) {
1868
+ let index = 0;
1869
+ while(index < listeners.length && session[kCurrentStreamCount] < session.remoteSettings.maxConcurrentStreams){
1870
+ // We assume `resolve(...)` calls `request(...)` *directly*,
1871
+ // otherwise the session will get overloaded.
1872
+ listeners[index].resolve(session);
1873
+ index++;
1874
+ }
1875
+ listeners.splice(0, index);
1876
+ if (listeners.length > 0) {
1877
+ this.getSession(normalizedOrigin, options, listeners);
1878
+ listeners.length = 0;
1879
+ }
1880
+ }
1881
+ getSession(origin, options, listeners) {
1882
+ return new Promise((resolve, reject)=>{
1883
+ if (Array.isArray(listeners) && listeners.length > 0) {
1884
+ listeners = [
1885
+ ...listeners
1886
+ ];
1887
+ // Resolve the current promise ASAP, we're just moving the listeners.
1888
+ // They will be executed at a different time.
1889
+ resolve();
1890
+ } else {
1891
+ listeners = [
1892
+ {
1893
+ resolve,
1894
+ reject
1895
+ }
1896
+ ];
1897
+ }
1898
+ try {
1899
+ // Parse origin
1900
+ if (typeof origin === 'string') {
1901
+ origin = new URL(origin);
1902
+ } else if (!(origin instanceof URL)) {
1903
+ throw new TypeError('The `origin` argument needs to be a string or an URL object');
1904
+ }
1905
+ if (options) {
1906
+ // Validate servername
1907
+ const { servername } = options;
1908
+ const { hostname } = origin;
1909
+ if (servername && hostname !== servername) {
1910
+ throw new Error(`Origin ${hostname} differs from servername ${servername}`);
1911
+ }
1912
+ }
1913
+ } catch (error) {
1914
+ for(let index = 0; index < listeners.length; index++){
1915
+ listeners[index].reject(error);
1916
+ }
1917
+ return;
1918
+ }
1919
+ const normalizedOptions = this.normalizeOptions(options);
1920
+ const normalizedOrigin = origin.origin;
1921
+ if (normalizedOptions in this.sessions) {
1922
+ const sessions = this.sessions[normalizedOptions];
1923
+ let maxConcurrentStreams = -1;
1924
+ let currentStreamsCount = -1;
1925
+ let optimalSession;
1926
+ // We could just do this.sessions[normalizedOptions].find(...) but that isn't optimal.
1927
+ // Additionally, we are looking for session which has biggest current pending streams count.
1928
+ //
1929
+ // |------------| |------------| |------------| |------------|
1930
+ // | Session: A | | Session: B | | Session: C | | Session: D |
1931
+ // | Pending: 5 |-| Pending: 8 |-| Pending: 9 |-| Pending: 4 |
1932
+ // | Max: 10 | | Max: 10 | | Max: 9 | | Max: 5 |
1933
+ // |------------| |------------| |------------| |------------|
1934
+ // ^
1935
+ // |
1936
+ // pick this one --
1937
+ //
1938
+ for(let index = 0; index < sessions.length; index++){
1939
+ const session = sessions[index];
1940
+ const sessionMaxConcurrentStreams = session.remoteSettings.maxConcurrentStreams;
1941
+ if (sessionMaxConcurrentStreams < maxConcurrentStreams) {
1942
+ break;
1943
+ }
1944
+ if (!session[kOriginSet].includes(normalizedOrigin)) {
1945
+ continue;
1946
+ }
1947
+ const sessionCurrentStreamsCount = session[kCurrentStreamCount];
1948
+ if (sessionCurrentStreamsCount >= sessionMaxConcurrentStreams || session[kGracefullyClosing] || session.destroyed) {
1949
+ continue;
1950
+ }
1951
+ // We only need set this once.
1952
+ if (!optimalSession) {
1953
+ maxConcurrentStreams = sessionMaxConcurrentStreams;
1954
+ }
1955
+ // Either get the session which has biggest current stream count or the lowest.
1956
+ if (this._isBetterSession(sessionCurrentStreamsCount, currentStreamsCount)) {
1957
+ optimalSession = session;
1958
+ currentStreamsCount = sessionCurrentStreamsCount;
1959
+ }
1960
+ }
1961
+ if (optimalSession) {
1962
+ this._accept(optimalSession, listeners, normalizedOrigin, options);
1963
+ return;
1964
+ }
1965
+ }
1966
+ if (normalizedOptions in this.queue) {
1967
+ if (normalizedOrigin in this.queue[normalizedOptions]) {
1968
+ // There's already an item in the queue, just attach ourselves to it.
1969
+ this.queue[normalizedOptions][normalizedOrigin].listeners.push(...listeners);
1970
+ return;
1971
+ }
1972
+ } else {
1973
+ this.queue[normalizedOptions] = {
1974
+ [kLength]: 0
1975
+ };
1976
+ }
1977
+ // The entry must be removed from the queue IMMEDIATELY when:
1978
+ // 1. the session connects successfully,
1979
+ // 2. an error occurs.
1980
+ const removeFromQueue = ()=>{
1981
+ // Our entry can be replaced. We cannot remove the new one.
1982
+ if (normalizedOptions in this.queue && this.queue[normalizedOptions][normalizedOrigin] === entry) {
1983
+ delete this.queue[normalizedOptions][normalizedOrigin];
1984
+ if (--this.queue[normalizedOptions][kLength] === 0) {
1985
+ delete this.queue[normalizedOptions];
1986
+ }
1987
+ }
1988
+ };
1989
+ // The main logic is here
1990
+ const entry = async ()=>{
1991
+ this._sessionCount++;
1992
+ const name = `${normalizedOrigin}:${normalizedOptions}`;
1993
+ let receivedSettings = false;
1994
+ let socket;
1995
+ try {
1996
+ const computedOptions = {
1997
+ ...options
1998
+ };
1999
+ if (computedOptions.settings === undefined) {
2000
+ computedOptions.settings = this.settings;
2001
+ }
2002
+ if (computedOptions.session === undefined) {
2003
+ computedOptions.session = this.tlsSessionCache.get(name);
2004
+ }
2005
+ const createConnection = computedOptions.createConnection || this.createConnection;
2006
+ // A hacky workaround to enable async `createConnection`
2007
+ socket = await createConnection.call(this, origin, computedOptions);
2008
+ computedOptions.createConnection = ()=>socket;
2009
+ const session = http2.connect(origin, computedOptions);
2010
+ session[kCurrentStreamCount] = 0;
2011
+ session[kGracefullyClosing] = false;
2012
+ // Node.js return https://false:443 instead of https://1.1.1.1:443
2013
+ const getOriginSet = ()=>{
2014
+ const { socket } = session;
2015
+ let originSet;
2016
+ if (socket.servername === false) {
2017
+ socket.servername = socket.remoteAddress;
2018
+ originSet = session.originSet;
2019
+ socket.servername = false;
2020
+ } else {
2021
+ originSet = session.originSet;
2022
+ }
2023
+ return originSet;
2024
+ };
2025
+ const isFree = ()=>session[kCurrentStreamCount] < session.remoteSettings.maxConcurrentStreams;
2026
+ session.socket.once('session', (tlsSession)=>{
2027
+ this.tlsSessionCache.set(name, tlsSession);
2028
+ });
2029
+ session.once('error', (error)=>{
2030
+ // Listeners are empty when the session successfully connected.
2031
+ for(let index = 0; index < listeners.length; index++){
2032
+ listeners[index].reject(error);
2033
+ }
2034
+ // The connection got broken, purge the cache.
2035
+ this.tlsSessionCache.delete(name);
2036
+ });
2037
+ session.setTimeout(this.timeout, ()=>{
2038
+ // Terminates all streams owned by this session.
2039
+ session.destroy();
2040
+ });
2041
+ session.once('close', ()=>{
2042
+ this._sessionCount--;
2043
+ if (receivedSettings) {
2044
+ // Assumes session `close` is emitted after request `close`
2045
+ this._emptySessionCount--;
2046
+ // This cannot be moved to the stream logic,
2047
+ // because there may be a session that hadn't made a single request.
2048
+ const where = this.sessions[normalizedOptions];
2049
+ if (where.length === 1) {
2050
+ delete this.sessions[normalizedOptions];
2051
+ } else {
2052
+ where.splice(where.indexOf(session), 1);
2053
+ }
2054
+ } else {
2055
+ // Broken connection
2056
+ removeFromQueue();
2057
+ const error = new Error('Session closed without receiving a SETTINGS frame');
2058
+ error.code = 'HTTP2WRAPPER_NOSETTINGS';
2059
+ for(let index = 0; index < listeners.length; index++){
2060
+ listeners[index].reject(error);
2061
+ }
2062
+ }
2063
+ // There may be another session awaiting.
2064
+ this._processQueue();
2065
+ });
2066
+ // Iterates over the queue and processes listeners.
2067
+ const processListeners = ()=>{
2068
+ const queue = this.queue[normalizedOptions];
2069
+ if (!queue) {
2070
+ return;
2071
+ }
2072
+ const originSet = session[kOriginSet];
2073
+ for(let index = 0; index < originSet.length; index++){
2074
+ const origin = originSet[index];
2075
+ if (origin in queue) {
2076
+ const { listeners, completed } = queue[origin];
2077
+ let index = 0;
2078
+ // Prevents session overloading.
2079
+ while(index < listeners.length && isFree()){
2080
+ // We assume `resolve(...)` calls `request(...)` *directly*,
2081
+ // otherwise the session will get overloaded.
2082
+ listeners[index].resolve(session);
2083
+ index++;
2084
+ }
2085
+ queue[origin].listeners.splice(0, index);
2086
+ if (queue[origin].listeners.length === 0 && !completed) {
2087
+ delete queue[origin];
2088
+ if (--queue[kLength] === 0) {
2089
+ delete this.queue[normalizedOptions];
2090
+ break;
2091
+ }
2092
+ }
2093
+ // We're no longer free, no point in continuing.
2094
+ if (!isFree()) {
2095
+ break;
2096
+ }
2097
+ }
2098
+ }
2099
+ };
2100
+ // The Origin Set cannot shrink. No need to check if it suddenly became covered by another one.
2101
+ session.on('origin', ()=>{
2102
+ session[kOriginSet] = getOriginSet() || [];
2103
+ session[kGracefullyClosing] = false;
2104
+ closeSessionIfCovered(this.sessions[normalizedOptions], session);
2105
+ if (session[kGracefullyClosing] || !isFree()) {
2106
+ return;
2107
+ }
2108
+ processListeners();
2109
+ if (!isFree()) {
2110
+ return;
2111
+ }
2112
+ // Close covered sessions (if possible).
2113
+ closeCoveredSessions(this.sessions[normalizedOptions], session);
2114
+ });
2115
+ session.once('remoteSettings', ()=>{
2116
+ // The Agent could have been destroyed already.
2117
+ if (entry.destroyed) {
2118
+ const error = new Error('Agent has been destroyed');
2119
+ for(let index = 0; index < listeners.length; index++){
2120
+ listeners[index].reject(error);
2121
+ }
2122
+ session.destroy();
2123
+ return;
2124
+ }
2125
+ // See https://github.com/nodejs/node/issues/38426
2126
+ if (session.setLocalWindowSize) {
2127
+ session.setLocalWindowSize(1024 * 1024 * 4); // 4 MB
2128
+ }
2129
+ session[kOriginSet] = getOriginSet() || [];
2130
+ if (session.socket.encrypted) {
2131
+ const mainOrigin = session[kOriginSet][0];
2132
+ if (mainOrigin !== normalizedOrigin) {
2133
+ const error = new Error(`Requested origin ${normalizedOrigin} does not match server ${mainOrigin}`);
2134
+ for(let index = 0; index < listeners.length; index++){
2135
+ listeners[index].reject(error);
2136
+ }
2137
+ session.destroy();
2138
+ return;
2139
+ }
2140
+ }
2141
+ removeFromQueue();
2142
+ {
2143
+ const where = this.sessions;
2144
+ if (normalizedOptions in where) {
2145
+ const sessions = where[normalizedOptions];
2146
+ sessions.splice(getSortedIndex(sessions, session, compareSessions), 0, session);
2147
+ } else {
2148
+ where[normalizedOptions] = [
2149
+ session
2150
+ ];
2151
+ }
2152
+ }
2153
+ receivedSettings = true;
2154
+ this._emptySessionCount++;
2155
+ this.emit('session', session);
2156
+ this._accept(session, listeners, normalizedOrigin, options);
2157
+ if (session[kCurrentStreamCount] === 0 && this._emptySessionCount > this.maxEmptySessions) {
2158
+ this.closeEmptySessions(this._emptySessionCount - this.maxEmptySessions);
2159
+ }
2160
+ // `session.remoteSettings.maxConcurrentStreams` might get increased
2161
+ session.on('remoteSettings', ()=>{
2162
+ if (!isFree()) {
2163
+ return;
2164
+ }
2165
+ processListeners();
2166
+ if (!isFree()) {
2167
+ return;
2168
+ }
2169
+ // In case the Origin Set changes
2170
+ closeCoveredSessions(this.sessions[normalizedOptions], session);
2171
+ });
2172
+ });
2173
+ // Shim `session.request()` in order to catch all streams
2174
+ session[kRequest] = session.request;
2175
+ session.request = (headers, streamOptions)=>{
2176
+ if (session[kGracefullyClosing]) {
2177
+ throw new Error('The session is gracefully closing. No new streams are allowed.');
2178
+ }
2179
+ const stream = session[kRequest](headers, streamOptions);
2180
+ // The process won't exit until the session is closed or all requests are gone.
2181
+ session.ref();
2182
+ if (session[kCurrentStreamCount]++ === 0) {
2183
+ this._emptySessionCount--;
2184
+ }
2185
+ stream.once('close', ()=>{
2186
+ if (--session[kCurrentStreamCount] === 0) {
2187
+ this._emptySessionCount++;
2188
+ session.unref();
2189
+ if (this._emptySessionCount > this.maxEmptySessions || session[kGracefullyClosing]) {
2190
+ session.close();
2191
+ return;
2192
+ }
2193
+ }
2194
+ if (session.destroyed || session.closed) {
2195
+ return;
2196
+ }
2197
+ if (isFree() && !closeSessionIfCovered(this.sessions[normalizedOptions], session)) {
2198
+ closeCoveredSessions(this.sessions[normalizedOptions], session);
2199
+ processListeners();
2200
+ if (session[kCurrentStreamCount] === 0) {
2201
+ this._processQueue();
2202
+ }
2203
+ }
2204
+ });
2205
+ return stream;
2206
+ };
2207
+ } catch (error) {
2208
+ removeFromQueue();
2209
+ this._sessionCount--;
2210
+ for(let index = 0; index < listeners.length; index++){
2211
+ listeners[index].reject(error);
2212
+ }
2213
+ }
2214
+ };
2215
+ entry.listeners = listeners;
2216
+ entry.completed = false;
2217
+ entry.destroyed = false;
2218
+ this.queue[normalizedOptions][normalizedOrigin] = entry;
2219
+ this.queue[normalizedOptions][kLength]++;
2220
+ this._processQueue();
2221
+ });
2222
+ }
2223
+ request(origin, options, headers, streamOptions) {
2224
+ return new Promise((resolve, reject)=>{
2225
+ this.getSession(origin, options, [
2226
+ {
2227
+ reject,
2228
+ resolve: (session)=>{
2229
+ try {
2230
+ const stream = session.request(headers, streamOptions);
2231
+ // Do not throw before `request(...)` has been awaited
2232
+ delayAsyncDestroy(stream);
2233
+ resolve(stream);
2234
+ } catch (error) {
2235
+ reject(error);
2236
+ }
2237
+ }
2238
+ }
2239
+ ]);
2240
+ });
2241
+ }
2242
+ async createConnection(origin, options) {
2243
+ return Agent.connect(origin, options);
2244
+ }
2245
+ static connect(origin, options) {
2246
+ options.ALPNProtocols = [
2247
+ 'h2'
2248
+ ];
2249
+ const port = origin.port || 443;
2250
+ const host = origin.hostname;
2251
+ if (typeof options.servername === 'undefined') {
2252
+ options.servername = host;
2253
+ }
2254
+ const socket = tls.connect(port, host, options);
2255
+ if (options.socket) {
2256
+ socket._peername = {
2257
+ family: undefined,
2258
+ address: undefined,
2259
+ port
2260
+ };
2261
+ }
2262
+ return socket;
2263
+ }
2264
+ closeEmptySessions(maxCount = Number.POSITIVE_INFINITY) {
2265
+ let closedCount = 0;
2266
+ const { sessions } = this;
2267
+ // eslint-disable-next-line guard-for-in
2268
+ for(const key in sessions){
2269
+ const thisSessions = sessions[key];
2270
+ for(let index = 0; index < thisSessions.length; index++){
2271
+ const session = thisSessions[index];
2272
+ if (session[kCurrentStreamCount] === 0) {
2273
+ closedCount++;
2274
+ session.close();
2275
+ if (closedCount >= maxCount) {
2276
+ return closedCount;
2277
+ }
2278
+ }
2279
+ }
2280
+ }
2281
+ return closedCount;
2282
+ }
2283
+ destroy(reason) {
2284
+ const { sessions, queue } = this;
2285
+ // eslint-disable-next-line guard-for-in
2286
+ for(const key in sessions){
2287
+ const thisSessions = sessions[key];
2288
+ for(let index = 0; index < thisSessions.length; index++){
2289
+ thisSessions[index].destroy(reason);
2290
+ }
2291
+ }
2292
+ // eslint-disable-next-line guard-for-in
2293
+ for(const normalizedOptions in queue){
2294
+ const entries = queue[normalizedOptions];
2295
+ // eslint-disable-next-line guard-for-in
2296
+ for(const normalizedOrigin in entries){
2297
+ entries[normalizedOrigin].destroyed = true;
2298
+ }
2299
+ }
2300
+ // New requests should NOT attach to destroyed sessions
2301
+ this.queue = {};
2302
+ this.tlsSessionCache.clear();
2303
+ }
2304
+ get emptySessionCount() {
2305
+ return this._emptySessionCount;
2306
+ }
2307
+ get pendingSessionCount() {
2308
+ return this._sessionCount - this._emptySessionCount;
2309
+ }
2310
+ get sessionCount() {
2311
+ return this._sessionCount;
2312
+ }
2313
+ }
2314
+ Agent.kCurrentStreamCount = kCurrentStreamCount;
2315
+ Agent.kGracefullyClosing = kGracefullyClosing;
2316
+ agent = {
2317
+ Agent,
2318
+ globalAgent: new Agent()
2319
+ };
2320
+ return agent;
2321
+ }
2322
+
2323
+ var incomingMessage;
2324
+ var hasRequiredIncomingMessage;
2325
+
2326
+ function requireIncomingMessage () {
2327
+ if (hasRequiredIncomingMessage) return incomingMessage;
2328
+ hasRequiredIncomingMessage = 1;
2329
+ const { Readable } = require$$0__default$6.default;
2330
+ class IncomingMessage extends Readable {
2331
+ constructor(socket, highWaterMark){
2332
+ super({
2333
+ emitClose: false,
2334
+ autoDestroy: true,
2335
+ highWaterMark
2336
+ });
2337
+ this.statusCode = null;
2338
+ this.statusMessage = '';
2339
+ this.httpVersion = '2.0';
2340
+ this.httpVersionMajor = 2;
2341
+ this.httpVersionMinor = 0;
2342
+ this.headers = {};
2343
+ this.trailers = {};
2344
+ this.req = null;
2345
+ this.aborted = false;
2346
+ this.complete = false;
2347
+ this.upgrade = null;
2348
+ this.rawHeaders = [];
2349
+ this.rawTrailers = [];
2350
+ this.socket = socket;
2351
+ this._dumped = false;
2352
+ }
2353
+ get connection() {
2354
+ return this.socket;
2355
+ }
2356
+ set connection(value) {
2357
+ this.socket = value;
2358
+ }
2359
+ _destroy(error, callback) {
2360
+ if (!this.readableEnded) {
2361
+ this.aborted = true;
2362
+ }
2363
+ // See https://github.com/nodejs/node/issues/35303
2364
+ callback();
2365
+ this.req._request.destroy(error);
2366
+ }
2367
+ setTimeout(ms, callback) {
2368
+ this.req.setTimeout(ms, callback);
2369
+ return this;
2370
+ }
2371
+ _dump() {
2372
+ if (!this._dumped) {
2373
+ this._dumped = true;
2374
+ this.removeAllListeners('data');
2375
+ this.resume();
2376
+ }
2377
+ }
2378
+ _read() {
2379
+ if (this.req) {
2380
+ this.req._request.resume();
2381
+ }
2382
+ }
2383
+ }
2384
+ incomingMessage = IncomingMessage;
2385
+ return incomingMessage;
2386
+ }
2387
+
2388
+ var proxyEvents;
2389
+ var hasRequiredProxyEvents;
2390
+
2391
+ function requireProxyEvents () {
2392
+ if (hasRequiredProxyEvents) return proxyEvents;
2393
+ hasRequiredProxyEvents = 1;
2394
+ proxyEvents = (from, to, events)=>{
2395
+ for (const event of events){
2396
+ from.on(event, (...args)=>to.emit(event, ...args));
2397
+ }
2398
+ };
2399
+ return proxyEvents;
2400
+ }
2401
+
2402
+ var errors$1 = {exports: {}};
2403
+
2404
+ var hasRequiredErrors;
2405
+
2406
+ function requireErrors () {
2407
+ if (hasRequiredErrors) return errors$1.exports;
2408
+ hasRequiredErrors = 1;
2409
+ (function (module) {
2410
+ /* istanbul ignore file: https://github.com/nodejs/node/blob/master/lib/internal/errors.js */ const makeError = (Base, key, getMessage)=>{
2411
+ module.exports[key] = class NodeError extends Base {
2412
+ constructor(...args){
2413
+ super(typeof getMessage === 'string' ? getMessage : getMessage(args));
2414
+ this.name = `${super.name} [${key}]`;
2415
+ this.code = key;
2416
+ }
2417
+ };
2418
+ };
2419
+ makeError(TypeError, 'ERR_INVALID_ARG_TYPE', (args)=>{
2420
+ const type = args[0].includes('.') ? 'property' : 'argument';
2421
+ let valid = args[1];
2422
+ const isManyTypes = Array.isArray(valid);
2423
+ if (isManyTypes) {
2424
+ valid = `${valid.slice(0, -1).join(', ')} or ${valid.slice(-1)}`;
2425
+ }
2426
+ return `The "${args[0]}" ${type} must be ${isManyTypes ? 'one of' : 'of'} type ${valid}. Received ${typeof args[2]}`;
2427
+ });
2428
+ makeError(TypeError, 'ERR_INVALID_PROTOCOL', (args)=>`Protocol "${args[0]}" not supported. Expected "${args[1]}"`);
2429
+ makeError(Error, 'ERR_HTTP_HEADERS_SENT', (args)=>`Cannot ${args[0]} headers after they are sent to the client`);
2430
+ makeError(TypeError, 'ERR_INVALID_HTTP_TOKEN', (args)=>`${args[0]} must be a valid HTTP token [${args[1]}]`);
2431
+ makeError(TypeError, 'ERR_HTTP_INVALID_HEADER_VALUE', (args)=>`Invalid value "${args[0]} for header "${args[1]}"`);
2432
+ makeError(TypeError, 'ERR_INVALID_CHAR', (args)=>`Invalid character in ${args[0]} [${args[1]}]`);
2433
+ makeError(Error, 'ERR_HTTP2_NO_SOCKET_MANIPULATION', 'HTTP/2 sockets should not be directly manipulated (e.g. read and written)');
2434
+ } (errors$1));
2435
+ return errors$1.exports;
2436
+ }
2437
+
2438
+ var isRequestPseudoHeader;
2439
+ var hasRequiredIsRequestPseudoHeader;
2440
+
2441
+ function requireIsRequestPseudoHeader () {
2442
+ if (hasRequiredIsRequestPseudoHeader) return isRequestPseudoHeader;
2443
+ hasRequiredIsRequestPseudoHeader = 1;
2444
+ isRequestPseudoHeader = (header)=>{
2445
+ switch(header){
2446
+ case ':method':
2447
+ case ':scheme':
2448
+ case ':authority':
2449
+ case ':path':
2450
+ return true;
2451
+ default:
2452
+ return false;
2453
+ }
2454
+ };
2455
+ return isRequestPseudoHeader;
2456
+ }
2457
+
2458
+ var validateHeaderName;
2459
+ var hasRequiredValidateHeaderName;
2460
+
2461
+ function requireValidateHeaderName () {
2462
+ if (hasRequiredValidateHeaderName) return validateHeaderName;
2463
+ hasRequiredValidateHeaderName = 1;
2464
+ const { ERR_INVALID_HTTP_TOKEN } = requireErrors();
2465
+ const isRequestPseudoHeader = requireIsRequestPseudoHeader();
2466
+ const isValidHttpToken = /^[\^`\-\w!#$%&*+.|~]+$/;
2467
+ validateHeaderName = (name)=>{
2468
+ if (typeof name !== 'string' || !isValidHttpToken.test(name) && !isRequestPseudoHeader(name)) {
2469
+ throw new ERR_INVALID_HTTP_TOKEN('Header name', name);
2470
+ }
2471
+ };
2472
+ return validateHeaderName;
2473
+ }
2474
+
2475
+ var validateHeaderValue;
2476
+ var hasRequiredValidateHeaderValue;
2477
+
2478
+ function requireValidateHeaderValue () {
2479
+ if (hasRequiredValidateHeaderValue) return validateHeaderValue;
2480
+ hasRequiredValidateHeaderValue = 1;
2481
+ const { ERR_HTTP_INVALID_HEADER_VALUE, ERR_INVALID_CHAR } = requireErrors();
2482
+ const isInvalidHeaderValue = /[^\t\u0020-\u007E\u0080-\u00FF]/;
2483
+ validateHeaderValue = (name, value)=>{
2484
+ if (typeof value === 'undefined') {
2485
+ throw new ERR_HTTP_INVALID_HEADER_VALUE(value, name);
2486
+ }
2487
+ if (isInvalidHeaderValue.test(value)) {
2488
+ throw new ERR_INVALID_CHAR('header content', name);
2489
+ }
2490
+ };
2491
+ return validateHeaderValue;
2492
+ }
2493
+
2494
+ var proxySocketHandler_1;
2495
+ var hasRequiredProxySocketHandler;
2496
+
2497
+ function requireProxySocketHandler () {
2498
+ if (hasRequiredProxySocketHandler) return proxySocketHandler_1;
2499
+ hasRequiredProxySocketHandler = 1;
2500
+ const { ERR_HTTP2_NO_SOCKET_MANIPULATION } = requireErrors();
2501
+ /* istanbul ignore file */ /* https://github.com/nodejs/node/blob/6eec858f34a40ffa489c1ec54bb24da72a28c781/lib/internal/http2/compat.js#L195-L272 */ const proxySocketHandler = {
2502
+ has (stream, property) {
2503
+ // Replaced [kSocket] with .socket
2504
+ const reference = stream.session === undefined ? stream : stream.session.socket;
2505
+ return property in stream || property in reference;
2506
+ },
2507
+ get (stream, property) {
2508
+ switch(property){
2509
+ case 'on':
2510
+ case 'once':
2511
+ case 'end':
2512
+ case 'emit':
2513
+ case 'destroy':
2514
+ return stream[property].bind(stream);
2515
+ case 'writable':
2516
+ case 'destroyed':
2517
+ return stream[property];
2518
+ case 'readable':
2519
+ if (stream.destroyed) {
2520
+ return false;
2521
+ }
2522
+ return stream.readable;
2523
+ case 'setTimeout':
2524
+ {
2525
+ const { session } = stream;
2526
+ if (session !== undefined) {
2527
+ return session.setTimeout.bind(session);
2528
+ }
2529
+ return stream.setTimeout.bind(stream);
2530
+ }
2531
+ case 'write':
2532
+ case 'read':
2533
+ case 'pause':
2534
+ case 'resume':
2535
+ throw new ERR_HTTP2_NO_SOCKET_MANIPULATION();
2536
+ default:
2537
+ {
2538
+ // Replaced [kSocket] with .socket
2539
+ const reference = stream.session === undefined ? stream : stream.session.socket;
2540
+ const value = reference[property];
2541
+ return typeof value === 'function' ? value.bind(reference) : value;
2542
+ }
2543
+ }
2544
+ },
2545
+ getPrototypeOf (stream) {
2546
+ if (stream.session !== undefined) {
2547
+ // Replaced [kSocket] with .socket
2548
+ return Reflect.getPrototypeOf(stream.session.socket);
2549
+ }
2550
+ return Reflect.getPrototypeOf(stream);
2551
+ },
2552
+ set (stream, property, value) {
2553
+ switch(property){
2554
+ case 'writable':
2555
+ case 'readable':
2556
+ case 'destroyed':
2557
+ case 'on':
2558
+ case 'once':
2559
+ case 'end':
2560
+ case 'emit':
2561
+ case 'destroy':
2562
+ stream[property] = value;
2563
+ return true;
2564
+ case 'setTimeout':
2565
+ {
2566
+ const { session } = stream;
2567
+ if (session === undefined) {
2568
+ stream.setTimeout = value;
2569
+ } else {
2570
+ session.setTimeout = value;
2571
+ }
2572
+ return true;
2573
+ }
2574
+ case 'write':
2575
+ case 'read':
2576
+ case 'pause':
2577
+ case 'resume':
2578
+ throw new ERR_HTTP2_NO_SOCKET_MANIPULATION();
2579
+ default:
2580
+ {
2581
+ // Replaced [kSocket] with .socket
2582
+ const reference = stream.session === undefined ? stream : stream.session.socket;
2583
+ reference[property] = value;
2584
+ return true;
2585
+ }
2586
+ }
2587
+ }
2588
+ };
2589
+ proxySocketHandler_1 = proxySocketHandler;
2590
+ return proxySocketHandler_1;
2591
+ }
2592
+
2593
+ var clientRequest;
2594
+ var hasRequiredClientRequest;
2595
+
2596
+ function requireClientRequest () {
2597
+ if (hasRequiredClientRequest) return clientRequest;
2598
+ hasRequiredClientRequest = 1;
2599
+ // See https://github.com/facebook/jest/issues/2549
2600
+ // eslint-disable-next-line node/prefer-global/url
2601
+ const { URL, urlToHttpOptions } = require$$0__default$3.default;
2602
+ const http2 = require$$3__default.default;
2603
+ const { Writable } = require$$0__default$6.default;
2604
+ const { Agent, globalAgent } = requireAgent();
2605
+ const IncomingMessage = requireIncomingMessage();
2606
+ const proxyEvents = requireProxyEvents();
2607
+ const { ERR_INVALID_ARG_TYPE, ERR_INVALID_PROTOCOL, ERR_HTTP_HEADERS_SENT } = requireErrors();
2608
+ const validateHeaderName = requireValidateHeaderName();
2609
+ const validateHeaderValue = requireValidateHeaderValue();
2610
+ const proxySocketHandler = requireProxySocketHandler();
2611
+ const { HTTP2_HEADER_STATUS, HTTP2_HEADER_METHOD, HTTP2_HEADER_PATH, HTTP2_HEADER_AUTHORITY, HTTP2_METHOD_CONNECT } = http2.constants;
2612
+ const kHeaders = Symbol('headers');
2613
+ const kOrigin = Symbol('origin');
2614
+ const kSession = Symbol('session');
2615
+ const kOptions = Symbol('options');
2616
+ const kFlushedHeaders = Symbol('flushedHeaders');
2617
+ const kJobs = Symbol('jobs');
2618
+ const kPendingAgentPromise = Symbol('pendingAgentPromise');
2619
+ class ClientRequest extends Writable {
2620
+ constructor(input, options, callback){
2621
+ super({
2622
+ autoDestroy: false,
2623
+ emitClose: false
2624
+ });
2625
+ if (typeof input === 'string') {
2626
+ input = urlToHttpOptions(new URL(input));
2627
+ } else if (input instanceof URL) {
2628
+ input = urlToHttpOptions(input);
2629
+ } else {
2630
+ input = {
2631
+ ...input
2632
+ };
2633
+ }
2634
+ if (typeof options === 'function' || options === undefined) {
2635
+ // (options, callback)
2636
+ callback = options;
2637
+ options = input;
2638
+ } else {
2639
+ // (input, options, callback)
2640
+ options = Object.assign(input, options);
2641
+ }
2642
+ if (options.h2session) {
2643
+ this[kSession] = options.h2session;
2644
+ if (this[kSession].destroyed) {
2645
+ throw new Error('The session has been closed already');
2646
+ }
2647
+ this.protocol = this[kSession].socket.encrypted ? 'https:' : 'http:';
2648
+ } else if (options.agent === false) {
2649
+ this.agent = new Agent({
2650
+ maxEmptySessions: 0
2651
+ });
2652
+ } else if (typeof options.agent === 'undefined' || options.agent === null) {
2653
+ this.agent = globalAgent;
2654
+ } else if (typeof options.agent.request === 'function') {
2655
+ this.agent = options.agent;
2656
+ } else {
2657
+ throw new ERR_INVALID_ARG_TYPE('options.agent', [
2658
+ 'http2wrapper.Agent-like Object',
2659
+ 'undefined',
2660
+ 'false'
2661
+ ], options.agent);
2662
+ }
2663
+ if (this.agent) {
2664
+ this.protocol = this.agent.protocol;
2665
+ }
2666
+ if (options.protocol && options.protocol !== this.protocol) {
2667
+ throw new ERR_INVALID_PROTOCOL(options.protocol, this.protocol);
2668
+ }
2669
+ if (!options.port) {
2670
+ options.port = options.defaultPort || this.agent && this.agent.defaultPort || 443;
2671
+ }
2672
+ options.host = options.hostname || options.host || 'localhost';
2673
+ // Unused
2674
+ delete options.hostname;
2675
+ const { timeout } = options;
2676
+ options.timeout = undefined;
2677
+ this[kHeaders] = Object.create(null);
2678
+ this[kJobs] = [];
2679
+ this[kPendingAgentPromise] = undefined;
2680
+ this.socket = null;
2681
+ this.connection = null;
2682
+ this.method = options.method || 'GET';
2683
+ if (!(this.method === 'CONNECT' && (options.path === '/' || options.path === undefined))) {
2684
+ this.path = options.path;
2685
+ }
2686
+ this.res = null;
2687
+ this.aborted = false;
2688
+ this.reusedSocket = false;
2689
+ const { headers } = options;
2690
+ if (headers) {
2691
+ // eslint-disable-next-line guard-for-in
2692
+ for(const header in headers){
2693
+ this.setHeader(header, headers[header]);
2694
+ }
2695
+ }
2696
+ if (options.auth && !('authorization' in this[kHeaders])) {
2697
+ this[kHeaders].authorization = 'Basic ' + Buffer.from(options.auth).toString('base64');
2698
+ }
2699
+ options.session = options.tlsSession;
2700
+ options.path = options.socketPath;
2701
+ this[kOptions] = options;
2702
+ // Clients that generate HTTP/2 requests directly SHOULD use the :authority pseudo-header field instead of the Host header field.
2703
+ this[kOrigin] = new URL(`${this.protocol}//${options.servername || options.host}:${options.port}`);
2704
+ // A socket is being reused
2705
+ const reuseSocket = options._reuseSocket;
2706
+ if (reuseSocket) {
2707
+ options.createConnection = (...args)=>{
2708
+ if (reuseSocket.destroyed) {
2709
+ return this.agent.createConnection(...args);
2710
+ }
2711
+ return reuseSocket;
2712
+ };
2713
+ // eslint-disable-next-line promise/prefer-await-to-then
2714
+ this.agent.getSession(this[kOrigin], this[kOptions]).catch(()=>{});
2715
+ }
2716
+ if (timeout) {
2717
+ this.setTimeout(timeout);
2718
+ }
2719
+ if (callback) {
2720
+ this.once('response', callback);
2721
+ }
2722
+ this[kFlushedHeaders] = false;
2723
+ }
2724
+ get method() {
2725
+ return this[kHeaders][HTTP2_HEADER_METHOD];
2726
+ }
2727
+ set method(value) {
2728
+ if (value) {
2729
+ this[kHeaders][HTTP2_HEADER_METHOD] = value.toUpperCase();
2730
+ }
2731
+ }
2732
+ get path() {
2733
+ const header = this.method === 'CONNECT' ? HTTP2_HEADER_AUTHORITY : HTTP2_HEADER_PATH;
2734
+ return this[kHeaders][header];
2735
+ }
2736
+ set path(value) {
2737
+ if (value) {
2738
+ const header = this.method === 'CONNECT' ? HTTP2_HEADER_AUTHORITY : HTTP2_HEADER_PATH;
2739
+ this[kHeaders][header] = value;
2740
+ }
2741
+ }
2742
+ get host() {
2743
+ return this[kOrigin].hostname;
2744
+ }
2745
+ set host(_value) {
2746
+ // Do nothing as this is read only.
2747
+ }
2748
+ get _mustNotHaveABody() {
2749
+ return this.method === 'GET' || this.method === 'HEAD' || this.method === 'DELETE';
2750
+ }
2751
+ _write(chunk, encoding, callback) {
2752
+ // https://github.com/nodejs/node/blob/654df09ae0c5e17d1b52a900a545f0664d8c7627/lib/internal/http2/util.js#L148-L156
2753
+ if (this._mustNotHaveABody) {
2754
+ callback(new Error('The GET, HEAD and DELETE methods must NOT have a body'));
2755
+ /* istanbul ignore next: Node.js 12 throws directly */ return;
2756
+ }
2757
+ this.flushHeaders();
2758
+ const callWrite = ()=>this._request.write(chunk, encoding, callback);
2759
+ if (this._request) {
2760
+ callWrite();
2761
+ } else {
2762
+ this[kJobs].push(callWrite);
2763
+ }
2764
+ }
2765
+ _final(callback) {
2766
+ this.flushHeaders();
2767
+ const callEnd = ()=>{
2768
+ // For GET, HEAD and DELETE and CONNECT
2769
+ if (this._mustNotHaveABody || this.method === 'CONNECT') {
2770
+ callback();
2771
+ return;
2772
+ }
2773
+ this._request.end(callback);
2774
+ };
2775
+ if (this._request) {
2776
+ callEnd();
2777
+ } else {
2778
+ this[kJobs].push(callEnd);
2779
+ }
2780
+ }
2781
+ abort() {
2782
+ if (this.res && this.res.complete) {
2783
+ return;
2784
+ }
2785
+ if (!this.aborted) {
2786
+ process.nextTick(()=>this.emit('abort'));
2787
+ }
2788
+ this.aborted = true;
2789
+ this.destroy();
2790
+ }
2791
+ async _destroy(error, callback) {
2792
+ if (this.res) {
2793
+ this.res._dump();
2794
+ }
2795
+ if (this._request) {
2796
+ this._request.destroy();
2797
+ } else {
2798
+ process.nextTick(()=>{
2799
+ this.emit('close');
2800
+ });
2801
+ }
2802
+ try {
2803
+ await this[kPendingAgentPromise];
2804
+ } catch (internalError) {
2805
+ if (this.aborted) {
2806
+ error = internalError;
2807
+ }
2808
+ }
2809
+ callback(error);
2810
+ }
2811
+ async flushHeaders() {
2812
+ if (this[kFlushedHeaders] || this.destroyed) {
2813
+ return;
2814
+ }
2815
+ this[kFlushedHeaders] = true;
2816
+ const isConnectMethod = this.method === HTTP2_METHOD_CONNECT;
2817
+ // The real magic is here
2818
+ const onStream = (stream)=>{
2819
+ this._request = stream;
2820
+ if (this.destroyed) {
2821
+ stream.destroy();
2822
+ return;
2823
+ }
2824
+ // Forwards `timeout`, `continue`, `close` and `error` events to this instance.
2825
+ if (!isConnectMethod) {
2826
+ // TODO: Should we proxy `close` here?
2827
+ proxyEvents(stream, this, [
2828
+ 'timeout',
2829
+ 'continue'
2830
+ ]);
2831
+ }
2832
+ stream.once('error', (error)=>{
2833
+ this.destroy(error);
2834
+ });
2835
+ stream.once('aborted', ()=>{
2836
+ const { res } = this;
2837
+ if (res) {
2838
+ res.aborted = true;
2839
+ res.emit('aborted');
2840
+ res.destroy();
2841
+ } else {
2842
+ this.destroy(new Error('The server aborted the HTTP/2 stream'));
2843
+ }
2844
+ });
2845
+ const onResponse = (headers, flags, rawHeaders)=>{
2846
+ // If we were to emit raw request stream, it would be as fast as the native approach.
2847
+ // Note that wrapping the raw stream in a Proxy instance won't improve the performance (already tested it).
2848
+ const response = new IncomingMessage(this.socket, stream.readableHighWaterMark);
2849
+ this.res = response;
2850
+ // Undocumented, but it is used by `cacheable-request`
2851
+ response.url = `${this[kOrigin].origin}${this.path}`;
2852
+ response.req = this;
2853
+ response.statusCode = headers[HTTP2_HEADER_STATUS];
2854
+ response.headers = headers;
2855
+ response.rawHeaders = rawHeaders;
2856
+ response.once('end', ()=>{
2857
+ response.complete = true;
2858
+ // Has no effect, just be consistent with the Node.js behavior
2859
+ response.socket = null;
2860
+ response.connection = null;
2861
+ });
2862
+ if (isConnectMethod) {
2863
+ response.upgrade = true;
2864
+ // The HTTP1 API says the socket is detached here,
2865
+ // but we can't do that so we pass the original HTTP2 request.
2866
+ if (this.emit('connect', response, stream, Buffer.alloc(0))) {
2867
+ this.emit('close');
2868
+ } else {
2869
+ // No listeners attached, destroy the original request.
2870
+ stream.destroy();
2871
+ }
2872
+ } else {
2873
+ // Forwards data
2874
+ stream.on('data', (chunk)=>{
2875
+ if (!response._dumped && !response.push(chunk)) {
2876
+ stream.pause();
2877
+ }
2878
+ });
2879
+ stream.once('end', ()=>{
2880
+ if (!this.aborted) {
2881
+ response.push(null);
2882
+ }
2883
+ });
2884
+ if (!this.emit('response', response)) {
2885
+ // No listeners attached, dump the response.
2886
+ response._dump();
2887
+ }
2888
+ }
2889
+ };
2890
+ // This event tells we are ready to listen for the data.
2891
+ stream.once('response', onResponse);
2892
+ // Emits `information` event
2893
+ stream.once('headers', (headers)=>this.emit('information', {
2894
+ statusCode: headers[HTTP2_HEADER_STATUS]
2895
+ }));
2896
+ stream.once('trailers', (trailers, flags, rawTrailers)=>{
2897
+ const { res } = this;
2898
+ // https://github.com/nodejs/node/issues/41251
2899
+ if (res === null) {
2900
+ onResponse(trailers, flags, rawTrailers);
2901
+ return;
2902
+ }
2903
+ // Assigns trailers to the response object.
2904
+ res.trailers = trailers;
2905
+ res.rawTrailers = rawTrailers;
2906
+ });
2907
+ stream.once('close', ()=>{
2908
+ const { aborted, res } = this;
2909
+ if (res) {
2910
+ if (aborted) {
2911
+ res.aborted = true;
2912
+ res.emit('aborted');
2913
+ res.destroy();
2914
+ }
2915
+ const finish = ()=>{
2916
+ res.emit('close');
2917
+ this.destroy();
2918
+ this.emit('close');
2919
+ };
2920
+ if (res.readable) {
2921
+ res.once('end', finish);
2922
+ } else {
2923
+ finish();
2924
+ }
2925
+ return;
2926
+ }
2927
+ if (!this.destroyed) {
2928
+ this.destroy(new Error('The HTTP/2 stream has been early terminated'));
2929
+ this.emit('close');
2930
+ return;
2931
+ }
2932
+ this.destroy();
2933
+ this.emit('close');
2934
+ });
2935
+ this.socket = new Proxy(stream, proxySocketHandler);
2936
+ for (const job of this[kJobs]){
2937
+ job();
2938
+ }
2939
+ this[kJobs].length = 0;
2940
+ this.emit('socket', this.socket);
2941
+ };
2942
+ if (!(HTTP2_HEADER_AUTHORITY in this[kHeaders]) && !isConnectMethod) {
2943
+ this[kHeaders][HTTP2_HEADER_AUTHORITY] = this[kOrigin].host;
2944
+ }
2945
+ // Makes a HTTP2 request
2946
+ if (this[kSession]) {
2947
+ try {
2948
+ onStream(this[kSession].request(this[kHeaders]));
2949
+ } catch (error) {
2950
+ this.destroy(error);
2951
+ }
2952
+ } else {
2953
+ this.reusedSocket = true;
2954
+ try {
2955
+ const promise = this.agent.request(this[kOrigin], this[kOptions], this[kHeaders]);
2956
+ this[kPendingAgentPromise] = promise;
2957
+ onStream(await promise);
2958
+ this[kPendingAgentPromise] = false;
2959
+ } catch (error) {
2960
+ this[kPendingAgentPromise] = false;
2961
+ this.destroy(error);
2962
+ }
2963
+ }
2964
+ }
2965
+ get connection() {
2966
+ return this.socket;
2967
+ }
2968
+ set connection(value) {
2969
+ this.socket = value;
2970
+ }
2971
+ getHeaderNames() {
2972
+ return Object.keys(this[kHeaders]);
2973
+ }
2974
+ hasHeader(name) {
2975
+ if (typeof name !== 'string') {
2976
+ throw new ERR_INVALID_ARG_TYPE('name', 'string', name);
2977
+ }
2978
+ return Boolean(this[kHeaders][name.toLowerCase()]);
2979
+ }
2980
+ getHeader(name) {
2981
+ if (typeof name !== 'string') {
2982
+ throw new ERR_INVALID_ARG_TYPE('name', 'string', name);
2983
+ }
2984
+ return this[kHeaders][name.toLowerCase()];
2985
+ }
2986
+ get headersSent() {
2987
+ return this[kFlushedHeaders];
2988
+ }
2989
+ removeHeader(name) {
2990
+ if (typeof name !== 'string') {
2991
+ throw new ERR_INVALID_ARG_TYPE('name', 'string', name);
2992
+ }
2993
+ if (this.headersSent) {
2994
+ throw new ERR_HTTP_HEADERS_SENT('remove');
2995
+ }
2996
+ delete this[kHeaders][name.toLowerCase()];
2997
+ }
2998
+ setHeader(name, value) {
2999
+ if (this.headersSent) {
3000
+ throw new ERR_HTTP_HEADERS_SENT('set');
3001
+ }
3002
+ validateHeaderName(name);
3003
+ validateHeaderValue(name, value);
3004
+ const lowercased = name.toLowerCase();
3005
+ if (lowercased === 'connection') {
3006
+ if (value.toLowerCase() === 'keep-alive') {
3007
+ return;
3008
+ }
3009
+ throw new Error(`Invalid 'connection' header: ${value}`);
3010
+ }
3011
+ if (lowercased === 'host' && this.method === 'CONNECT') {
3012
+ this[kHeaders][HTTP2_HEADER_AUTHORITY] = value;
3013
+ } else {
3014
+ this[kHeaders][lowercased] = value;
3015
+ }
3016
+ }
3017
+ setNoDelay() {
3018
+ // HTTP2 sockets cannot be malformed, do nothing.
3019
+ }
3020
+ setSocketKeepAlive() {
3021
+ // HTTP2 sockets cannot be malformed, do nothing.
3022
+ }
3023
+ setTimeout(ms, callback) {
3024
+ const applyTimeout = ()=>this._request.setTimeout(ms, callback);
3025
+ if (this._request) {
3026
+ applyTimeout();
3027
+ } else {
3028
+ this[kJobs].push(applyTimeout);
3029
+ }
3030
+ return this;
3031
+ }
3032
+ get maxHeadersCount() {
3033
+ if (!this.destroyed && this._request) {
3034
+ return this._request.session.localSettings.maxHeaderListSize;
3035
+ }
3036
+ return undefined;
3037
+ }
3038
+ set maxHeadersCount(_value) {
3039
+ // Updating HTTP2 settings would affect all requests, do nothing.
3040
+ }
3041
+ }
3042
+ clientRequest = ClientRequest;
3043
+ return clientRequest;
3044
+ }
3045
+
1541
3046
  var doh;
1542
3047
  var hasRequiredDoh;
1543
3048
 
1544
3049
  function requireDoh () {
1545
3050
  if (hasRequiredDoh) return doh;
1546
3051
  hasRequiredDoh = 1;
1547
- const http = require$$0__default$3.default;
3052
+ const http = require$$0__default$4.default;
1548
3053
  const https = require$$1__default.default;
1549
- const http2 = require$$2__default$1.default;
3054
+ const HTTP2ClientRequest = requireClientRequest();
1550
3055
  const Packet = requirePacket();
3056
+ // https://github.com/szmarczak/http2-wrapper/blob/f1a1776d4b1aef1cd47d55b1a950986e86145a09/source/index.js#L24
3057
+ // Copy the implementation allows us to pull in minimum code,
3058
+ // instead of importing the entire module to reduce bundle size
3059
+ function http2Get(url, options, callback) {
3060
+ const req = new HTTP2ClientRequest(url, options, callback);
3061
+ req.end();
3062
+ return req;
3063
+ }
1551
3064
  const protocols = {
1552
3065
  'http:': http.get,
1553
3066
  'https:': https.get,
1554
- 'h2:': (url, options, done)=>{
1555
- const urlObj = new URL(url);
1556
- const client = http2.connect(url.replace('h2:', 'https:'));
1557
- const req = client.request({
1558
- ':path': `${urlObj.pathname}${urlObj.search}`,
1559
- ':method': 'GET',
1560
- ...options.headers
1561
- });
1562
- req.on('response', (headers)=>{
1563
- client.close();
1564
- done({
1565
- headers,
1566
- statusCode: headers[':status'],
1567
- on: req.on.bind(req)
1568
- });
1569
- });
1570
- req.on('error', (_err)=>{
1571
- client.close();
1572
- });
1573
- req.end();
1574
- return req;
1575
- }
3067
+ 'h2:': http2Get
1576
3068
  };
1577
3069
  const makeRequest = (url, query)=>new Promise((resolve, reject)=>{
1578
3070
  const index = url.indexOf('://');
@@ -1644,7 +3136,7 @@ function requireUdp () {
1644
3136
  hasRequiredUdp = 1;
1645
3137
  const udp = require$$0__default$1.default;
1646
3138
  const Packet = requirePacket();
1647
- const { equal } = require$$2__default$2.default;
3139
+ const { equal } = require$$2__default.default;
1648
3140
  const { debuglog } = require$$0__default.default;
1649
3141
  const debug = debuglog('dns2');
1650
3142
  udp_1 = ({ dns = '8.8.8.8', port = 53, socketType = 'udp4' } = {})=>{
@@ -1712,7 +3204,7 @@ function requireDns2 () {
1712
3204
  if (hasRequiredDns2) return dns2;
1713
3205
  hasRequiredDns2 = 1;
1714
3206
  const { TCPServer, UDPServer, DOHServer, createTCPServer, createUDPServer, createDOHServer, createServer } = requireServer();
1715
- const EventEmitter = require$$4__default.default;
3207
+ const EventEmitter = require$$1__default$1.default;
1716
3208
  /**
1717
3209
  * [DNS description]
1718
3210
  * @docs https://tools.ietf.org/html/rfc1034
@@ -3112,7 +4604,7 @@ const sharedNullResponse = Object.freeze({
3112
4604
  const mutex = createAsyncMutex();
3113
4605
  const dnsClients = getDnsClients(dnsServers);
3114
4606
  return async function isRegisterableDomainAlive(domain) {
3115
- domain = require$$2.domainToASCII(domain);
4607
+ domain = require$$0$3.domainToASCII(domain);
3116
4608
  return mutex(domain, ()=>cacheApply(registerableDomainResultCache, domain, async ()=>{
3117
4609
  // Step 0: we normalize the domain and find the registerable part
3118
4610
  const registerableDomain = tldts.getDomain(domain, getRegisterableDomainTldtsOption);
@@ -3218,7 +4710,7 @@ function createDomainAliveChecker(options = {}) {
3218
4710
  const mutex = createAsyncMutex();
3219
4711
  const dnsClients = getDnsClients(dnsServers);
3220
4712
  return async function isDomainAlive(domain) {
3221
- domain = require$$2.domainToASCII(domain);
4713
+ domain = require$$0$3.domainToASCII(domain);
3222
4714
  const registerableDomainAliveResult = await isRegisterableDomainAlive(domain);
3223
4715
  if (registerableDomainAliveResult.registerableDomain === null) {
3224
4716
  return sharedNullishResult;