import { HttpsProxyAgent } from 'https-proxy-agent'; import { SocksProxyAgent } from 'socks-proxy-agent'; import { ProxyAgent } from 'undici'; type Proxy = { host: string; password?: string; port: string; protocol: string; username?: string; }; function selectProxyAgent(proxyUrl: string): HttpsProxyAgent | SocksProxyAgent { const url = new URL(proxyUrl); // NOTE: The following constants are not used in the function but are defined for clarity. // When a proxy URL is used to build the URL object, the protocol returned by procotol's property contains a `:` at // the end so, we add the protocol constants without the `:` to avoid confusion. const PROXY_HTTP_PROTOCOL = 'http:'; const PROXY_SOCKS_PROTOCOL = 'socks:'; switch (url.protocol) { case PROXY_HTTP_PROTOCOL: return new HttpsProxyAgent(url); case PROXY_SOCKS_PROTOCOL: return new SocksProxyAgent(url); default: throw new Error(`Unsupported proxy protocol: ${url.protocol}`); } } export function makeProxyAgent(proxy: Proxy | string): HttpsProxyAgent | SocksProxyAgent { if (typeof proxy === 'string') { return selectProxyAgent(proxy); } const { host, password, port, protocol, username } = proxy; let proxyUrl = `${protocol}://${host}:${port}`; if (username && password) { proxyUrl = `${protocol}://${username}:${password}@${host}:${port}`; } return selectProxyAgent(proxyUrl); } export function makeProxyAgentUndici(proxy: Proxy | string): ProxyAgent { let proxyUrl: string; let protocol: string; if (typeof proxy === 'string') { const url = new URL(proxy); protocol = url.protocol.replace(':', ''); proxyUrl = proxy; } else { const { host, password, port, protocol: proto, username } = proxy; protocol = (proto || 'http').replace(':', ''); if (protocol === 'socks') { protocol = 'socks5'; } const auth = username && password ? `${username}:${password}@` : ''; proxyUrl = `${protocol}://${auth}${host}:${port}`; } const PROXY_HTTP_PROTOCOL = 'http'; const PROXY_HTTPS_PROTOCOL = 'https'; const PROXY_SOCKS4_PROTOCOL = 'socks4'; const PROXY_SOCKS5_PROTOCOL = 'socks5'; switch (protocol) { case PROXY_HTTP_PROTOCOL: case PROXY_HTTPS_PROTOCOL: case PROXY_SOCKS4_PROTOCOL: case PROXY_SOCKS5_PROTOCOL: return new ProxyAgent(proxyUrl); default: throw new Error(`Unsupported proxy protocol: ${protocol}`); } }