From dbb18f4778a97915cd8bbb737a807f3db51c4619 Mon Sep 17 00:00:00 2001 From: Luke Karrys Date: Wed, 30 Aug 2023 10:24:16 -0700 Subject: [PATCH] deps: @npmcli/agent@2.1.0 --- DEPENDENCIES.md | 6 +- node_modules/.gitignore | 6 + node_modules/@npmcli/agent/lib/agents.js | 201 ++++++++++++++++++ node_modules/@npmcli/agent/lib/dns.js | 68 +++--- node_modules/@npmcli/agent/lib/errors.js | 34 ++- node_modules/@npmcli/agent/lib/http.js | 33 --- node_modules/@npmcli/agent/lib/https.js | 33 --- node_modules/@npmcli/agent/lib/index.js | 149 +++---------- node_modules/@npmcli/agent/lib/options.js | 74 +++++++ node_modules/@npmcli/agent/lib/proxy.js | 96 +++++++++ node_modules/@npmcli/agent/lib/proxy/http.js | 146 ------------- node_modules/@npmcli/agent/lib/proxy/index.js | 25 --- node_modules/@npmcli/agent/lib/proxy/null.js | 97 --------- node_modules/@npmcli/agent/lib/proxy/socks.js | 153 ------------- node_modules/@npmcli/agent/lib/util.js | 85 ++++++-- .../node_modules/agent-base/dist/helpers.js | 66 ++++++ .../node_modules/agent-base/dist/index.js | 112 ++++++++++ .../node_modules/agent-base/package.json | 49 +++++ .../node_modules/http-proxy-agent/LICENSE | 25 +++ .../http-proxy-agent/dist/index.js | 147 +++++++++++++ .../http-proxy-agent/package.json | 47 ++++ .../https-proxy-agent/dist/index.js | 170 +++++++++++++++ .../dist/parse-proxy-response.js | 98 +++++++++ .../https-proxy-agent/package.json | 50 +++++ .../socks-proxy-agent/dist/index.js | 181 ++++++++++++++++ .../socks-proxy-agent/package.json | 142 +++++++++++++ node_modules/@npmcli/agent/package.json | 12 +- package-lock.json | 62 +++++- 28 files changed, 1681 insertions(+), 686 deletions(-) create mode 100644 node_modules/@npmcli/agent/lib/agents.js delete mode 100644 node_modules/@npmcli/agent/lib/http.js delete mode 100644 node_modules/@npmcli/agent/lib/https.js create mode 100644 node_modules/@npmcli/agent/lib/options.js create mode 100644 node_modules/@npmcli/agent/lib/proxy.js delete mode 100644 node_modules/@npmcli/agent/lib/proxy/http.js delete mode 100644 node_modules/@npmcli/agent/lib/proxy/index.js delete mode 100644 node_modules/@npmcli/agent/lib/proxy/null.js delete mode 100644 node_modules/@npmcli/agent/lib/proxy/socks.js create mode 100644 node_modules/@npmcli/agent/node_modules/agent-base/dist/helpers.js create mode 100644 node_modules/@npmcli/agent/node_modules/agent-base/dist/index.js create mode 100644 node_modules/@npmcli/agent/node_modules/agent-base/package.json create mode 100644 node_modules/@npmcli/agent/node_modules/http-proxy-agent/LICENSE create mode 100644 node_modules/@npmcli/agent/node_modules/http-proxy-agent/dist/index.js create mode 100644 node_modules/@npmcli/agent/node_modules/http-proxy-agent/package.json create mode 100644 node_modules/@npmcli/agent/node_modules/https-proxy-agent/dist/index.js create mode 100644 node_modules/@npmcli/agent/node_modules/https-proxy-agent/dist/parse-proxy-response.js create mode 100644 node_modules/@npmcli/agent/node_modules/https-proxy-agent/package.json create mode 100644 node_modules/@npmcli/agent/node_modules/socks-proxy-agent/dist/index.js create mode 100644 node_modules/@npmcli/agent/node_modules/socks-proxy-agent/package.json diff --git a/DEPENDENCIES.md b/DEPENDENCIES.md index b080058cb387e..773b6aeffa54d 100644 --- a/DEPENDENCIES.md +++ b/DEPENDENCIES.md @@ -115,6 +115,7 @@ graph LR; npm-->npm-profile; npm-->npm-registry-fetch; npm-->npm-user-validate; + npm-->npmcli-agent["@npmcli/agent"]; npm-->npmcli-arborist["@npmcli/arborist"]; npm-->npmcli-config["@npmcli/config"]; npm-->npmcli-docs["@npmcli/docs"]; @@ -540,6 +541,7 @@ graph LR; npm-->npm-profile; npm-->npm-registry-fetch; npm-->npm-user-validate; + npm-->npmcli-agent["@npmcli/agent"]; npm-->npmcli-arborist["@npmcli/arborist"]; npm-->npmcli-config["@npmcli/config"]; npm-->npmcli-docs["@npmcli/docs"]; @@ -598,8 +600,10 @@ graph LR; npm-registry-fetch-->minizlib; npm-registry-fetch-->npm-package-arg; npm-registry-fetch-->proc-log; + npmcli-agent-->http-proxy-agent; + npmcli-agent-->https-proxy-agent; npmcli-agent-->lru-cache; - npmcli-agent-->socks; + npmcli-agent-->socks-proxy-agent; npmcli-arborist-->benchmark; npmcli-arborist-->bin-links; npmcli-arborist-->cacache; diff --git a/node_modules/.gitignore b/node_modules/.gitignore index dda14819326ad..9076b038b0ceb 100644 --- a/node_modules/.gitignore +++ b/node_modules/.gitignore @@ -19,6 +19,12 @@ !/@npmcli/ /@npmcli/* !/@npmcli/agent +!/@npmcli/agent/node_modules/ +/@npmcli/agent/node_modules/* +!/@npmcli/agent/node_modules/agent-base +!/@npmcli/agent/node_modules/http-proxy-agent +!/@npmcli/agent/node_modules/https-proxy-agent +!/@npmcli/agent/node_modules/socks-proxy-agent !/@npmcli/disparity-colors !/@npmcli/fs !/@npmcli/git diff --git a/node_modules/@npmcli/agent/lib/agents.js b/node_modules/@npmcli/agent/lib/agents.js new file mode 100644 index 0000000000000..db997403f7579 --- /dev/null +++ b/node_modules/@npmcli/agent/lib/agents.js @@ -0,0 +1,201 @@ +'use strict' + +const http = require('http') +const https = require('https') +const net = require('net') +const tls = require('tls') +const { once } = require('events') +const { createTimeout, abortRace, urlify, appendPort, cacheAgent } = require('./util') +const { normalizeOptions, cacheOptions } = require('./options') +const { getProxy, getProxyType, isSecureProxy, proxyCache } = require('./proxy.js') +const Errors = require('./errors.js') + +const createAgent = (base, name) => { + const SECURE = base === https + const SOCKET_TYPE = SECURE ? tls : net + + const agent = class extends base.Agent { + #options + #timeouts + #proxy + #socket + + constructor (_options) { + const { timeouts, proxy, noProxy, ...options } = normalizeOptions(_options) + + super(options) + + this.#options = options + this.#timeouts = timeouts + this.#proxy = proxy ? { proxies: getProxyType(proxy), proxy: urlify(proxy), noProxy } : null + } + + get proxy () { + return this.#proxy ? { url: this.#proxy.proxy } : {} + } + + #getProxy (options) { + const proxy = this.#proxy + ? getProxy(appendPort(`${options.protocol}//${options.host}`, options.port), this.#proxy) + : null + + if (!proxy) { + return + } + + const secure = isSecureProxy(proxy) + + return cacheAgent({ + key: cacheOptions({ + ...options, + ...this.#options, + secure, + timeouts: this.#timeouts, + proxy, + }), + cache: proxyCache, + secure, + proxies: this.#proxy.proxies, + }, proxy, this.#options) + } + + #setKeepAlive (socket) { + socket.setKeepAlive(this.keepAlive, this.keepAliveMsecs) + socket.setNoDelay(this.keepAlive) + } + + #setIdleTimeout (socket, options) { + if (this.#timeouts.idle) { + socket.setTimeout(this.#timeouts.idle, () => { + socket.destroy(new Errors.IdleTimeoutError(options)) + }) + } + } + + async #proxyConnect (proxy, request, options) { + // socks-proxy-agent accepts a dns lookup function + options.lookup ??= this.#options.lookup + + // all the proxy agents use this secureEndpoint option to determine + // if the proxy should connect over tls or not. we can set it based + // on if the HttpAgent or HttpsAgent is used. + options.secureEndpoint = SECURE + + const socket = await abortRace([ + (ac) => createTimeout(this.#timeouts.connection, ac).catch(() => { + throw new Errors.ConnectionTimeoutError(options) + }), + (ac) => proxy.connect(request, options).then((s) => { + this.#setKeepAlive(s) + + const connectEvent = SECURE ? 'secureConnect' : 'connect' + const connectingEvent = SECURE ? 'secureConnecting' : 'connecting' + + if (!s[connectingEvent]) { + return s + } + + return abortRace([ + () => once(s, 'error', ac).then((err) => { + throw err + }), + () => once(s, connectEvent, ac).then(() => s), + ], ac) + }), + ]) + + this.#setIdleTimeout(socket, options) + + return socket + } + + async connect (request, options) { + const proxy = this.#getProxy(options) + if (proxy) { + return this.#proxyConnect(proxy, request, options) + } + + const socket = SOCKET_TYPE.connect(options) + + this.#setKeepAlive(socket) + + await abortRace([ + (s) => createTimeout(this.#timeouts.connection, s).catch(() => { + throw new Errors.ConnectionTimeoutError(options) + }), + (s) => once(socket, 'error', s).then((err) => { + throw err + }), + (s) => once(socket, 'connect', s), + ]) + + this.#setIdleTimeout(socket, options) + + return socket + } + + addRequest (request, options) { + const proxy = this.#getProxy(options) + // it would be better to call proxy.addRequest here but this causes the + // http-proxy-agent to call its super.addRequest which causes the request + // to be added to the agent twice. since we only support 3 agents + // currently (see the required agents in proxy.js) we have manually + // checked that the only public methods we need to call are called in the + // next block. this could change in the future and presumably we would get + // failing tests until we have properly called the necessary methods on + // each of our proxy agents + if (proxy?.setRequestProps) { + proxy.setRequestProps(request, options) + } + + request.setHeader('connection', this.keepAlive ? 'keep-alive' : 'close') + + const responseTimeout = createTimeout(this.#timeouts.response) + if (responseTimeout) { + request.once('finish', () => { + responseTimeout.start(() => { + request.destroy(new Errors.ResponseTimeoutError(request, this.proxy?.url)) + }) + }) + request.once('response', () => { + responseTimeout.clear() + }) + } + + const transferTimeout = createTimeout(this.#timeouts.transfer) + if (transferTimeout) { + request.once('response', (res) => { + transferTimeout.start(() => { + res.destroy(new Errors.TransferTimeoutError(request, this.proxy?.url)) + }) + res.once('close', () => { + transferTimeout.clear() + }) + }) + } + + return super.addRequest(request, options) + } + + createSocket (req, options, cb) { + return Promise.resolve() + .then(() => this.connect(req, options)) + .then((socket) => { + this.#socket = socket + return super.createSocket(req, options, cb) + }, cb) + } + + createConnection () { + return this.#socket + } + } + + Object.defineProperty(agent, 'name', { value: name }) + return agent +} + +module.exports = { + HttpAgent: createAgent(http, 'HttpAgent'), + HttpsAgent: createAgent(https, 'HttpsAgent'), +} diff --git a/node_modules/@npmcli/agent/lib/dns.js b/node_modules/@npmcli/agent/lib/dns.js index 7f1a7c9a80e19..3c6946c566d73 100644 --- a/node_modules/@npmcli/agent/lib/dns.js +++ b/node_modules/@npmcli/agent/lib/dns.js @@ -3,49 +3,51 @@ const { LRUCache } = require('lru-cache') const dns = require('dns') -const defaultOptions = exports.defaultOptions = { - family: undefined, - hints: dns.ADDRCONFIG, - all: false, - verbatim: undefined, -} - -const lookupCache = exports.lookupCache = new LRUCache({ max: 50 }) - // this is a factory so that each request can have its own opts (i.e. ttl) // while still sharing the cache across all requests -exports.getLookup = (dnsOptions) => { - return (hostname, options, callback) => { - if (typeof options === 'function') { - callback = options - options = null - } else if (typeof options === 'number') { - options = { family: options } +const cache = new LRUCache({ max: 50 }) + +const getOptions = ({ + family = 0, + hints = dns.ADDRCONFIG, + all = false, + verbatim = undefined, + ttl = 5 * 60 * 1000, + lookup = dns.lookup, +}) => ({ + // hints and lookup are returned since both are top level properties to (net|tls).connect + hints, + lookup: (hostname, ...args) => { + const callback = args.pop() // callback is always last arg + const lookupOptions = args[0] ?? {} + + const options = { + family, + hints, + all, + verbatim, + ...(typeof lookupOptions === 'number' ? { family: lookupOptions } : lookupOptions), } - options = { ...defaultOptions, ...options } + const key = JSON.stringify({ hostname, ...options }) - const key = JSON.stringify({ - hostname, - family: options.family, - hints: options.hints, - all: options.all, - verbatim: options.verbatim, - }) - - if (lookupCache.has(key)) { - const [address, family] = lookupCache.get(key) - process.nextTick(callback, null, address, family) - return + if (cache.has(key)) { + const cached = cache.get(key) + return process.nextTick(callback, null, ...cached) } - dnsOptions.lookup(hostname, options, (err, address, family) => { + lookup(hostname, options, (err, ...result) => { if (err) { return callback(err) } - lookupCache.set(key, [address, family], { ttl: dnsOptions.ttl }) - return callback(null, address, family) + cache.set(key, result, { ttl }) + return callback(null, ...result) }) - } + }, +}) + +module.exports = { + cache, + getOptions, } diff --git a/node_modules/@npmcli/agent/lib/errors.js b/node_modules/@npmcli/agent/lib/errors.js index 9c664aeb39757..f41b4a065d713 100644 --- a/node_modules/@npmcli/agent/lib/errors.js +++ b/node_modules/@npmcli/agent/lib/errors.js @@ -1,5 +1,7 @@ 'use strict' +const { appendPort } = require('./util') + class InvalidProxyProtocolError extends Error { constructor (url) { super(`Invalid protocol \`${url.protocol}\` connecting to proxy \`${url.host}\``) @@ -8,17 +10,9 @@ class InvalidProxyProtocolError extends Error { } } -class InvalidProxyResponseError extends Error { - constructor (url, status) { - super(`Invalid status code \`${status}\` connecting to proxy \`${url.host}\``) - this.code = 'EINVALIDRESPONSE' - this.proxy = url - this.status = status - } -} - class ConnectionTimeoutError extends Error { - constructor (host) { + constructor ({ host, port }) { + host = appendPort(host, port) super(`Timeout connecting to host \`${host}\``) this.code = 'ECONNECTIONTIMEOUT' this.host = host @@ -26,7 +20,8 @@ class ConnectionTimeoutError extends Error { } class IdleTimeoutError extends Error { - constructor (host) { + constructor ({ host, port }) { + host = appendPort(host, port) super(`Idle timeout reached for host \`${host}\``) this.code = 'EIDLETIMEOUT' this.host = host @@ -34,36 +29,35 @@ class IdleTimeoutError extends Error { } class ResponseTimeoutError extends Error { - constructor (proxy, request) { + constructor (request, proxy) { let msg = 'Response timeout ' - if (proxy.url) { - msg += `from proxy \`${proxy.url.host}\` ` + if (proxy) { + msg += `from proxy \`${proxy.host}\` ` } msg += `connecting to host \`${request.host}\`` super(msg) this.code = 'ERESPONSETIMEOUT' - this.proxy = proxy.url + this.proxy = proxy this.request = request } } class TransferTimeoutError extends Error { - constructor (proxy, request) { + constructor (request, proxy) { let msg = 'Transfer timeout ' - if (proxy.url) { - msg += `from proxy \`${proxy.url.host}\` ` + if (proxy) { + msg += `from proxy \`${proxy.host}\` ` } msg += `for \`${request.host}\`` super(msg) this.code = 'ETRANSFERTIMEOUT' - this.proxy = proxy.url + this.proxy = proxy this.request = request } } module.exports = { InvalidProxyProtocolError, - InvalidProxyResponseError, ConnectionTimeoutError, IdleTimeoutError, ResponseTimeoutError, diff --git a/node_modules/@npmcli/agent/lib/http.js b/node_modules/@npmcli/agent/lib/http.js deleted file mode 100644 index 23512393caf3f..0000000000000 --- a/node_modules/@npmcli/agent/lib/http.js +++ /dev/null @@ -1,33 +0,0 @@ -'use strict' - -const http = require('http') - -const { getLookup } = require('./dns.js') -const { normalizeOptions } = require('./util.js') -const createProxy = require('./proxy/index.js') - -class HttpAgent extends http.Agent { - constructor (_options = {}) { - const options = normalizeOptions(_options) - super(options) - this.proxy = createProxy({ - agent: this, - lookup: getLookup(options.dns), - proxy: options.proxy, - secure: false, - }) - } - - createConnection (_options, callback) { - const options = normalizeOptions(_options) - return this.proxy.createConnection(options, callback) - } - - addRequest (request, _options) { - const options = normalizeOptions(_options) - super.addRequest(request, _options) - return this.proxy.addRequest(request, options) - } -} - -module.exports = HttpAgent diff --git a/node_modules/@npmcli/agent/lib/https.js b/node_modules/@npmcli/agent/lib/https.js deleted file mode 100644 index b544614d7f47f..0000000000000 --- a/node_modules/@npmcli/agent/lib/https.js +++ /dev/null @@ -1,33 +0,0 @@ -'use strict' - -const https = require('https') - -const { getLookup } = require('./dns.js') -const { normalizeOptions } = require('./util.js') -const createProxy = require('./proxy/index.js') - -class HttpsAgent extends https.Agent { - constructor (_options) { - const options = normalizeOptions(_options) - super(options) - this.proxy = createProxy({ - agent: this, - lookup: getLookup(options.dns), - proxy: options.proxy, - secure: true, - }) - } - - createConnection (_options, callback) { - const options = normalizeOptions(_options) - return this.proxy.createConnection(options, callback) - } - - addRequest (request, _options) { - const options = normalizeOptions(_options) - super.addRequest(request, options) - return this.proxy.addRequest(request, options) - } -} - -module.exports = HttpsAgent diff --git a/node_modules/@npmcli/agent/lib/index.js b/node_modules/@npmcli/agent/lib/index.js index a6f556964d86d..2cd69390ea77e 100644 --- a/node_modules/@npmcli/agent/lib/index.js +++ b/node_modules/@npmcli/agent/lib/index.js @@ -1,135 +1,46 @@ 'use strict' -const { normalizeOptions } = require('./util.js') -const HttpAgent = require('./http.js') -const HttpsAgent = require('./https.js') +const { LRUCache } = require('lru-cache') +const { urlify, cacheAgent } = require('./util') +const { normalizeOptions, cacheOptions } = require('./options') +const { getProxy, proxyCache } = require('./proxy.js') +const dns = require('./dns.js') +const { HttpAgent, HttpsAgent } = require('./agents.js') -const AgentCache = new Map() - -const proxyEnv = {} -for (const [key, value] of Object.entries(process.env)) { - const lowerKey = key.toLowerCase() - if (['https_proxy', 'http_proxy', 'proxy', 'no_proxy'].includes(lowerKey)) { - proxyEnv[lowerKey] = value - } -} - -const getAgent = (url, options) => { - url = new URL(url) - options = normalizeOptions(options) +const agentCache = new LRUCache({ max: 20 }) +const getAgent = (url, { agent: _agent, proxy: _proxy, noProxy, ..._options } = {}) => { // false has meaning so this can't be a simple truthiness check - if (options.agent != null) { - return options.agent - } - - const isHttps = url.protocol === 'https:' - - let proxy = options.proxy - if (!proxy) { - proxy = isHttps - ? proxyEnv.https_proxy - : (proxyEnv.https_proxy || proxyEnv.http_proxy || proxyEnv.proxy) - } - - if (proxy) { - proxy = new URL(proxy) - let noProxy = options.noProxy || proxyEnv.no_proxy - if (typeof noProxy === 'string') { - noProxy = noProxy.split(',').map((p) => p.trim()) - } - - if (noProxy) { - const hostSegments = url.hostname.split('.').reverse() - const matches = noProxy.some((no) => { - const noSegments = no.split('.').filter(Boolean).reverse() - if (!noSegments.length) { - return false - } - - for (let i = 0; i < noSegments.length; ++i) { - if (hostSegments[i] !== noSegments[i]) { - return false - } - } - - return true - }) - - if (matches) { - proxy = '' - } - } + if (_agent != null) { + return _agent } - const timeouts = [ - options.timeouts.connection || 0, - options.timeouts.idle || 0, - options.timeouts.response || 0, - options.timeouts.transfer || 0, - ].join('.') - - const maxSockets = options.maxSockets || 15 - - let proxyDescriptor = 'proxy:' - if (!proxy) { - proxyDescriptor += 'null' - } else { - proxyDescriptor += `${proxy.protocol}//` - let auth = '' - - if (proxy.username) { - auth += proxy.username - } - - if (proxy.password) { - auth += `:${proxy.password}` - } - - if (auth) { - proxyDescriptor += `${auth}@` - } - - proxyDescriptor += proxy.host - } - - const key = [ - `https:${isHttps}`, - proxyDescriptor, - `local-address:${options.localAddress || 'null'}`, - `strict-ssl:${isHttps ? options.rejectUnauthorized : 'false'}`, - `ca:${isHttps && options.ca || 'null'}`, - `cert:${isHttps && options.cert || 'null'}`, - `key:${isHttps && options.key || 'null'}`, - `timeouts:${timeouts}`, - `maxSockets:${maxSockets}`, - ].join(':') - - if (AgentCache.has(key)) { - return AgentCache.get(key) - } - - const agentOptions = { - ca: options.ca, - cert: options.cert, - key: options.key, - rejectUnauthorized: options.rejectUnauthorized, - maxSockets, - timeouts: options.timeouts, - localAddress: options.localAddress, - proxy, - } + url = urlify(url) - const agent = isHttps - ? new HttpsAgent(agentOptions) - : new HttpAgent(agentOptions) + const secure = url.protocol === 'https:' + const proxy = getProxy(url, { proxy: _proxy, noProxy }) + const options = { ...normalizeOptions(_options), proxy } - AgentCache.set(key, agent) - return agent + return cacheAgent({ + key: cacheOptions({ ...options, secure }), + cache: agentCache, + secure, + proxies: [HttpAgent, HttpsAgent], + }, options) } module.exports = { getAgent, HttpAgent, HttpsAgent, + cache: { + proxy: proxyCache, + agent: agentCache, + dns: dns.cache, + clear: () => { + proxyCache.clear() + agentCache.clear() + dns.cache.clear() + }, + }, } diff --git a/node_modules/@npmcli/agent/lib/options.js b/node_modules/@npmcli/agent/lib/options.js new file mode 100644 index 0000000000000..cd87c09d6a25a --- /dev/null +++ b/node_modules/@npmcli/agent/lib/options.js @@ -0,0 +1,74 @@ +'use strict' + +const dns = require('./dns') +const { createKey } = require('./util') + +const normalizeOptions = (opts) => { + const family = parseInt(opts.family ?? '0', 10) + const keepAlive = opts.keepAlive ?? true + + const normalized = { + // nodejs http agent options. these are all the defaults + // but kept here to increase the likelihood of cache hits + // https://nodejs.org/api/http.html#new-agentoptions + keepAliveMsecs: keepAlive ? 1000 : undefined, + maxSockets: opts.maxSockets ?? 15, + maxTotalSockets: Infinity, + maxFreeSockets: keepAlive ? 256 : undefined, + scheduling: 'fifo', + // then spread the rest of the options + ...opts, + // we already set these to their defaults that we want + family, + keepAlive, + // our custom timeout options + timeouts: { + // the standard timeout option is mapped to our idle timeout + // and then deleted below + idle: opts.timeout ?? 0, + connection: 0, + response: 0, + transfer: 0, + ...opts.timeouts, + }, + // get the dns options that go at the top level of socket connection + ...dns.getOptions({ family, ...opts.dns }), + } + + // remove timeout since we already used it to set our own idle timeout + delete normalized.timeout + + return normalized +} + +const cacheOptions = (options) => { + const { secure } = options + return createKey({ + secure: !!secure, + // socket connect options + family: options.family, + hints: options.hints, + localAddress: options.localAddress, + // tls specific connect options + strictSsl: secure ? !!options.rejectUnauthorized : false, + ca: secure ? options.ca : null, + cert: secure ? options.cert : null, + key: secure ? options.key : null, + // http agent options + keepAlive: options.keepAlive, + keepAliveMsecs: options.keepAliveMsecs, + maxSockets: options.maxSockets, + maxTotalSockets: options.maxTotalSockets, + maxFreeSockets: options.maxFreeSockets, + scheduling: options.scheduling, + // timeout options + timeouts: options.timeouts, + // proxy + proxy: options.proxy, + }) +} + +module.exports = { + normalizeOptions, + cacheOptions, +} diff --git a/node_modules/@npmcli/agent/lib/proxy.js b/node_modules/@npmcli/agent/lib/proxy.js new file mode 100644 index 0000000000000..81afdad74c1e5 --- /dev/null +++ b/node_modules/@npmcli/agent/lib/proxy.js @@ -0,0 +1,96 @@ +'use strict' + +const { HttpProxyAgent } = require('http-proxy-agent') +const { HttpsProxyAgent } = require('https-proxy-agent') +const { SocksProxyAgent } = require('socks-proxy-agent') +const { LRUCache } = require('lru-cache') +const { InvalidProxyProtocolError } = require('./errors.js') +const { urlify } = require('./util.js') + +const PROXY_CACHE = new LRUCache({ max: 20 }) + +const PROXY_ENV = (() => { + const keys = new Set(['https_proxy', 'http_proxy', 'proxy', 'no_proxy']) + const values = {} + for (let [key, value] of Object.entries(process.env)) { + key = key.toLowerCase() + if (keys.has(key)) { + values[key] = value + } + } + return values +})() + +const SOCKS_PROTOCOLS = new Set(SocksProxyAgent.protocols) +const SECURE_PROTOCOLS = new Set([...SocksProxyAgent.protocols, 'https']) + +const isSecureProxy = (url) => { + url = urlify(url) + const protocol = url.protocol.slice(0, -1) + return SECURE_PROTOCOLS.has(protocol) +} + +const getProxyType = (url) => { + url = urlify(url) + + const protocol = url.protocol.slice(0, -1) + if (SOCKS_PROTOCOLS.has(protocol)) { + return [SocksProxyAgent] + } + if (protocol === 'https' || protocol === 'http') { + return [HttpProxyAgent, HttpsProxyAgent] + } + + throw new InvalidProxyProtocolError(url) +} + +const isNoProxy = (url, noProxy) => { + if (typeof noProxy === 'string') { + noProxy = noProxy.split(',').map((p) => p.trim()).filter(Boolean) + } + + if (!noProxy || !noProxy.length) { + return false + } + + const hostSegments = url.hostname.split('.').reverse() + + return noProxy.some((no) => { + const noSegments = no.split('.').filter(Boolean).reverse() + if (!noSegments.length) { + return false + } + + for (let i = 0; i < noSegments.length; i++) { + if (hostSegments[i] !== noSegments[i]) { + return false + } + } + + return true + }) +} + +const getProxy = (url, { + proxy = PROXY_ENV.https_proxy, + noProxy = PROXY_ENV.no_proxy, +}) => { + url = urlify(url) + + if (!proxy && url.protocol !== 'https:') { + proxy = PROXY_ENV.http_proxy || PROXY_ENV.proxy + } + + if (!proxy || isNoProxy(url, noProxy)) { + return null + } + + return urlify(proxy) +} + +module.exports = { + getProxyType, + getProxy, + isSecureProxy, + proxyCache: PROXY_CACHE, +} diff --git a/node_modules/@npmcli/agent/lib/proxy/http.js b/node_modules/@npmcli/agent/lib/proxy/http.js deleted file mode 100644 index 8d092e963c084..0000000000000 --- a/node_modules/@npmcli/agent/lib/proxy/http.js +++ /dev/null @@ -1,146 +0,0 @@ -'use strict' - -const http = require('http') -const https = require('https') -const net = require('net') -const tls = require('tls') - -const { - ConnectionTimeoutError, - IdleTimeoutError, - InvalidProxyResponseError, - ResponseTimeoutError, - TransferTimeoutError, -} = require('../errors.js') - -// this proxy class uses the http CONNECT method -class HttpProxy { - constructor ({ agent, lookup, url, secure }) { - this.agent = agent - this.lookup = lookup - this.url = url - this.secure = secure - } - - createConnection (options, callback) { - const requestOptions = { - // pass createConnection so this request doesn't go through an agent - createConnection: (opts, cb) => { - // delete the path first, otherwise (net|tls).connect will try to open a unix socket - delete opts.path - // we also delete the timeout since we control it ourselves - delete opts.timeout - opts.family = this.agent.options.family - opts.lookup = this.lookup - - if (this.url.protocol === 'https:') { - return tls.connect(opts, cb) - } - - return net.connect(opts, cb) - }, - method: 'CONNECT', - host: this.url.hostname, - port: this.url.port, - servername: this.url.hostname, - path: `${options.host}:${options.port}`, - setHost: false, - timeout: options.timeout, - headers: { - connection: this.agent.keepAlive ? 'keep-alive' : 'close', - host: `${options.host}:${options.port}`, - }, - rejectUnauthorized: options.rejectUnauthorized, - } - - if (this.url.username || this.url.password) { - const username = decodeURIComponent(this.url.username) - const password = decodeURIComponent(this.url.password) - requestOptions.headers['proxy-authentication'] = - Buffer.from(`${username}:${password}`).toString('base64') - } - - let connectionTimeout - - const onConnect = (res, socket) => { - clearTimeout(connectionTimeout) - req.removeListener('error', onError) - - if (res.statusCode !== 200) { - return callback(new InvalidProxyResponseError(this.url, res.statusCode)) - } - - if (this.secure) { - socket = tls.connect({ ...options, socket }) - } - - socket.setKeepAlive(this.agent.keepAlive, this.agent.keepAliveMsecs) - socket.setNoDelay(this.agent.keepAlive) - - if (options.timeouts.idle) { - socket.setTimeout(options.timeouts.idle) - socket.once('timeout', () => { - socket.destroy(new IdleTimeoutError(this.url.host)) - }) - } - - return callback(null, socket) - } - - const onError = (err) => { - req.removeListener('connect', onConnect) - return callback(err) - } - - const req = this.secure - ? https.request(requestOptions) - : http.request(requestOptions) - - req.once('connect', onConnect) - req.once('error', onError) - req.end() - - if (options.timeouts.connection) { - connectionTimeout = setTimeout(() => { - return callback(new ConnectionTimeoutError(this.url.host)) - }, options.timeouts.connection) - } - } - - addRequest (request, options) { - if (this.agent.options.timeouts.response) { - let responseTimeout - - const onFinish = () => { - responseTimeout = setTimeout(() => { - request.destroy(new ResponseTimeoutError(this, request)) - }, this.agent.options.timeouts.response) - } - - const onResponse = () => { - clearTimeout(responseTimeout) - } - - request.once('finish', onFinish) - request.once('response', onResponse) - } - - if (this.agent.options.timeouts.transfer) { - let transferTimeout - - const onResponse = (res) => { - transferTimeout = setTimeout(() => { - res.destroy(new TransferTimeoutError(this, request)) - }, this.agent.options.timeouts.transfer) - - res.once('close', () => { - clearTimeout(transferTimeout) - }) - } - - request.once('response', onResponse) - } - } -} - -module.exports = HttpProxy diff --git a/node_modules/@npmcli/agent/lib/proxy/index.js b/node_modules/@npmcli/agent/lib/proxy/index.js deleted file mode 100644 index 87f628c5bbf94..0000000000000 --- a/node_modules/@npmcli/agent/lib/proxy/index.js +++ /dev/null @@ -1,25 +0,0 @@ -'use strict' - -const { InvalidProxyProtocolError } = require('../errors.js') -const HttpProxy = require('./http.js') -const NullProxy = require('./null.js') -const SocksProxy = require('./socks.js') - -const createProxy = ({ agent, lookup, proxy, secure }) => { - if (!proxy) { - return new NullProxy({ agent, lookup, secure }) - } - - const parsed = new URL(proxy) - if (parsed.protocol === 'http:' || parsed.protocol === 'https:') { - return new HttpProxy({ agent, lookup, url: parsed, secure }) - } - - if (parsed.protocol.startsWith('socks')) { - return new SocksProxy({ agent, lookup, url: parsed, secure }) - } - - throw new InvalidProxyProtocolError(parsed) -} - -module.exports = createProxy diff --git a/node_modules/@npmcli/agent/lib/proxy/null.js b/node_modules/@npmcli/agent/lib/proxy/null.js deleted file mode 100644 index d2b2f6f777e92..0000000000000 --- a/node_modules/@npmcli/agent/lib/proxy/null.js +++ /dev/null @@ -1,97 +0,0 @@ -'use strict' - -const net = require('net') -const tls = require('tls') - -const { - ConnectionTimeoutError, - IdleTimeoutError, - ResponseTimeoutError, - TransferTimeoutError, -} = require('../errors.js') - -class NullProxy { - constructor ({ agent, lookup, secure }) { - this.agent = agent - this.lookup = lookup - this.secure = secure - } - - createConnection (options, callback) { - const socket = this.secure - ? tls.connect({ ...options, family: this.agent.options.family, lookup: this.lookup }) - : net.connect({ ...options, family: this.agent.options.family, lookup: this.lookup }) - - socket.setKeepAlive(this.agent.keepAlive, this.agent.keepAliveMsecs) - socket.setNoDelay(this.agent.keepAlive) - - let connectionTimeout - - if (options.timeouts.connection) { - connectionTimeout = setTimeout(() => { - callback(new ConnectionTimeoutError(options.host)) - }, options.timeouts.connection) - } - - if (options.timeouts.idle) { - socket.setTimeout(options.timeouts.idle) - socket.once('timeout', () => { - socket.destroy(new IdleTimeoutError(options.host)) - }) - } - - const onConnect = () => { - clearTimeout(connectionTimeout) - socket.removeListener('error', onError) - callback(null, socket) - } - - const onError = (err) => { - socket.removeListener('connect', onConnect) - callback(err) - } - - socket.once('error', onError) - socket.once(this.secure ? 'secureConnect' : 'connect', onConnect) - } - - addRequest (request, options) { - if (this.agent.options.timeouts.response) { - let responseTimeout - - const onFinish = () => { - responseTimeout = setTimeout(() => { - request.destroy(new ResponseTimeoutError(this, request)) - }, this.agent.options.timeouts.response) - } - - const onResponse = () => { - clearTimeout(responseTimeout) - } - - request.once('finish', onFinish) - request.once('response', onResponse) - } - - if (this.agent.options.timeouts.transfer) { - let transferTimeout - - const onResponse = (res) => { - transferTimeout = setTimeout(() => { - // swallow the error event on the request, this allows the one on the response - // to make it to the end user - request.once('error', () => {}) - res.destroy(new TransferTimeoutError(this, request)) - }, this.agent.options.timeouts.transfer) - - res.once('close', () => { - clearTimeout(transferTimeout) - }) - } - - request.once('response', onResponse) - } - } -} - -module.exports = NullProxy diff --git a/node_modules/@npmcli/agent/lib/proxy/socks.js b/node_modules/@npmcli/agent/lib/proxy/socks.js deleted file mode 100644 index 8cad7148e9227..0000000000000 --- a/node_modules/@npmcli/agent/lib/proxy/socks.js +++ /dev/null @@ -1,153 +0,0 @@ -'use strict' - -const { SocksClient } = require('socks') -const tls = require('tls') - -const { - ConnectionTimeoutError, - IdleTimeoutError, - InvalidProxyProtocolError, - ResponseTimeoutError, - TransferTimeoutError, -} = require('../errors.js') - -class SocksProxy { - constructor ({ agent, lookup, secure, url }) { - this.agent = agent - this.lookup = lookup - this.secure = secure - this.url = url - if (!this.url.port) { - this.url.port = 1080 - } - - if (this.url.protocol === 'socks4:') { - this.shouldLookup = true - this.type = 4 - } else if (this.url.protocol === 'socks4a:') { - this.shouldLookup = false - this.type = 4 - } else if (this.url.protocol === 'socks5:') { - this.shouldLookup = true - this.type = 5 - } else if (this.url.protocol === 'socks5h:' || this.url.protocol === 'socks:') { - this.shouldLookup = false - this.type = 5 - } else { - throw new InvalidProxyProtocolError(this.url) - } - } - - createConnection (options, callback) { - const socksOptions = { - proxy: { - host: this.url.hostname, - port: parseInt(this.url.port, 10), - type: this.type, - userId: this.url.username, - password: this.url.password, - }, - destination: { - host: options.host, - port: parseInt(options.port, 10), - }, - command: 'connect', - socket_options: { - family: this.agent.options.family, - lookup: this.lookup, - }, - } - - const connect = () => { - let connectionTimeout - const socksClient = new SocksClient(socksOptions) - - const onError = (err) => { - socksClient.removeListener('established', onEstablished) - return callback(err) - } - - const onEstablished = (connection) => { - clearTimeout(connectionTimeout) - socksClient.removeListener('error', onError) - - if (this.secure) { - connection.socket = tls.connect({ ...options, socket: connection.socket }) - } - - connection.socket.setKeepAlive(this.agent.keepAlive, this.agent.keepAliveMsecs) - connection.socket.setNoDelay(this.agent.keepAlive) - - if (options.timeouts.idle) { - connection.socket.setTimeout(options.timeouts.idle) - connection.socket.once('timeout', () => { - connection.socket.destroy(new IdleTimeoutError(this.url.host)) - }) - } - - return callback(null, connection.socket) - } - - socksClient.once('error', onError) - socksClient.once('established', onEstablished) - - if (options.timeouts.connection) { - connectionTimeout = setTimeout(() => { - return callback(new ConnectionTimeoutError(this.url.host)) - }, options.timeouts.connection) - } - - socksClient.connect() - } - - if (!this.shouldLookup) { - return connect() - } - - this.lookup(options.host, (err, result) => { - if (err) { - return callback(err) - } - - socksOptions.destination.host = result - connect() - }) - } - - addRequest (request, options) { - if (this.agent.options.timeouts.response) { - let responseTimeout - - const onFinish = () => { - responseTimeout = setTimeout(() => { - request.destroy(new ResponseTimeoutError(this, request)) - }, this.agent.options.timeouts.response) - } - - const onResponse = () => { - clearTimeout(responseTimeout) - } - - request.once('finish', onFinish) - request.once('response', onResponse) - } - - if (this.agent.options.timeouts.transfer) { - let transferTimeout - - const onResponse = (res) => { - transferTimeout = setTimeout(() => { - res.destroy(new TransferTimeoutError(this, request)) - }, this.agent.options.timeouts.transfer) - - res.once('close', () => { - clearTimeout(transferTimeout) - }) - } - - request.once('response', onResponse) - } - } -} - -module.exports = SocksProxy diff --git a/node_modules/@npmcli/agent/lib/util.js b/node_modules/@npmcli/agent/lib/util.js index 512207084d23e..6d42a2e202c1f 100644 --- a/node_modules/@npmcli/agent/lib/util.js +++ b/node_modules/@npmcli/agent/lib/util.js @@ -1,33 +1,84 @@ 'use strict' -const dns = require('dns') +const timers = require('timers/promises') -const normalizeOptions = (_options) => { - const options = { ..._options } +const createKey = (obj) => { + let key = '' + const sorted = Object.entries(obj).sort((a, b) => a[0] - b[0]) + for (let [k, v] of sorted) { + if (v == null) { + v = 'null' + } else if (v instanceof URL) { + v = v.toString() + } else if (typeof v === 'object') { + v = createKey(v) + } + key += `${k}:${v}:` + } + return key +} - if (typeof options.keepAlive === 'undefined') { - options.keepAlive = true +const createTimeout = (delay, signal) => { + if (!delay) { + return signal ? new Promise(() => {}) : null } - if (!options.timeouts) { - options.timeouts = {} + if (!signal) { + let timeout + return { + start: (cb) => (timeout = setTimeout(cb, delay)), + clear: () => clearTimeout(timeout), + } } - if (options.timeout) { - options.timeouts.idle = options.timeout - delete options.timeout + return timers.setTimeout(delay, null, signal) + .then(() => { + throw new Error() + }).catch((err) => { + if (err.name === 'AbortError') { + return + } + throw err + }) +} + +const abortRace = async (promises, ac = new AbortController()) => { + let res + try { + res = await Promise.race(promises.map((p) => p(ac))) + ac.abort() + } catch (err) { + ac.abort() + throw err } + return res +} + +const urlify = (url) => typeof url === 'string' ? new URL(url) : url - options.family = !isNaN(+options.family) ? +options.family : 0 - options.dns = { - ttl: 5 * 60 * 1000, - lookup: dns.lookup, - ...options.dns, +const appendPort = (host, port) => { + // istanbul ignore next + if (port) { + host += `:${port}` } + return host +} - return options +const cacheAgent = ({ key, cache, secure, proxies }, ...args) => { + if (cache.has(key)) { + return cache.get(key) + } + const Ctor = (secure ? proxies[1] : proxies[0]) ?? proxies[0] + const agent = new Ctor(...args) + cache.set(key, agent) + return agent } module.exports = { - normalizeOptions, + createKey, + createTimeout, + abortRace, + urlify, + cacheAgent, + appendPort, } diff --git a/node_modules/@npmcli/agent/node_modules/agent-base/dist/helpers.js b/node_modules/@npmcli/agent/node_modules/agent-base/dist/helpers.js new file mode 100644 index 0000000000000..ef3f92022d455 --- /dev/null +++ b/node_modules/@npmcli/agent/node_modules/agent-base/dist/helpers.js @@ -0,0 +1,66 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.req = exports.json = exports.toBuffer = void 0; +const http = __importStar(require("http")); +const https = __importStar(require("https")); +async function toBuffer(stream) { + let length = 0; + const chunks = []; + for await (const chunk of stream) { + length += chunk.length; + chunks.push(chunk); + } + return Buffer.concat(chunks, length); +} +exports.toBuffer = toBuffer; +// eslint-disable-next-line @typescript-eslint/no-explicit-any +async function json(stream) { + const buf = await toBuffer(stream); + const str = buf.toString('utf8'); + try { + return JSON.parse(str); + } + catch (_err) { + const err = _err; + err.message += ` (input: ${str})`; + throw err; + } +} +exports.json = json; +function req(url, opts = {}) { + const href = typeof url === 'string' ? url : url.href; + const req = (href.startsWith('https:') ? https : http).request(url, opts); + const promise = new Promise((resolve, reject) => { + req + .once('response', resolve) + .once('error', reject) + .end(); + }); + req.then = promise.then.bind(promise); + return req; +} +exports.req = req; +//# sourceMappingURL=helpers.js.map \ No newline at end of file diff --git a/node_modules/@npmcli/agent/node_modules/agent-base/dist/index.js b/node_modules/@npmcli/agent/node_modules/agent-base/dist/index.js new file mode 100644 index 0000000000000..7bafc8c68604f --- /dev/null +++ b/node_modules/@npmcli/agent/node_modules/agent-base/dist/index.js @@ -0,0 +1,112 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.Agent = void 0; +const http = __importStar(require("http")); +__exportStar(require("./helpers"), exports); +const INTERNAL = Symbol('AgentBaseInternalState'); +class Agent extends http.Agent { + constructor(opts) { + super(opts); + this[INTERNAL] = {}; + } + /** + * Determine whether this is an `http` or `https` request. + */ + isSecureEndpoint(options) { + if (options) { + // First check the `secureEndpoint` property explicitly, since this + // means that a parent `Agent` is "passing through" to this instance. + // eslint-disable-next-line @typescript-eslint/no-explicit-any + if (typeof options.secureEndpoint === 'boolean') { + return options.secureEndpoint; + } + // If no explicit `secure` endpoint, check if `protocol` property is + // set. This will usually be the case since using a full string URL + // or `URL` instance should be the most common usage. + if (typeof options.protocol === 'string') { + return options.protocol === 'https:'; + } + } + // Finally, if no `protocol` property was set, then fall back to + // checking the stack trace of the current call stack, and try to + // detect the "https" module. + const { stack } = new Error(); + if (typeof stack !== 'string') + return false; + return stack + .split('\n') + .some((l) => l.indexOf('(https.js:') !== -1 || + l.indexOf('node:https:') !== -1); + } + createSocket(req, options, cb) { + const connectOpts = { + ...options, + secureEndpoint: this.isSecureEndpoint(options), + }; + Promise.resolve() + .then(() => this.connect(req, connectOpts)) + .then((socket) => { + if (socket instanceof http.Agent) { + // @ts-expect-error `addRequest()` isn't defined in `@types/node` + return socket.addRequest(req, connectOpts); + } + this[INTERNAL].currentSocket = socket; + // @ts-expect-error `createSocket()` isn't defined in `@types/node` + super.createSocket(req, options, cb); + }, cb); + } + createConnection() { + const socket = this[INTERNAL].currentSocket; + this[INTERNAL].currentSocket = undefined; + if (!socket) { + throw new Error('No socket was returned in the `connect()` function'); + } + return socket; + } + get defaultPort() { + return (this[INTERNAL].defaultPort ?? + (this.protocol === 'https:' ? 443 : 80)); + } + set defaultPort(v) { + if (this[INTERNAL]) { + this[INTERNAL].defaultPort = v; + } + } + get protocol() { + return (this[INTERNAL].protocol ?? + (this.isSecureEndpoint() ? 'https:' : 'http:')); + } + set protocol(v) { + if (this[INTERNAL]) { + this[INTERNAL].protocol = v; + } + } +} +exports.Agent = Agent; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/node_modules/@npmcli/agent/node_modules/agent-base/package.json b/node_modules/@npmcli/agent/node_modules/agent-base/package.json new file mode 100644 index 0000000000000..7178f4983f4fb --- /dev/null +++ b/node_modules/@npmcli/agent/node_modules/agent-base/package.json @@ -0,0 +1,49 @@ +{ + "name": "agent-base", + "version": "7.1.0", + "description": "Turn a function into an `http.Agent` instance", + "main": "./dist/index.js", + "types": "./dist/index.d.ts", + "files": [ + "dist" + ], + "repository": { + "type": "git", + "url": "https://github.com/TooTallNate/proxy-agents.git", + "directory": "packages/agent-base" + }, + "keywords": [ + "http", + "agent", + "base", + "barebones", + "https" + ], + "author": "Nathan Rajlich (http://n8.io/)", + "license": "MIT", + "dependencies": { + "debug": "^4.3.4" + }, + "devDependencies": { + "@types/debug": "^4.1.7", + "@types/jest": "^29.5.1", + "@types/node": "^14.18.45", + "@types/semver": "^7.3.13", + "@types/ws": "^6.0.4", + "async-listen": "^3.0.0", + "jest": "^29.5.0", + "ts-jest": "^29.1.0", + "typescript": "^5.0.4", + "ws": "^3.3.3", + "tsconfig": "0.0.0" + }, + "engines": { + "node": ">= 14" + }, + "scripts": { + "build": "tsc", + "test": "jest --env node --verbose --bail", + "lint": "eslint . --ext .ts", + "pack": "node ../../scripts/pack.mjs" + } +} \ No newline at end of file diff --git a/node_modules/@npmcli/agent/node_modules/http-proxy-agent/LICENSE b/node_modules/@npmcli/agent/node_modules/http-proxy-agent/LICENSE new file mode 100644 index 0000000000000..aad14057fad57 --- /dev/null +++ b/node_modules/@npmcli/agent/node_modules/http-proxy-agent/LICENSE @@ -0,0 +1,25 @@ +License +------- + +(The MIT License) + +Copyright (c) 2013 Nathan Rajlich <nathan@tootallnate.net> + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/@npmcli/agent/node_modules/http-proxy-agent/dist/index.js b/node_modules/@npmcli/agent/node_modules/http-proxy-agent/dist/index.js new file mode 100644 index 0000000000000..4a7daf6156f94 --- /dev/null +++ b/node_modules/@npmcli/agent/node_modules/http-proxy-agent/dist/index.js @@ -0,0 +1,147 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.HttpProxyAgent = void 0; +const net = __importStar(require("net")); +const tls = __importStar(require("tls")); +const debug_1 = __importDefault(require("debug")); +const events_1 = require("events"); +const agent_base_1 = require("agent-base"); +const debug = (0, debug_1.default)('http-proxy-agent'); +/** + * The `HttpProxyAgent` implements an HTTP Agent subclass that connects + * to the specified "HTTP proxy server" in order to proxy HTTP requests. + */ +class HttpProxyAgent extends agent_base_1.Agent { + constructor(proxy, opts) { + super(opts); + this.proxy = typeof proxy === 'string' ? new URL(proxy) : proxy; + this.proxyHeaders = opts?.headers ?? {}; + debug('Creating new HttpProxyAgent instance: %o', this.proxy.href); + // Trim off the brackets from IPv6 addresses + const host = (this.proxy.hostname || this.proxy.host).replace(/^\[|\]$/g, ''); + const port = this.proxy.port + ? parseInt(this.proxy.port, 10) + : this.proxy.protocol === 'https:' + ? 443 + : 80; + this.connectOpts = { + ...(opts ? omit(opts, 'headers') : null), + host, + port, + }; + } + addRequest(req, opts) { + req._header = null; + this.setRequestProps(req, opts); + // @ts-expect-error `addRequest()` isn't defined in `@types/node` + super.addRequest(req, opts); + } + setRequestProps(req, opts) { + const { proxy } = this; + const protocol = opts.secureEndpoint ? 'https:' : 'http:'; + const hostname = req.getHeader('host') || 'localhost'; + const base = `${protocol}//${hostname}`; + const url = new URL(req.path, base); + if (opts.port !== 80) { + url.port = String(opts.port); + } + // Change the `http.ClientRequest` instance's "path" field + // to the absolute path of the URL that will be requested. + req.path = String(url); + // Inject the `Proxy-Authorization` header if necessary. + const headers = typeof this.proxyHeaders === 'function' + ? this.proxyHeaders() + : { ...this.proxyHeaders }; + if (proxy.username || proxy.password) { + const auth = `${decodeURIComponent(proxy.username)}:${decodeURIComponent(proxy.password)}`; + headers['Proxy-Authorization'] = `Basic ${Buffer.from(auth).toString('base64')}`; + } + if (!headers['Proxy-Connection']) { + headers['Proxy-Connection'] = this.keepAlive + ? 'Keep-Alive' + : 'close'; + } + for (const name of Object.keys(headers)) { + const value = headers[name]; + if (value) { + req.setHeader(name, value); + } + } + } + async connect(req, opts) { + req._header = null; + if (!req.path.includes('://')) { + this.setRequestProps(req, opts); + } + // At this point, the http ClientRequest's internal `_header` field + // might have already been set. If this is the case then we'll need + // to re-generate the string since we just changed the `req.path`. + let first; + let endOfHeaders; + debug('Regenerating stored HTTP header string for request'); + req._implicitHeader(); + if (req.outputData && req.outputData.length > 0) { + debug('Patching connection write() output buffer with updated header'); + first = req.outputData[0].data; + endOfHeaders = first.indexOf('\r\n\r\n') + 4; + req.outputData[0].data = + req._header + first.substring(endOfHeaders); + debug('Output buffer: %o', req.outputData[0].data); + } + // Create a socket connection to the proxy server. + let socket; + if (this.proxy.protocol === 'https:') { + debug('Creating `tls.Socket`: %o', this.connectOpts); + socket = tls.connect(this.connectOpts); + } + else { + debug('Creating `net.Socket`: %o', this.connectOpts); + socket = net.connect(this.connectOpts); + } + // Wait for the socket's `connect` event, so that this `callback()` + // function throws instead of the `http` request machinery. This is + // important for i.e. `PacProxyAgent` which determines a failed proxy + // connection via the `callback()` function throwing. + await (0, events_1.once)(socket, 'connect'); + return socket; + } +} +HttpProxyAgent.protocols = ['http', 'https']; +exports.HttpProxyAgent = HttpProxyAgent; +function omit(obj, ...keys) { + const ret = {}; + let key; + for (key in obj) { + if (!keys.includes(key)) { + ret[key] = obj[key]; + } + } + return ret; +} +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/node_modules/@npmcli/agent/node_modules/http-proxy-agent/package.json b/node_modules/@npmcli/agent/node_modules/http-proxy-agent/package.json new file mode 100644 index 0000000000000..08c650cbb22aa --- /dev/null +++ b/node_modules/@npmcli/agent/node_modules/http-proxy-agent/package.json @@ -0,0 +1,47 @@ +{ + "name": "http-proxy-agent", + "version": "7.0.0", + "description": "An HTTP(s) proxy `http.Agent` implementation for HTTP", + "main": "./dist/index.js", + "types": "./dist/index.d.ts", + "files": [ + "dist" + ], + "repository": { + "type": "git", + "url": "https://github.com/TooTallNate/proxy-agents.git", + "directory": "packages/http-proxy-agent" + }, + "keywords": [ + "http", + "proxy", + "endpoint", + "agent" + ], + "author": "Nathan Rajlich (http://n8.io/)", + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "devDependencies": { + "@types/debug": "^4.1.7", + "@types/jest": "^29.5.1", + "@types/node": "^14.18.45", + "async-listen": "^3.0.0", + "jest": "^29.5.0", + "ts-jest": "^29.1.0", + "typescript": "^5.0.4", + "proxy": "2.1.1", + "tsconfig": "0.0.0" + }, + "engines": { + "node": ">= 14" + }, + "scripts": { + "build": "tsc", + "test": "jest --env node --verbose --bail", + "lint": "eslint . --ext .ts", + "pack": "node ../../scripts/pack.mjs" + } +} \ No newline at end of file diff --git a/node_modules/@npmcli/agent/node_modules/https-proxy-agent/dist/index.js b/node_modules/@npmcli/agent/node_modules/https-proxy-agent/dist/index.js new file mode 100644 index 0000000000000..e3bbfe632c454 --- /dev/null +++ b/node_modules/@npmcli/agent/node_modules/https-proxy-agent/dist/index.js @@ -0,0 +1,170 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.HttpsProxyAgent = void 0; +const net = __importStar(require("net")); +const tls = __importStar(require("tls")); +const assert_1 = __importDefault(require("assert")); +const debug_1 = __importDefault(require("debug")); +const agent_base_1 = require("agent-base"); +const parse_proxy_response_1 = require("./parse-proxy-response"); +const debug = (0, debug_1.default)('https-proxy-agent'); +/** + * The `HttpsProxyAgent` implements an HTTP Agent subclass that connects to + * the specified "HTTP(s) proxy server" in order to proxy HTTPS requests. + * + * Outgoing HTTP requests are first tunneled through the proxy server using the + * `CONNECT` HTTP request method to establish a connection to the proxy server, + * and then the proxy server connects to the destination target and issues the + * HTTP request from the proxy server. + * + * `https:` requests have their socket connection upgraded to TLS once + * the connection to the proxy server has been established. + */ +class HttpsProxyAgent extends agent_base_1.Agent { + constructor(proxy, opts) { + super(opts); + this.options = { path: undefined }; + this.proxy = typeof proxy === 'string' ? new URL(proxy) : proxy; + this.proxyHeaders = opts?.headers ?? {}; + debug('Creating new HttpsProxyAgent instance: %o', this.proxy.href); + // Trim off the brackets from IPv6 addresses + const host = (this.proxy.hostname || this.proxy.host).replace(/^\[|\]$/g, ''); + const port = this.proxy.port + ? parseInt(this.proxy.port, 10) + : this.proxy.protocol === 'https:' + ? 443 + : 80; + this.connectOpts = { + // Attempt to negotiate http/1.1 for proxy servers that support http/2 + ALPNProtocols: ['http/1.1'], + ...(opts ? omit(opts, 'headers') : null), + host, + port, + }; + } + /** + * Called when the node-core HTTP client library is creating a + * new HTTP request. + */ + async connect(req, opts) { + const { proxy } = this; + if (!opts.host) { + throw new TypeError('No "host" provided'); + } + // Create a socket connection to the proxy server. + let socket; + if (proxy.protocol === 'https:') { + debug('Creating `tls.Socket`: %o', this.connectOpts); + socket = tls.connect(this.connectOpts); + } + else { + debug('Creating `net.Socket`: %o', this.connectOpts); + socket = net.connect(this.connectOpts); + } + const headers = typeof this.proxyHeaders === 'function' + ? this.proxyHeaders() + : { ...this.proxyHeaders }; + const host = net.isIPv6(opts.host) ? `[${opts.host}]` : opts.host; + let payload = `CONNECT ${host}:${opts.port} HTTP/1.1\r\n`; + // Inject the `Proxy-Authorization` header if necessary. + if (proxy.username || proxy.password) { + const auth = `${decodeURIComponent(proxy.username)}:${decodeURIComponent(proxy.password)}`; + headers['Proxy-Authorization'] = `Basic ${Buffer.from(auth).toString('base64')}`; + } + headers.Host = `${host}:${opts.port}`; + if (!headers['Proxy-Connection']) { + headers['Proxy-Connection'] = this.keepAlive + ? 'Keep-Alive' + : 'close'; + } + for (const name of Object.keys(headers)) { + payload += `${name}: ${headers[name]}\r\n`; + } + const proxyResponsePromise = (0, parse_proxy_response_1.parseProxyResponse)(socket); + socket.write(`${payload}\r\n`); + const { connect, buffered } = await proxyResponsePromise; + req.emit('proxyConnect', connect); + this.emit('proxyConnect', connect, req); + if (connect.statusCode === 200) { + req.once('socket', resume); + if (opts.secureEndpoint) { + // The proxy is connecting to a TLS server, so upgrade + // this socket connection to a TLS connection. + debug('Upgrading socket connection to TLS'); + const servername = opts.servername || opts.host; + return tls.connect({ + ...omit(opts, 'host', 'path', 'port'), + socket, + servername: net.isIP(servername) ? undefined : servername, + }); + } + return socket; + } + // Some other status code that's not 200... need to re-play the HTTP + // header "data" events onto the socket once the HTTP machinery is + // attached so that the node core `http` can parse and handle the + // error status code. + // Close the original socket, and a new "fake" socket is returned + // instead, so that the proxy doesn't get the HTTP request + // written to it (which may contain `Authorization` headers or other + // sensitive data). + // + // See: https://hackerone.com/reports/541502 + socket.destroy(); + const fakeSocket = new net.Socket({ writable: false }); + fakeSocket.readable = true; + // Need to wait for the "socket" event to re-play the "data" events. + req.once('socket', (s) => { + debug('Replaying proxy buffer for failed request'); + (0, assert_1.default)(s.listenerCount('data') > 0); + // Replay the "buffered" Buffer onto the fake `socket`, since at + // this point the HTTP module machinery has been hooked up for + // the user. + s.push(buffered); + s.push(null); + }); + return fakeSocket; + } +} +HttpsProxyAgent.protocols = ['http', 'https']; +exports.HttpsProxyAgent = HttpsProxyAgent; +function resume(socket) { + socket.resume(); +} +function omit(obj, ...keys) { + const ret = {}; + let key; + for (key in obj) { + if (!keys.includes(key)) { + ret[key] = obj[key]; + } + } + return ret; +} +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/node_modules/@npmcli/agent/node_modules/https-proxy-agent/dist/parse-proxy-response.js b/node_modules/@npmcli/agent/node_modules/https-proxy-agent/dist/parse-proxy-response.js new file mode 100644 index 0000000000000..a28f1d811805f --- /dev/null +++ b/node_modules/@npmcli/agent/node_modules/https-proxy-agent/dist/parse-proxy-response.js @@ -0,0 +1,98 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.parseProxyResponse = void 0; +const debug_1 = __importDefault(require("debug")); +const debug = (0, debug_1.default)('https-proxy-agent:parse-proxy-response'); +function parseProxyResponse(socket) { + return new Promise((resolve, reject) => { + // we need to buffer any HTTP traffic that happens with the proxy before we get + // the CONNECT response, so that if the response is anything other than an "200" + // response code, then we can re-play the "data" events on the socket once the + // HTTP parser is hooked up... + let buffersLength = 0; + const buffers = []; + function read() { + const b = socket.read(); + if (b) + ondata(b); + else + socket.once('readable', read); + } + function cleanup() { + socket.removeListener('end', onend); + socket.removeListener('error', onerror); + socket.removeListener('readable', read); + } + function onend() { + cleanup(); + debug('onend'); + reject(new Error('Proxy connection ended before receiving CONNECT response')); + } + function onerror(err) { + cleanup(); + debug('onerror %o', err); + reject(err); + } + function ondata(b) { + buffers.push(b); + buffersLength += b.length; + const buffered = Buffer.concat(buffers, buffersLength); + const endOfHeaders = buffered.indexOf('\r\n\r\n'); + if (endOfHeaders === -1) { + // keep buffering + debug('have not received end of HTTP headers yet...'); + read(); + return; + } + const headerParts = buffered.slice(0, endOfHeaders).toString('ascii').split('\r\n'); + const firstLine = headerParts.shift(); + if (!firstLine) { + socket.destroy(); + return reject(new Error('No header received from proxy CONNECT response')); + } + const firstLineParts = firstLine.split(' '); + const statusCode = +firstLineParts[1]; + const statusText = firstLineParts.slice(2).join(' '); + const headers = {}; + for (const header of headerParts) { + if (!header) + continue; + const firstColon = header.indexOf(':'); + if (firstColon === -1) { + socket.destroy(); + return reject(new Error(`Invalid header from proxy CONNECT response: "${header}"`)); + } + const key = header.slice(0, firstColon).toLowerCase(); + const value = header.slice(firstColon + 1).trimStart(); + const current = headers[key]; + if (typeof current === 'string') { + headers[key] = [current, value]; + } + else if (Array.isArray(current)) { + current.push(value); + } + else { + headers[key] = value; + } + } + debug('got proxy server response: %o %o', firstLine, headers); + cleanup(); + resolve({ + connect: { + statusCode, + statusText, + headers, + }, + buffered, + }); + } + socket.on('error', onerror); + socket.on('end', onend); + read(); + }); +} +exports.parseProxyResponse = parseProxyResponse; +//# sourceMappingURL=parse-proxy-response.js.map \ No newline at end of file diff --git a/node_modules/@npmcli/agent/node_modules/https-proxy-agent/package.json b/node_modules/@npmcli/agent/node_modules/https-proxy-agent/package.json new file mode 100644 index 0000000000000..fc5f988d3b02b --- /dev/null +++ b/node_modules/@npmcli/agent/node_modules/https-proxy-agent/package.json @@ -0,0 +1,50 @@ +{ + "name": "https-proxy-agent", + "version": "7.0.1", + "description": "An HTTP(s) proxy `http.Agent` implementation for HTTPS", + "main": "./dist/index.js", + "types": "./dist/index.d.ts", + "files": [ + "dist" + ], + "repository": { + "type": "git", + "url": "https://github.com/TooTallNate/proxy-agents.git", + "directory": "packages/https-proxy-agent" + }, + "keywords": [ + "https", + "proxy", + "endpoint", + "agent" + ], + "author": "Nathan Rajlich (http://n8.io/)", + "license": "MIT", + "dependencies": { + "agent-base": "^7.0.2", + "debug": "4" + }, + "devDependencies": { + "@types/async-retry": "^1.4.5", + "@types/debug": "4", + "@types/jest": "^29.5.1", + "@types/node": "^14.18.45", + "async-listen": "^3.0.0", + "async-retry": "^1.3.3", + "jest": "^29.5.0", + "ts-jest": "^29.1.0", + "typescript": "^5.0.4", + "proxy": "2.1.1", + "tsconfig": "0.0.0" + }, + "engines": { + "node": ">= 14" + }, + "scripts": { + "build": "tsc", + "test": "jest --env node --verbose --bail test/test.ts", + "test-e2e": "jest --env node --verbose --bail test/e2e.test.ts", + "lint": "eslint --ext .ts", + "pack": "node ../../scripts/pack.mjs" + } +} \ No newline at end of file diff --git a/node_modules/@npmcli/agent/node_modules/socks-proxy-agent/dist/index.js b/node_modules/@npmcli/agent/node_modules/socks-proxy-agent/dist/index.js new file mode 100644 index 0000000000000..8189e014c13a0 --- /dev/null +++ b/node_modules/@npmcli/agent/node_modules/socks-proxy-agent/dist/index.js @@ -0,0 +1,181 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.SocksProxyAgent = void 0; +const socks_1 = require("socks"); +const agent_base_1 = require("agent-base"); +const debug_1 = __importDefault(require("debug")); +const dns = __importStar(require("dns")); +const net = __importStar(require("net")); +const tls = __importStar(require("tls")); +const debug = (0, debug_1.default)('socks-proxy-agent'); +function parseSocksURL(url) { + let lookup = false; + let type = 5; + const host = url.hostname; + // From RFC 1928, Section 3: https://tools.ietf.org/html/rfc1928#section-3 + // "The SOCKS service is conventionally located on TCP port 1080" + const port = parseInt(url.port, 10) || 1080; + // figure out if we want socks v4 or v5, based on the "protocol" used. + // Defaults to 5. + switch (url.protocol.replace(':', '')) { + case 'socks4': + lookup = true; + type = 4; + break; + // pass through + case 'socks4a': + type = 4; + break; + case 'socks5': + lookup = true; + type = 5; + break; + // pass through + case 'socks': // no version specified, default to 5h + type = 5; + break; + case 'socks5h': + type = 5; + break; + default: + throw new TypeError(`A "socks" protocol must be specified! Got: ${String(url.protocol)}`); + } + const proxy = { + host, + port, + type, + }; + if (url.username) { + Object.defineProperty(proxy, 'userId', { + value: decodeURIComponent(url.username), + enumerable: false, + }); + } + if (url.password != null) { + Object.defineProperty(proxy, 'password', { + value: decodeURIComponent(url.password), + enumerable: false, + }); + } + return { lookup, proxy }; +} +class SocksProxyAgent extends agent_base_1.Agent { + constructor(uri, opts) { + super(opts); + const url = typeof uri === 'string' ? new URL(uri) : uri; + const { proxy, lookup } = parseSocksURL(url); + this.shouldLookup = lookup; + this.proxy = proxy; + this.timeout = opts?.timeout ?? null; + } + /** + * Initiates a SOCKS connection to the specified SOCKS proxy server, + * which in turn connects to the specified remote host and port. + */ + async connect(req, opts) { + const { shouldLookup, proxy, timeout } = this; + if (!opts.host) { + throw new Error('No `host` defined!'); + } + let { host } = opts; + const { port, lookup: lookupFn = dns.lookup } = opts; + if (shouldLookup) { + // Client-side DNS resolution for "4" and "5" socks proxy versions. + host = await new Promise((resolve, reject) => { + // Use the request's custom lookup, if one was configured: + lookupFn(host, {}, (err, res) => { + if (err) { + reject(err); + } + else { + resolve(res); + } + }); + }); + } + const socksOpts = { + proxy, + destination: { + host, + port: typeof port === 'number' ? port : parseInt(port, 10), + }, + command: 'connect', + timeout: timeout ?? undefined, + }; + const cleanup = (tlsSocket) => { + req.destroy(); + socket.destroy(); + if (tlsSocket) + tlsSocket.destroy(); + }; + debug('Creating socks proxy connection: %o', socksOpts); + const { socket } = await socks_1.SocksClient.createConnection(socksOpts); + debug('Successfully created socks proxy connection'); + if (timeout !== null) { + socket.setTimeout(timeout); + socket.on('timeout', () => cleanup()); + } + if (opts.secureEndpoint) { + // The proxy is connecting to a TLS server, so upgrade + // this socket connection to a TLS connection. + debug('Upgrading socket connection to TLS'); + const servername = opts.servername || opts.host; + const tlsSocket = tls.connect({ + ...omit(opts, 'host', 'path', 'port'), + socket, + servername: net.isIP(servername) ? undefined : servername, + }); + tlsSocket.once('error', (error) => { + debug('Socket TLS error', error.message); + cleanup(tlsSocket); + }); + return tlsSocket; + } + return socket; + } +} +SocksProxyAgent.protocols = [ + 'socks', + 'socks4', + 'socks4a', + 'socks5', + 'socks5h', +]; +exports.SocksProxyAgent = SocksProxyAgent; +function omit(obj, ...keys) { + const ret = {}; + let key; + for (key in obj) { + if (!keys.includes(key)) { + ret[key] = obj[key]; + } + } + return ret; +} +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/node_modules/@npmcli/agent/node_modules/socks-proxy-agent/package.json b/node_modules/@npmcli/agent/node_modules/socks-proxy-agent/package.json new file mode 100644 index 0000000000000..a6c7c0741641a --- /dev/null +++ b/node_modules/@npmcli/agent/node_modules/socks-proxy-agent/package.json @@ -0,0 +1,142 @@ +{ + "name": "socks-proxy-agent", + "version": "8.0.1", + "description": "A SOCKS proxy `http.Agent` implementation for HTTP and HTTPS", + "main": "./dist/index.js", + "types": "./dist/index.d.ts", + "files": [ + "dist" + ], + "author": { + "email": "nathan@tootallnate.net", + "name": "Nathan Rajlich", + "url": "http://n8.io/" + }, + "contributors": [ + { + "name": "Kiko Beats", + "email": "josefrancisco.verdu@gmail.com" + }, + { + "name": "Josh Glazebrook", + "email": "josh@joshglazebrook.com" + }, + { + "name": "talmobi", + "email": "talmobi@users.noreply.github.com" + }, + { + "name": "Indospace.io", + "email": "justin@indospace.io" + }, + { + "name": "Kilian von Pflugk", + "email": "github@jumoog.io" + }, + { + "name": "Kyle", + "email": "admin@hk1229.cn" + }, + { + "name": "Matheus Fernandes", + "email": "matheus.frndes@gmail.com" + }, + { + "name": "Ricky Miller", + "email": "richardkazuomiller@gmail.com" + }, + { + "name": "Shantanu Sharma", + "email": "shantanu34@outlook.com" + }, + { + "name": "Tim Perry", + "email": "pimterry@gmail.com" + }, + { + "name": "Vadim Baryshev", + "email": "vadimbaryshev@gmail.com" + }, + { + "name": "jigu", + "email": "luo1257857309@gmail.com" + }, + { + "name": "Alba Mendez", + "email": "me@jmendeth.com" + }, + { + "name": "Дмитрий Гуденков", + "email": "Dimangud@rambler.ru" + }, + { + "name": "Andrei Bitca", + "email": "63638922+andrei-bitca-dc@users.noreply.github.com" + }, + { + "name": "Andrew Casey", + "email": "amcasey@users.noreply.github.com" + }, + { + "name": "Brandon Ros", + "email": "brandonros1@gmail.com" + }, + { + "name": "Dang Duy Thanh", + "email": "thanhdd.it@gmail.com" + }, + { + "name": "Dimitar Nestorov", + "email": "8790386+dimitarnestorov@users.noreply.github.com" + } + ], + "repository": { + "type": "git", + "url": "https://github.com/TooTallNate/proxy-agents.git", + "directory": "packages/socks-proxy-agent" + }, + "keywords": [ + "agent", + "http", + "https", + "proxy", + "socks", + "socks4", + "socks4a", + "socks5", + "socks5h" + ], + "dependencies": { + "agent-base": "^7.0.1", + "debug": "^4.3.4", + "socks": "^2.7.1" + }, + "devDependencies": { + "@types/async-retry": "^1.4.5", + "@types/debug": "^4.1.7", + "@types/dns2": "^2.0.3", + "@types/jest": "^29.5.1", + "@types/node": "^14.18.45", + "async-listen": "^2.1.0", + "async-retry": "^1.3.3", + "cacheable-lookup": "^6.1.0", + "dns2": "^2.1.0", + "jest": "^29.5.0", + "socksv5": "github:TooTallNate/socksv5#fix/dstSock-close-event", + "ts-jest": "^29.1.0", + "typescript": "^5.0.4", + "tsconfig": "0.0.0", + "proxy": "2.0.1" + }, + "engines": { + "node": ">= 14" + }, + "license": "MIT", + "scripts": { + "build": "tsc", + "test": "jest --env node --verbose --bail test/test.ts", + "test-e2e": "jest --env node --verbose --bail test/e2e.test.ts", + "lint": "eslint . --ext .ts", + "pack": "node ../../scripts/pack.mjs" + } +} \ No newline at end of file diff --git a/node_modules/@npmcli/agent/package.json b/node_modules/@npmcli/agent/package.json index 0d0ec1bdfb418..c0bf65719db9a 100644 --- a/node_modules/@npmcli/agent/package.json +++ b/node_modules/@npmcli/agent/package.json @@ -1,6 +1,6 @@ { "name": "@npmcli/agent", - "version": "2.0.0", + "version": "2.1.0", "description": "the http/https agent used by the npm cli", "main": "lib/index.js", "scripts": { @@ -37,6 +37,12 @@ "18.x" ] }, + "dependencies": { + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.1", + "lru-cache": "^10.0.1", + "socks-proxy-agent": "^8.0.1" + }, "devDependencies": { "@npmcli/eslint-config": "^4.0.0", "@npmcli/template-oss": "4.18.0", @@ -54,9 +60,5 @@ "--exclude", "tap-snapshots/**" ] - }, - "dependencies": { - "lru-cache": "^10.0.1", - "socks": "^2.7.1" } } diff --git a/package-lock.json b/package-lock.json index 26628070149f4..4e41c82f33bda 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2314,18 +2314,72 @@ } }, "node_modules/@npmcli/agent": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@npmcli/agent/-/agent-2.0.0.tgz", - "integrity": "sha512-RpRbD6PnaQIUl+p8MoH7sl2CHyMofCO0abOV+0VulqKW84+0nRWnj0bYFQELTN5HpNvzWAV8pRN6Fjx9ZLOS0g==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@npmcli/agent/-/agent-2.1.0.tgz", + "integrity": "sha512-/HFJP3a/DzgIg+6TWVee3bQmnBcWeKKYE9DKQqS8SWpAV8oYDTn/zkDM8iQ7bWI6kDDgNfHOlEFZZpN/UXMwig==", "inBundle": true, "dependencies": { + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.1", "lru-cache": "^10.0.1", - "socks": "^2.7.1" + "socks-proxy-agent": "^8.0.1" }, "engines": { "node": "^16.14.0 || >=18.0.0" } }, + "node_modules/@npmcli/agent/node_modules/agent-base": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.0.tgz", + "integrity": "sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==", + "inBundle": true, + "dependencies": { + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/@npmcli/agent/node_modules/http-proxy-agent": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.0.tgz", + "integrity": "sha512-+ZT+iBxVUQ1asugqnD6oWoRiS25AkjNfG085dKJGtGxkdwLQrMKU5wJr2bOOFAXzKcTuqq+7fZlTMgG3SRfIYQ==", + "inBundle": true, + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/@npmcli/agent/node_modules/https-proxy-agent": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.1.tgz", + "integrity": "sha512-Eun8zV0kcYS1g19r78osiQLEFIRspRUDd9tIfBCTBPBeMieF/EsJNL8VI3xOIdYRDEkjQnqOYPsZ2DsWsVsFwQ==", + "inBundle": true, + "dependencies": { + "agent-base": "^7.0.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/@npmcli/agent/node_modules/socks-proxy-agent": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.1.tgz", + "integrity": "sha512-59EjPbbgg8U3x62hhKOFVAmySQUcfRQ4C7Q/D5sEHnZTQRrQlNKINks44DMR1gwXp0p4LaVIeccX2KHTTcHVqQ==", + "inBundle": true, + "dependencies": { + "agent-base": "^7.0.1", + "debug": "^4.3.4", + "socks": "^2.7.1" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/@npmcli/arborist": { "resolved": "workspaces/arborist", "link": true