Spaces:
Running
Running
// 加载环境变量 | |
require('dotenv').config(); | |
// 在logger加载前添加临时日志函数 | |
function tempLog(level, message) { | |
const timestamp = new Date().toISOString(); | |
if (level === 'ERROR') { | |
console.error(`[ERROR] ${timestamp} ${message}`); | |
} else if (level === 'WARN') { | |
console.warn(`[WARN] ${timestamp} ${message}`); | |
} else { | |
console.log(`[INFO] ${timestamp} ${message}`); | |
} | |
} | |
// 环境检查 | |
tempLog('INFO', '启动前检查环境配置...'); | |
const envChecker = require('./utils/envChecker'); | |
// 先执行简单检查,避免循环依赖 | |
envChecker.enforceEnvCheck(); | |
const express = require('express'); | |
const morgan = require('morgan'); | |
const path = require('path'); | |
const cron = require('node-cron'); | |
const app = express(); | |
const cookieParser = require('cookie-parser'); | |
const { spawn } = require('child_process'); | |
// 先加载配置,再加载logger | |
const config = require('./config/config'); | |
const logger = require('./utils/logger'); | |
const routes = require('./routes'); | |
const keyManager = require('./utils/keyManager'); | |
const cookieRefresher = require('./utils/cookieRefresher'); | |
const authMiddleware = require('./middleware/auth'); | |
const proxyLauncher = require('./utils/proxyLauncher'); | |
// 初始化代理服务器 | |
if (process.env.USE_TLS_PROXY === 'true') { | |
logger.info('正在启动TLS代理服务器...'); | |
proxyLauncher.startProxyServer(); | |
} else { | |
logger.info('TLS代理服务器未启用,跳过启动代理'); | |
} | |
// 加载路由 | |
const v1Router = require('./routes/v1'); | |
// 初始化API Keys | |
logger.info('初始化API Keys...'); | |
keyManager.initializeApiKeys(); | |
// 输出最终的API Keys配置 | |
logger.debug('最终API Keys配置:', JSON.stringify(keyManager.getAllApiKeys().reduce((obj, key) => { | |
obj[key] = keyManager.getAllCookiesForApiKey(key); | |
return obj; | |
}, {}), null, 2)); | |
// 输出每个API key的Cookie数量信息 | |
const apiKeys = keyManager.getAllApiKeys(); | |
const keySummary = apiKeys.map(key => { | |
const cookies = keyManager.getAllCookiesForApiKey(key); | |
return `${key}: ${cookies.length}个Cookie`; | |
}).join(', '); | |
logger.info(`当前已加载 ${apiKeys.length} 个API Key,详情: ${keySummary}`); | |
// 添加CORS支持 | |
app.use((req, res, next) => { | |
res.header('Access-Control-Allow-Origin', '*'); | |
res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept, Authorization'); | |
res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS'); | |
if (req.method === 'OPTIONS') { | |
return res.status(200).end(); | |
} | |
next(); | |
}); | |
app.use(express.json({ limit: '50mb' })); | |
app.use(express.urlencoded({ extended: true, limit: '50mb' })); | |
app.use(cookieParser()); | |
// 自定义Morgan格式,将日志输出到我们的日志系统 | |
morgan.token('remote-addr', (req) => { | |
return req.headers['x-forwarded-for'] || req.socket.remoteAddress; | |
}); | |
// 创建一个将 Morgan 日志写入我们的日志系统的流 | |
const morganLoggerStream = { | |
write: (message) => { | |
// 移除行尾的换行符 | |
const trimmedMessage = message.trim(); | |
if (trimmedMessage) { | |
logger.http(trimmedMessage); | |
} | |
} | |
}; | |
// 使用自定义格式的 Morgan 中间件 | |
app.use(morgan(process.env.MORGAN_FORMAT || 'combined', { | |
stream: morganLoggerStream, | |
// 跳过健康检查等路由的日志 | |
skip: (req, res) => { | |
return req.path === '/health' || req.path === '/favicon.ico'; | |
} | |
})); | |
// 添加静态文件支持 | |
app.use(express.static(path.join(__dirname, 'public'))); | |
// 添加根路由,重定向到登录页面 | |
app.get('/', (req, res) => { | |
res.redirect('/login.html'); | |
}); | |
// 添加认证中间件 | |
app.use(authMiddleware); | |
// API路由 | |
app.use('/v1', v1Router); | |
app.use("/", routes) | |
// 设置自动定时刷新Cookie任务 | |
if (config.refresh.enabled) { | |
logger.info(`已启用自动刷新 Cookie,定时任务将在每 ${config.refresh.interval} 运行`); | |
cron.schedule(config.refresh.interval, () => { | |
logger.info('开始定时自动刷新 Cookie...'); | |
const scriptPath = path.resolve(__dirname, '../auto-refresh-cookies.js'); | |
const child = spawn('node', [scriptPath], { | |
stdio: ['ignore', 'pipe', 'pipe'] | |
}); | |
child.stdout.on('data', (data) => { | |
logger.info(`刷新进程输出: ${data.toString().trim()}`); | |
}); | |
child.stderr.on('data', (data) => { | |
logger.error(`刷新进程错误: ${data.toString().trim()}`); | |
}); | |
child.on('close', (code) => { | |
if (code === 0) { | |
logger.info('自动刷新 Cookie 定时任务完成'); | |
} else { | |
logger.error(`自动刷新 Cookie 定时任务异常退出,代码: ${code}`); | |
} | |
}); | |
}); | |
} else { | |
logger.info('未启用自动刷新 Cookie,如需启用请设置环境变量 ENABLE_AUTO_REFRESH=true'); | |
} | |
// 错误处理中间件 | |
app.use((err, req, res, next) => { | |
logger.error('服务器错误:', err); | |
res.status(500).json({ | |
error: 'Internal server error', | |
message: err.message | |
}); | |
}); | |
// 处理404请求 | |
app.use((req, res) => { | |
logger.warn(`未找到路由: ${req.method} ${req.url}`); | |
res.status(404).json({ | |
error: 'Not found', | |
message: '请求的资源不存在' | |
}); | |
}); | |
app.listen(config.port, () => { | |
logger.info(`服务器已启动,监听端口: ${config.port}`); | |
logger.info(`打开管理界面: http://localhost:${config.port}`); | |
}); | |
// 处理进程退出事件,清理资源 | |
process.on('SIGINT', () => { | |
logger.info('接收到SIGINT信号,正在优雅关闭服务...'); | |
// 停止代理服务器 | |
if (process.env.USE_TLS_PROXY === 'true') { | |
logger.info('正在停止TLS代理服务器...'); | |
proxyLauncher.stopProxyServer(); | |
} | |
process.exit(0); | |
}); | |
process.on('SIGTERM', () => { | |
logger.info('接收到SIGTERM信号,正在优雅关闭服务...'); | |
// 停止代理服务器 | |
if (process.env.USE_TLS_PROXY === 'true') { | |
logger.info('正在停止TLS代理服务器...'); | |
proxyLauncher.stopProxyServer(); | |
} | |
process.exit(0); | |
}); | |
module.exports = app; | |