Spaces:
Running
Running
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 }; |