Download src/server/index.js from ASEM12345/anti_api: direct link, hf CLI and curl.
- Browser
- Download file 5.89 kB
-
https://huggingface.co/spaces/ASEM12345/anti_api/resolve/main/src/server/index.js
- Command line
-
hf download hf://spaces/ASEM12345/anti_api/src/server/index.js
-
curl -L -o index.js https://huggingface.co/spaces/ASEM12345/anti_api/resolve/main/src/server/index.js
5.89 kB
| /** | |
| * 服务器主入口 | |
| * Express 应用配置、中间件、路由挂载、服务器启动和关闭 | |
| */ | |
| import express from 'express'; | |
| import cors from 'cors'; | |
| import path from 'path'; | |
| import { closeRequester } from '../api/client.js'; | |
| import logger from '../utils/logger.js'; | |
| import config from '../config/config.js'; | |
| import memoryManager from '../utils/memoryManager.js'; | |
| import { getPublicDir, getRelativePath } from '../utils/paths.js'; | |
| import { MEMORY_CHECK_INTERVAL } from '../constants/index.js'; | |
| import { errorHandler } from '../utils/errors.js'; | |
| import { getChunkPoolSize, clearChunkPool } from './stream.js'; | |
| // 路由模块 | |
| import adminRouter from '../routes/admin.js'; | |
| import sdRouter from '../routes/sd.js'; | |
| import openaiRouter from '../routes/openai.js'; | |
| import geminiRouter from '../routes/gemini.js'; | |
| import claudeRouter from '../routes/claude.js'; | |
| const publicDir = getPublicDir(); | |
| logger.info(`静态文件目录: ${getRelativePath(publicDir)}`); | |
| const app = express(); | |
| // ==================== 内存管理 ==================== | |
| memoryManager.setThreshold(config.server.memoryThreshold); | |
| memoryManager.start(MEMORY_CHECK_INTERVAL); | |
| // ==================== 基础中间件 ==================== | |
| app.use(cors()); | |
| app.use(express.json({ limit: config.security.maxRequestSize })); | |
| // 静态文件服务 | |
| app.use('/images', express.static(path.join(publicDir, 'images'))); | |
| app.use(express.static(publicDir)); | |
| // 管理路由 | |
| app.use('/admin', adminRouter); | |
| // 使用统一错误处理中间件 | |
| app.use(errorHandler); | |
| // ==================== 请求日志中间件 ==================== | |
| app.use((req, res, next) => { | |
| const ignorePaths = [ | |
| '/images', '/favicon.ico', '/.well-known', | |
| '/sdapi/v1/options', '/sdapi/v1/samplers', '/sdapi/v1/schedulers', | |
| '/sdapi/v1/upscalers', '/sdapi/v1/latent-upscale-modes', | |
| '/sdapi/v1/sd-vae', '/sdapi/v1/sd-modules' | |
| ]; | |
| // 提前获取完整路径,避免在路由处理后 req.path 被修改为相对路径 | |
| const fullPath = req.originalUrl.split('?')[0]; | |
| if (!ignorePaths.some(p => fullPath.startsWith(p))) { | |
| const start = Date.now(); | |
| res.on('finish', () => { | |
| logger.request(req.method, fullPath, res.statusCode, Date.now() - start); | |
| }); | |
| } | |
| next(); | |
| }); | |
| // SD API 路由 | |
| app.use('/sdapi/v1', sdRouter); | |
| // ==================== API Key 验证中间件 ==================== | |
| app.use((req, res, next) => { | |
| if (req.path.startsWith('/v1/')) { | |
| const apiKey = config.security?.apiKey; | |
| if (apiKey) { | |
| const authHeader = req.headers.authorization || req.headers['x-api-key']; | |
| const providedKey = authHeader?.startsWith('Bearer ') ? authHeader.slice(7) : authHeader; | |
| if (providedKey !== apiKey) { | |
| logger.warn(`API Key 验证失败: ${req.method} ${req.path} (提供的Key: ${providedKey ? providedKey.substring(0, 10) + '...' : '无'})`); | |
| return res.status(401).json({ error: 'Invalid API Key' }); | |
| } | |
| } | |
| } else if (req.path.startsWith('/v1beta/')) { | |
| const apiKey = config.security?.apiKey; | |
| if (apiKey) { | |
| const providedKey = req.query.key || req.headers['x-goog-api-key']; | |
| if (providedKey !== apiKey) { | |
| logger.warn(`API Key 验证失败: ${req.method} ${req.path} (提供的Key: ${providedKey ? providedKey.substring(0, 10) + '...' : '无'})`); | |
| return res.status(401).json({ error: 'Invalid API Key' }); | |
| } | |
| } | |
| } | |
| next(); | |
| }); | |
| // ==================== API 路由 ==================== | |
| // OpenAI 兼容 API | |
| app.use('/v1', openaiRouter); | |
| // Gemini 兼容 API | |
| app.use('/v1beta', geminiRouter); | |
| // Claude 兼容 API(/v1/messages 由 claudeRouter 处理) | |
| app.use('/v1', claudeRouter); | |
| // ==================== 系统端点 ==================== | |
| // 内存监控端点 | |
| app.get('/v1/memory', (req, res) => { | |
| const usage = process.memoryUsage(); | |
| res.json({ | |
| heapUsed: usage.heapUsed, | |
| heapTotal: usage.heapTotal, | |
| rss: usage.rss, | |
| external: usage.external, | |
| arrayBuffers: usage.arrayBuffers, | |
| pressure: memoryManager.getCurrentPressure(), | |
| poolSizes: memoryManager.getPoolSizes(), | |
| chunkPoolSize: getChunkPoolSize() | |
| }); | |
| }); | |
| // 健康检查端点 | |
| app.get('/health', (req, res) => { | |
| res.json({ status: 'ok', uptime: process.uptime() }); | |
| }); | |
| // ==================== 服务器启动 ==================== | |
| const server = app.listen(config.server.port, config.server.host, () => { | |
| logger.info(`服务器已启动: ${config.server.host}:${config.server.port}`); | |
| }); | |
| server.on('error', (error) => { | |
| if (error.code === 'EADDRINUSE') { | |
| logger.error(`端口 ${config.server.port} 已被占用`); | |
| process.exit(1); | |
| } else if (error.code === 'EACCES') { | |
| logger.error(`端口 ${config.server.port} 无权限访问`); | |
| process.exit(1); | |
| } else { | |
| logger.error('服务器启动失败:', error.message); | |
| process.exit(1); | |
| } | |
| }); | |
| // ==================== 优雅关闭 ==================== | |
| const shutdown = () => { | |
| logger.info('正在关闭服务器...'); | |
| // 停止内存管理器 | |
| memoryManager.stop(); | |
| logger.info('已停止内存管理器'); | |
| // 关闭子进程请求器 | |
| closeRequester(); | |
| logger.info('已关闭子进程请求器'); | |
| // 清理对象池 | |
| clearChunkPool(); | |
| logger.info('已清理对象池'); | |
| server.close(() => { | |
| logger.info('服务器已关闭'); | |
| process.exit(0); | |
| }); | |
| // 5秒超时强制退出 | |
| setTimeout(() => { | |
| logger.warn('服务器关闭超时,强制退出'); | |
| process.exit(0); | |
| }, 5000); | |
| }; | |
| process.on('SIGINT', shutdown); | |
| process.on('SIGTERM', shutdown); | |
| // ==================== 异常处理 ==================== | |
| process.on('uncaughtException', (error) => { | |
| logger.error('未捕获异常:', error.message); | |
| // 不立即退出,让当前请求完成 | |
| }); | |
| process.on('unhandledRejection', (reason, promise) => { | |
| logger.error('未处理的 Promise 拒绝:', reason); | |
| }); | |