Skip to main content
Glama
app.js7.96 kB
/** * Web应用主文件 * Express + Socket.IO服务器,提供MCP API和管理界面 */ import express from 'express'; import http from 'http'; import { Server as socketIo } from 'socket.io'; import cors from 'cors'; import helmet from 'helmet'; import compression from 'compression'; import { logger } from '../utils/logger.js'; import MCPManager from '../core/mcp-manager.js'; import TaskManager from '../core/task-manager.js'; import DatabaseManager from '../database/database-manager.js'; import { getConfig } from '../config/config-manager.js'; class WebApplication { constructor(options = {}) { console.log('WebApplication constructor called'); this.options = options; this.app = express(); try { this.server = http.createServer(this.app); console.log('HTTP server created successfully'); } catch (error) { console.error('Error creating HTTP server:', error); throw error; } // Temporarily disable Socket.IO to isolate the issue this.io = null; console.log('Socket.IO disabled for testing'); // Use provided managers or create new ones this.db = options.dbManager || new DatabaseManager(getConfig('database')); this.taskManager = options.taskExecutor || new TaskManager(this.db); this.mcpManager = options.mcpManager || new MCPManager(this.taskManager, this.db); this.setupMiddleware(); // this.setupSocketHandlers(); // Disabled for now // setupErrorHandling() will be called after routes are set up in start() method } /** * 设置中间件 */ setupMiddleware() { // 安全中间件 this.app.use(helmet()); this.app.use(compression()); this.app.use(cors(getConfig('server.cors'))); // 限流(暂时禁用,因为express-rate-limit包不存在) // 如果需要限流功能,请安装express-rate-limit包 // 请求解析 this.app.use(express.json({ limit: '10mb' })); this.app.use(express.urlencoded({ extended: true, limit: '10mb' })); // 请求日志 this.app.use((req, res, next) => { console.log(`收到请求: ${req.method} ${req.path}`); logger.info(`${req.method} ${req.path}`, { ip: req.ip, userAgent: req.get('User-Agent') }); next(); }); } /** * 设置路由 */ async setupRoutes() { console.log('开始设置路由...'); // 健康检查 this.app.get('/health', async (req, res) => { console.log('健康检查端点被调用'); const packageJson = await import('../../package.json', { with: { type: 'json' } }); res.json({ status: 'healthy', timestamp: new Date().toISOString(), uptime: process.uptime(), version: packageJson.default.version }); }); // MCP API路由 - 动态导入 console.log('导入路由模块...'); const mcpRoutes = (await import('./routes/mcp.js')).default; const adminRoutes = (await import('./routes/admin.js')).default; const apiRoutes = (await import('./routes/api.js')).default; console.log('路由模块导入完成'); this.app.use('/api/mcp', mcpRoutes(this.mcpManager)); this.app.use('/api/admin', adminRoutes(this.db, this.taskManager)); this.app.use('/api/dashboard', apiRoutes(this.db, this.taskManager)); console.log('API路由设置完成'); // 静态文件服务 console.log('设置静态文件服务...'); this.app.use(express.static('public')); console.log('静态文件服务设置完成'); // 管理界面 this.app.get('/', (req, res) => { console.log('根路径被访问'); res.sendFile('index.html', { root: 'public' }); }); // API文档 this.app.get('/docs', (req, res) => { console.log('API文档端点被访问'); res.json(this.mcpManager.getMethods()); }); console.log('所有路由设置完成'); } /** * 设置Socket.IO处理器 */ setupSocketHandlers() { this.io.on('connection', (socket) => { logger.info(`客户端连接: ${socket.id}`); // 订阅任务状态更新 socket.on('subscribe_tasks', (accountId) => { socket.join(`tasks_${accountId}`); logger.info(`客户端 ${socket.id} 订阅任务: ${accountId}`); }); // 订阅系统状态 socket.on('subscribe_system', () => { socket.join('system'); logger.info(`客户端 ${socket.id} 订阅系统状态`); }); // 断开连接 socket.on('disconnect', () => { logger.info(`客户端断开连接: ${socket.id}`); }); }); // 任务状态广播 this.taskManager.on('task_update', (data) => { this.io.to(`tasks_${data.accountId}`).emit('task_update', data); }); // 系统状态广播 setInterval(async () => { try { const status = await this.mcpManager.handleRequest({ jsonrpc: '2.0', method: 'system.status', id: null }); this.io.to('system').emit('system_status', status); } catch (error) { logger.error('系统状态广播失败', error); } }, 5000); } /** * 设置错误处理 */ setupErrorHandling() { // 404处理 this.app.use((req, res) => { res.status(404).json({ error: 'Not Found', message: 'The requested resource was not found' }); }); // 错误处理中间件 this.app.use((error, req, res, next) => { logger.error('Web应用错误', error); const status = error.status || 500; res.status(status).json({ error: error.message || 'Internal Server Error', ...(process.env.NODE_ENV === 'development' && { stack: error.stack }) }); }); // 进程错误处理 process.on('uncaughtException', (error) => { logger.error('未捕获的异常', error); process.exit(1); }); process.on('unhandledRejection', (reason, promise) => { logger.error('未处理的Promise拒绝', { reason, promise }); }); } /** * 启动服务器 */ async start() { try { // 初始化数据库 await this.db.initialize(); logger.info('数据库初始化完成'); // 初始化任务管理器 await this.taskManager.initialize(); logger.info('任务管理器初始化完成'); // 设置路由(需要异步导入) await this.setupRoutes(); logger.info('路由设置完成'); // 设置错误处理(必须在路由之后) this.setupErrorHandling(); logger.info('错误处理设置完成'); // 启动服务器 const port = this.options?.config?.app?.port || getConfig('server.port'); const host = this.options?.config?.app?.host || getConfig('server.host'); this.server.listen(port, host, () => { logger.info(`服务器启动成功`, { host, port, url: `http://${host}:${port}` }); }); // 优雅关闭 process.on('SIGTERM', () => this.gracefulShutdown()); process.on('SIGINT', () => this.gracefulShutdown()); } catch (error) { logger.error('服务器启动失败', error); process.exit(1); } } /** * 优雅关闭 */ async gracefulShutdown() { logger.info('开始优雅关闭...'); try { // 关闭服务器 this.server.close(() => { logger.info('HTTP服务器已关闭'); }); // 停止任务管理器 await this.taskManager.stop(); logger.info('任务管理器已停止'); // 关闭数据库连接 await this.db.close(); logger.info('数据库连接已关闭'); process.exit(0); } catch (error) { logger.error('优雅关闭失败', error); process.exit(1); } } } // 启动应用 if (import.meta.url === `file://${process.argv[1]}`) { const app = new WebApplication(); app.start(); } export default WebApplication;

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/billyangbc/xiaohongshu-mcp-nodejs'

If you have feedback or need assistance with the MCP directory API, please join our Discord server