import { HttpsProxyAgent, HttpsProxyAgentOptions } from "https-proxy-agent"; import { SocksProxyAgent, SocksProxyAgentOptions } from "socks-proxy-agent"; export type ProxyConfig = { host: string; port: number; auth?: { username: string; password: string; }; protocol: | "http" | "https" | "socks4" | "socks4a" | "socks5" | "socks5h" | "socks"; }; class ProxyProtocolError extends Error {} const proxyAgent = ( proxyConfig: ProxyConfig, ): HttpsProxyAgent | SocksProxyAgent => { switch (proxyConfig.protocol) { case "http": { let options: HttpsProxyAgentOptions = { host: proxyConfig.host, port: proxyConfig.port, secureProxy: false, }; if (proxyConfig.auth) { options = Object.assign(options, { auth: `${proxyConfig.auth.username}:${proxyConfig.auth.password}`, }); } const httpsAgent = new HttpsProxyAgent(options); return httpsAgent; } case "https": { let options: HttpsProxyAgentOptions = { host: proxyConfig.host, port: proxyConfig.port, secureProxy: true, }; if (proxyConfig.auth) { options = Object.assign(options, { auth: `${proxyConfig.auth.username}:${proxyConfig.auth.password}`, }); } const httpsAgent = new HttpsProxyAgent(options); return httpsAgent; } case "socks4": case "socks4a": { let options: SocksProxyAgentOptions = { type: 4, hostname: proxyConfig.host, port: proxyConfig.port, }; if (proxyConfig.auth) { options = Object.assign(options, { userId: proxyConfig.auth.username, password: proxyConfig.auth.password, }); } const socksAgent = new SocksProxyAgent(options); return socksAgent; } case "socks5": case "socks5h": case "socks": { let options: SocksProxyAgentOptions = { type: 5, hostname: proxyConfig.host, port: proxyConfig.port, }; if (proxyConfig.auth) { options = Object.assign(options, { userId: proxyConfig.auth.username, password: proxyConfig.auth.password, }); } const socksAgent = new SocksProxyAgent(options); return socksAgent; } default: throw new ProxyProtocolError("protocol is not accepted"); } }; export default proxyAgent;