const { Logger } = require('./logger'); /** * 404错误处理中间件 */ const notFoundHandler = (req, res, next) => { const error = new Error(`找不到请求的资源: ${req.method} ${req.originalUrl}`); error.status = 404; error.code = 'NOT_FOUND'; Logger.warn('404错误', { method: req.method, url: req.originalUrl, ip: req.ip, userAgent: req.get('User-Agent') }); next(error); }; /** * 全局错误处理中间件 */ const globalErrorHandler = (err, req, res, next) => { // 默认错误状态码 let statusCode = err.status || err.statusCode || 500; let message = err.message || '服务器内部错误'; let code = err.code || 'INTERNAL_ERROR'; // 记录错误日志 Logger.error('全局错误处理', err, { method: req.method, url: req.originalUrl, ip: req.ip, userAgent: req.get('User-Agent'), body: req.body, params: req.params, query: req.query }); // 根据错误类型设置不同的响应 switch (err.name) { case 'ValidationError': statusCode = 400; message = '请求参数验证失败'; code = 'VALIDATION_ERROR'; break; case 'UnauthorizedError': statusCode = 401; message = '未授权访问'; code = 'UNAUTHORIZED'; break; case 'JsonWebTokenError': statusCode = 401; message = 'Token无效'; code = 'INVALID_TOKEN'; break; case 'TokenExpiredError': statusCode = 401; message = 'Token已过期'; code = 'TOKEN_EXPIRED'; break; case 'CastError': statusCode = 400; message = '无效的ID格式'; code = 'INVALID_ID'; break; case 'SyntaxError': if (err.message.includes('JSON')) { statusCode = 400; message = 'JSON格式错误'; code = 'INVALID_JSON'; } break; } // 数据库相关错误 if (err.message.includes('SQLITE_')) { statusCode = 500; message = '数据库操作失败'; code = 'DATABASE_ERROR'; // 具体的SQLite错误处理 if (err.message.includes('UNIQUE')) { statusCode = 409; message = '资源已存在'; code = 'RESOURCE_CONFLICT'; } else if (err.message.includes('FOREIGN KEY')) { statusCode = 400; message = '外键约束错误'; code = 'FOREIGN_KEY_ERROR'; } } // LLM API相关错误 if (err.message.includes('LLM') || err.message.includes('API')) { if (err.message.includes('密钥')) { statusCode = 503; message = 'AI服务配置错误'; code = 'LLM_CONFIG_ERROR'; } else if (err.message.includes('网络') || err.message.includes('连接')) { statusCode = 503; message = 'AI服务连接失败'; code = 'LLM_CONNECTION_ERROR'; } else if (err.message.includes('频率')) { statusCode = 429; message = '请求过于频繁'; code = 'RATE_LIMIT_EXCEEDED'; } } // 构建错误响应 const errorResponse = { success: false, error: message, code: code, timestamp: new Date().toISOString(), path: req.originalUrl, method: req.method }; // 开发环境包含更多错误信息 if (process.env.NODE_ENV === 'development') { errorResponse.stack = err.stack; errorResponse.details = { name: err.name, originalMessage: err.message }; } // 特殊处理:如果是流式请求,需要特殊处理 if (req.headers.accept && req.headers.accept.includes('text/plain')) { res.status(statusCode).write(JSON.stringify({ type: 'error', data: errorResponse }) + '\n'); res.end(); return; } res.status(statusCode).json(errorResponse); }; /** * 异步错误包装器 */ const asyncHandler = (fn) => { return (req, res, next) => { Promise.resolve(fn(req, res, next)).catch(next); }; }; /** * 验证错误处理器 */ const validationErrorHandler = (errors) => { const formattedErrors = errors.map(error => ({ field: error.param, message: error.msg, value: error.value })); const validationError = new Error('请求参数验证失败'); validationError.status = 400; validationError.code = 'VALIDATION_ERROR'; validationError.details = formattedErrors; return validationError; }; /** * 业务逻辑错误类 */ class BusinessError extends Error { constructor(message, statusCode = 400, code = 'BUSINESS_ERROR') { super(message); this.name = 'BusinessError'; this.status = statusCode; this.code = code; } } /** * 资源未找到错误类 */ class NotFoundError extends Error { constructor(resource = '资源') { super(`${resource}不存在`); this.name = 'NotFoundError'; this.status = 404; this.code = 'NOT_FOUND'; } } /** * 验证错误类 */ class ValidationError extends Error { constructor(message, field = null) { super(message); this.name = 'ValidationError'; this.status = 400; this.code = 'VALIDATION_ERROR'; this.field = field; } } /** * 权限错误类 */ class ForbiddenError extends Error { constructor(message = '权限不足') { super(message); this.name = 'ForbiddenError'; this.status = 403; this.code = 'FORBIDDEN'; } } /** * 服务不可用错误类 */ class ServiceUnavailableError extends Error { constructor(service = '服务') { super(`${service}暂时不可用`); this.name = 'ServiceUnavailableError'; this.status = 503; this.code = 'SERVICE_UNAVAILABLE'; } } /** * 进程退出前的清理处理 */ const gracefulShutdown = () => { process.on('SIGTERM', () => { Logger.info('收到SIGTERM信号,开始优雅关闭...'); process.exit(0); }); process.on('SIGINT', () => { Logger.info('收到SIGINT信号,开始优雅关闭...'); process.exit(0); }); process.on('uncaughtException', (err) => { Logger.error('未捕获的异常', err); process.exit(1); }); process.on('unhandledRejection', (reason, promise) => { Logger.error('未处理的Promise拒绝', new Error(reason), { promise }); process.exit(1); }); }; module.exports = { notFoundHandler, globalErrorHandler, asyncHandler, validationErrorHandler, gracefulShutdown, // 错误类 BusinessError, NotFoundError, ValidationError, ForbiddenError, ServiceUnavailableError };