1'use strict' 2 3const { HttpProxyAgent } = require('http-proxy-agent') 4const { HttpsProxyAgent } = require('https-proxy-agent') 5const { SocksProxyAgent } = require('socks-proxy-agent') 6const { LRUCache } = require('lru-cache') 7const { InvalidProxyProtocolError } = require('./errors.js') 8 9const PROXY_CACHE = new LRUCache({ max: 20 }) 10 11const SOCKS_PROTOCOLS = new Set(SocksProxyAgent.protocols) 12 13const PROXY_ENV_KEYS = new Set(['https_proxy', 'http_proxy', 'proxy', 'no_proxy']) 14 15const PROXY_ENV = Object.entries(process.env).reduce((acc, [key, value]) => { 16 key = key.toLowerCase() 17 if (PROXY_ENV_KEYS.has(key)) { 18 acc[key] = value 19 } 20 return acc 21}, {}) 22 23const getProxyAgent = (url) => { 24 url = new URL(url) 25 26 const protocol = url.protocol.slice(0, -1) 27 if (SOCKS_PROTOCOLS.has(protocol)) { 28 return SocksProxyAgent 29 } 30 if (protocol === 'https' || protocol === 'http') { 31 return [HttpProxyAgent, HttpsProxyAgent] 32 } 33 34 throw new InvalidProxyProtocolError(url) 35} 36 37const isNoProxy = (url, noProxy) => { 38 if (typeof noProxy === 'string') { 39 noProxy = noProxy.split(',').map((p) => p.trim()).filter(Boolean) 40 } 41 42 if (!noProxy || !noProxy.length) { 43 return false 44 } 45 46 const hostSegments = url.hostname.split('.').reverse() 47 48 return noProxy.some((no) => { 49 const noSegments = no.split('.').filter(Boolean).reverse() 50 if (!noSegments.length) { 51 return false 52 } 53 54 for (let i = 0; i < noSegments.length; i++) { 55 if (hostSegments[i] !== noSegments[i]) { 56 return false 57 } 58 } 59 60 return true 61 }) 62} 63 64const getProxy = (url, { proxy, noProxy }) => { 65 url = new URL(url) 66 67 if (!proxy) { 68 proxy = url.protocol === 'https:' 69 ? PROXY_ENV.https_proxy 70 : PROXY_ENV.https_proxy || PROXY_ENV.http_proxy || PROXY_ENV.proxy 71 } 72 73 if (!noProxy) { 74 noProxy = PROXY_ENV.no_proxy 75 } 76 77 if (!proxy || isNoProxy(url, noProxy)) { 78 return null 79 } 80 81 return new URL(proxy) 82} 83 84module.exports = { 85 getProxyAgent, 86 getProxy, 87 proxyCache: PROXY_CACHE, 88} 89