/** * 简化的代理池类,支持 HTTP 和 SOCKS5 代理 */ class ProxyPool { constructor() { // 从环境变量读取完整的代理URL this.proxyUrl = process.env.HTTP_PROXY || process.env.HTTPS_PROXY || ''; this.isInitialized = false; // 解析代理URL this.parseProxyUrl(); } /** * 解析代理URL */ parseProxyUrl() { if (!this.proxyUrl) { console.log('未设置代理URL环境变量 (HTTP_PROXY)'); return; } try { const url = new URL(this.proxyUrl); this.proxyInfo = { protocol: url.protocol.replace(':', ''), host: url.hostname, port: parseInt(url.port), username: url.username, password: url.password, full: this.proxyUrl }; console.log(`代理配置解析成功: ${this.proxyInfo.protocol}://${this.proxyInfo.host}:${this.proxyInfo.port}`); } catch (error) { console.error(`代理URL解析失败: ${error.message}`); this.proxyInfo = null; } } /** * 初始化代理池 */ async initialize() { if (this.isInitialized) return true; if (!this.proxyUrl) { console.log('未配置代理,将使用直连模式'); this.isInitialized = true; return true; } if (!this.proxyInfo) { console.error('代理配置无效'); return false; } // 测试代理连接 const isValid = await this.testProxyConnection(); if (isValid) { this.isInitialized = true; console.log('代理池初始化成功'); return true; } else { console.error('代理连接测试失败'); // 即使测试失败,也标记为已初始化,让实际使用时验证 this.isInitialized = true; console.log('跳过测试失败,继续使用配置的代理'); return true; } } /** * 测试代理连接 */ async testProxyConnection() { if (!this.proxyInfo) return false; try { let agent; // 根据协议选择不同的代理 Agent if (this.proxyUrl.startsWith('socks5://')) { const { SocksProxyAgent } = await import('socks-proxy-agent'); agent = new SocksProxyAgent(this.proxyUrl); console.log('使用 SOCKS5 代理进行测试...'); } else if (this.proxyUrl.startsWith('socks4://')) { const { SocksProxyAgent } = await import('socks-proxy-agent'); agent = new SocksProxyAgent(this.proxyUrl); console.log('使用 SOCKS4 代理进行测试...'); } else { const HttpProxyAgent = (await import('http-proxy-agent')).default; agent = new HttpProxyAgent(this.proxyUrl); console.log('使用 HTTP 代理进行测试...'); } const fetch = (await import('node-fetch')).default; // 尝试多个测试URL const testUrls = [ 'http://httpbin.org/ip', 'https://api.ipify.org?format=json', 'http://icanhazip.com' ]; for (const testUrl of testUrls) { try { console.log(`测试代理连接到: ${testUrl}`); const response = await fetch(testUrl, { agent, timeout: 15000, headers: { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36', 'Accept': '*/*', 'Connection': 'close' } }); if (response.ok) { const data = await response.text(); let ip = data.trim(); // 尝试解析JSON格式的响应 try { const jsonData = JSON.parse(data); ip = jsonData.ip || jsonData.origin || ip; } catch (e) { // 如果不是JSON,使用原始文本 } console.log(`${this.proxyInfo.protocol.toUpperCase()} 代理连接测试成功!`); console.log(`测试URL: ${testUrl}`); console.log(`出口IP: ${ip}`); return true; } else { console.log(`测试URL ${testUrl} 失败,状态码: ${response.status}`); } } catch (urlError) { console.log(`测试URL ${testUrl} 出错: ${urlError.message}`); } } console.error('所有测试URL都失败了'); return false; } catch (error) { console.error(`代理连接测试失败: ${error.message}`); return false; } } /** * 获取代理(每次调用返回相同的代理) */ getProxy() { if (!this.proxyInfo) { return null; } return { ip: this.proxyInfo.host, port: this.proxyInfo.port, protocol: this.proxyInfo.protocol, full: this.proxyInfo.full }; } /** * 移除代理(记录错误) */ removeProxy(ip, port) { console.log(`记录代理问题: ${ip}:${port}`); return true; } /** * 获取代理数量 */ getValidCount() { return this.proxyInfo ? 1 : 0; } /** * 获取状态信息 */ getStatus() { if (!this.proxyInfo) { return []; } return [{ index: 0, host: this.proxyInfo.host, port: this.proxyInfo.port, protocol: this.proxyInfo.protocol, active: true }]; } /** * 停止代理池 */ stop() { console.log('代理池已停止'); } } // 导出 export default ProxyPool; export const proxyPool = new ProxyPool();