const express = require('express'); const cors = require('cors'); const helmet = require('helmet'); const compression = require('compression'); const dotenv = require('dotenv'); // 导入中间件 const { requestLogger, consoleLogger, errorLogger, apiStats } = require('./middleware/logger'); const { notFoundHandler, globalErrorHandler, gracefulShutdown } = require('./middleware/errorHandler'); const { globalRateLimit, chatRateLimit } = require('./middleware/rateLimit'); const { sessionAuth, contentTypeCheck } = require('./middleware/auth'); // 导入路由 const apiRoutes = require('./routes'); // 导入数据库 const database = require('./models/database'); // 导入配置验证 const { validateConfig } = require('./config/llm'); // 加载环境变量 dotenv.config(); class App { constructor() { this.app = express(); this.port = process.env.PORT || 3000; this.env = process.env.NODE_ENV || 'development'; // 初始化应用 this.initializeMiddlewares(); this.initializeRoutes(); this.initializeErrorHandling(); this.initializeGracefulShutdown(); } /** * 初始化中间件 */ initializeMiddlewares() { // 安全相关中间件 this.app.use(helmet({ contentSecurityPolicy: false, // 禁用CSP以避免开发时的问题 crossOriginEmbedderPolicy: false })); // 启用 trust proxy,用于正确获取客户端IP this.app.set('trust proxy', 1); // CORS配置 const corsOptions = { origin: process.env.CORS_ORIGIN?.split(',') || ['http://localhost:5173'], credentials: true, methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'], allowedHeaders: ['Content-Type', 'Authorization', 'x-api-key', 'x-session-id'] }; this.app.use(cors(corsOptions)); // 压缩响应 this.app.use(compression()); // 解析JSON请求体 this.app.use(express.json({ limit: '10mb', strict: true })); // 解析URL编码的请求体 this.app.use(express.urlencoded({ extended: true, limit: '10mb' })); // 日志中间件 this.app.use(consoleLogger); this.app.use(requestLogger); this.app.use(errorLogger); // API统计中间件 this.app.use(apiStats); // 会话认证中间件 this.app.use(sessionAuth); // 内容类型检查中间件 this.app.use('/api', contentTypeCheck()); // 全局速率限制 this.app.use('/api', globalRateLimit); // 聊天API专用速率限制 this.app.use('/api/chat', chatRateLimit); } /** * 初始化路由 */ initializeRoutes() { // 根路径 this.app.get('/', (req, res) => { res.json({ success: true, data: { name: 'LLM Chat Website Backend', version: '1.0.0', environment: this.env, timestamp: new Date().toISOString() }, message: '欢迎使用大语言模型聊天网站后端服务' }); }); // API路由 this.app.use('/api', apiRoutes); // 静态文件服务(如果需要) this.app.use('/static', express.static('public')); } /** * 初始化错误处理 */ initializeErrorHandling() { // 404处理 this.app.use(notFoundHandler); // 全局错误处理 this.app.use(globalErrorHandler); } /** * 初始化优雅关闭 */ initializeGracefulShutdown() { gracefulShutdown(); } /** * 初始化数据库 */ async initializeDatabase() { try { await database.initialize(); console.log('数据库初始化完成'); return true; } catch (error) { console.error('数据库初始化失败:', error); return false; } } /** * 验证配置 */ validateConfiguration() { console.log('验证配置...'); // 验证LLM配置 const llmConfigValid = validateConfig(); if (!llmConfigValid) { console.warn('LLM配置可能不完整,请检查环境变量'); } // 验证必要的环境变量 const requiredEnvVars = ['PORT']; const missingEnvVars = requiredEnvVars.filter(envVar => !process.env[envVar]); if (missingEnvVars.length > 0) { console.warn('缺少环境变量:', missingEnvVars.join(', ')); } console.log('配置验证完成'); return true; } /** * 启动服务器 */ async start() { try { console.log('启动应用程序...'); // 验证配置 this.validateConfiguration(); // 初始化数据库 const dbInitialized = await this.initializeDatabase(); if (!dbInitialized) { throw new Error('数据库初始化失败'); } // 启动HTTP服务器 const server = this.app.listen(this.port, () => { console.log(` 🚀 服务器启动成功! 📝 环境: ${this.env} 🌐 端口: ${this.port} 🔗 本地地址: http://localhost:${this.port} 📊 API文档: http://localhost:${this.port}/api 🏥 健康检查: http://localhost:${this.port}/api/health `); }); // 设置服务器超时 server.timeout = 30000; // 30秒 // 处理服务器错误 server.on('error', (error) => { if (error.code === 'EADDRINUSE') { console.error(`❌ 端口 ${this.port} 已被占用`); process.exit(1); } else { console.error('❌ 服务器启动失败:', error); process.exit(1); } }); // 优雅关闭处理 const gracefulShutdown = () => { console.log('📝 正在关闭服务器...'); server.close(async () => { console.log('🔒 HTTP服务器已关闭'); try { await database.close(); console.log('🔒 数据库连接已关闭'); } catch (error) { console.error('关闭数据库连接失败:', error); } console.log('👋 应用程序已安全退出'); process.exit(0); }); }; process.on('SIGTERM', gracefulShutdown); process.on('SIGINT', gracefulShutdown); return server; } catch (error) { console.error('❌ 应用程序启动失败:', error); process.exit(1); } } /** * 获取Express应用实例 */ getApp() { return this.app; } } module.exports = App;