Spaces:
Paused
Paused
| import { spawn } from 'child_process'; | |
| import { fileURLToPath } from 'url'; | |
| import { dirname, join } from 'path'; | |
| import fs from 'fs'; | |
| import os from 'os'; | |
| import dotenv from 'dotenv'; | |
| import chalk from 'chalk'; | |
| // 获取当前文件的目录路径 | |
| const __filename = fileURLToPath(import.meta.url); | |
| const __dirname = dirname(__filename); | |
| // 加载环境变量 | |
| dotenv.config({ path: join(dirname(__dirname), '.env') }); | |
| // 日志配置 | |
| const logger = { | |
| info: (message) => console.log(chalk.blue(`[ProxyServer] ${message}`)), | |
| error: (message) => console.error(chalk.red(`[ProxyServer] ${message}`)), | |
| warning: (message) => console.warn(chalk.yellow(`[ProxyServer] ${message}`)), | |
| success: (message) => console.log(chalk.green(`[ProxyServer] ${message}`)), | |
| // 新增一个专门用于子进程输出的 logger | |
| subprocess: (message) => console.log(chalk.gray(`[ProxyBinary] ${message}`)), | |
| }; | |
| class ProxyServer { | |
| constructor() { | |
| this.proxyProcess = null; | |
| this.platform = process.env.PROXY_SERVER_PLATFORM || 'auto'; | |
| this.port = process.env.PROXY_SERVER_PORT || 10655; | |
| // ***【修改 1】*** 移除了 this.logPath 和 this.logStream | |
| this.enabled = process.env.ENABLE_PROXY_SERVER === 'true'; | |
| this.proxyAuthToken = process.env.PROXY_AUTH_TOKEN || 'default_token'; | |
| } | |
| // 获取当前系统平台 (无变化) | |
| detectPlatform() { | |
| if (this.platform !== 'auto') { | |
| return this.platform; | |
| } | |
| const platform = os.platform(); | |
| const arch = os.arch(); | |
| if (platform === 'win32') return 'windows'; | |
| if (platform === 'linux') return (arch === 'arm64' ? 'android' : 'linux'); | |
| if (platform === 'android') return 'android'; | |
| logger.warning(`未知平台: ${platform}, ${arch}, 默认使用linux版本`); | |
| return 'linux'; | |
| } | |
| // 获取代理服务器可执行文件路径 (无变化) | |
| getProxyServerPath() { | |
| const platform = this.detectPlatform(); | |
| const isProduction = process.env.NODE_ENV === 'production'; | |
| const proxyDir = isProduction ? '/tmp/proxy' : join(__dirname, 'proxy'); | |
| logger.info(`环境: ${isProduction ? 'Production' : 'Development'}, 代理二进制目录: ${proxyDir}`); | |
| switch (platform) { | |
| case 'windows': return join(proxyDir, 'chrome_proxy_server_windows_amd64.exe'); | |
| case 'linux': return join(proxyDir, 'chrome_proxy_server_linux_amd64'); | |
| case 'android': return join(proxyDir, 'chrome_proxy_server_android_arm64'); | |
| default: | |
| logger.error(`不支持的平台: ${platform}`); | |
| return null; | |
| } | |
| } | |
| // 启动代理服务器 | |
| async start() { | |
| if (!this.enabled) { | |
| logger.info('代理服务器未启用,跳过启动'); | |
| return; | |
| } | |
| if (this.proxyProcess) { | |
| logger.warning('代理服务器已经在运行中'); | |
| return; | |
| } | |
| const proxyServerPath = this.getProxyServerPath(); | |
| if (!proxyServerPath || !fs.existsSync(proxyServerPath)) { | |
| logger.error(`代理二进制文件不存在于路径: ${proxyServerPath || '未知'}`); | |
| return; | |
| } | |
| try { | |
| // ***【修改 2】*** 移除了所有与文件日志相关的代码 | |
| // 启动代理服务器进程 | |
| this.proxyProcess = spawn(proxyServerPath, [ | |
| '--port', this.port.toString(), | |
| '--token', this.proxyAuthToken | |
| ], { | |
| stdio: ['ignore', 'pipe', 'pipe'], | |
| detached: false | |
| }); | |
| // ***【修改 3】*** 将子进程的输出直接打印到控制台 | |
| if (this.proxyProcess.stdout) { | |
| this.proxyProcess.stdout.on('data', (data) => { | |
| logger.subprocess(data.toString().trim()); | |
| }); | |
| } | |
| if (this.proxyProcess.stderr) { | |
| this.proxyProcess.stderr.on('data', (data) => { | |
| logger.error(`[ProxyBinary-Error] ${data.toString().trim()}`); | |
| }); | |
| } | |
| this.proxyProcess.on('error', (err) => { | |
| logger.error(`代理服务器启动失败: ${err.message}`); | |
| this.proxyProcess = null; | |
| }); | |
| this.proxyProcess.on('exit', (code, signal) => { | |
| logger.info(`代理服务器已退出,退出码: ${code}, 信号: ${signal}`); | |
| this.proxyProcess = null; | |
| }); | |
| await new Promise(resolve => setTimeout(resolve, 1000)); | |
| if (this.proxyProcess && this.proxyProcess.exitCode === null) { | |
| logger.success(`代理服务器已启动,端口: ${this.port}`); | |
| return true; | |
| } else { | |
| logger.error('代理服务器启动失败或立即退出。'); | |
| return false; | |
| } | |
| } catch (error) { | |
| logger.error(`启动代理服务器时出错: ${error.message}`); | |
| return false; | |
| } | |
| } | |
| // 停止代理服务器 (无变化) | |
| stop() { | |
| if (!this.proxyProcess) return; | |
| try { | |
| if (this.detectPlatform() === 'windows' && this.proxyProcess.pid) { | |
| spawn('taskkill', ['/pid', this.proxyProcess.pid, '/f', '/t']); | |
| } else { | |
| this.proxyProcess.kill('SIGTERM'); | |
| } | |
| logger.success('代理服务器已停止'); | |
| } catch (error) { | |
| logger.error(`停止代理服务器时出错: ${error.message}`); | |
| } finally { | |
| this.proxyProcess = null; | |
| } | |
| } | |
| } | |
| // 创建单例 | |
| const proxyServer = new ProxyServer(); | |
| // 导出 | |
| export { proxyServer }; |