- 新增auth模块处理认证逻辑 - 新增security模块处理安全相关功能 - 新增user-mgmt模块管理用户相关操作 - 新增shared模块存放共享组件 - 重构admin模块,添加DTO和Guards - 为admin模块添加测试文件结构
137 lines
3.9 KiB
TypeScript
137 lines
3.9 KiB
TypeScript
/**
|
||
* 维护模式中间件
|
||
*
|
||
* 功能描述:
|
||
* - 检查系统是否处于维护模式
|
||
* - 在维护期间阻止用户访问API
|
||
* - 提供维护状态和预计恢复时间信息
|
||
*
|
||
* 使用场景:
|
||
* - 系统升级维护
|
||
* - 数据库迁移
|
||
* - 紧急故障修复
|
||
* - 定期维护窗口
|
||
*
|
||
* @author kiro-ai
|
||
* @version 1.0.0
|
||
* @since 2025-12-24
|
||
*/
|
||
|
||
import { Injectable, NestMiddleware } from '@nestjs/common';
|
||
import { Request, Response, NextFunction } from 'express';
|
||
import { ConfigService } from '@nestjs/config';
|
||
import { Logger } from '@nestjs/common';
|
||
|
||
/**
|
||
* 维护模式响应接口
|
||
*/
|
||
interface MaintenanceResponse {
|
||
/** 请求是否成功 */
|
||
success: boolean;
|
||
/** 响应消息 */
|
||
message: string;
|
||
/** 错误代码 */
|
||
error_code: string;
|
||
/** 维护信息 */
|
||
maintenance_info?: {
|
||
/** 维护开始时间 */
|
||
start_time: string;
|
||
/** 预计结束时间 */
|
||
estimated_end_time?: string;
|
||
/** 重试间隔(秒) */
|
||
retry_after: number;
|
||
/** 维护原因 */
|
||
reason?: string;
|
||
};
|
||
}
|
||
|
||
@Injectable()
|
||
export class MaintenanceMiddleware implements NestMiddleware {
|
||
private readonly logger = new Logger(MaintenanceMiddleware.name);
|
||
|
||
constructor(private readonly configService: ConfigService) {}
|
||
|
||
/**
|
||
* 中间件处理函数
|
||
*
|
||
* 业务逻辑:
|
||
* 1. 检查维护模式环境变量
|
||
* 2. 如果处于维护模式,返回503状态码
|
||
* 3. 提供维护信息和重试建议
|
||
* 4. 记录维护期间的访问尝试
|
||
*
|
||
* @param req HTTP请求对象
|
||
* @param res HTTP响应对象
|
||
* @param next 下一个中间件函数
|
||
*/
|
||
use(req: Request, res: Response, next: NextFunction) {
|
||
// 1. 检查维护模式状态
|
||
const isMaintenanceMode = this.configService.get<string>('MAINTENANCE_MODE') === 'true';
|
||
|
||
if (!isMaintenanceMode) {
|
||
// 非维护模式,继续处理请求
|
||
next();
|
||
return;
|
||
}
|
||
|
||
// 2. 记录维护期间的访问尝试
|
||
this.logger.warn('维护模式:拒绝访问请求', {
|
||
operation: 'maintenance_check',
|
||
method: req.method,
|
||
url: req.url,
|
||
userAgent: req.get('User-Agent'),
|
||
ip: req.ip,
|
||
timestamp: new Date().toISOString()
|
||
});
|
||
|
||
// 3. 获取维护配置信息
|
||
const maintenanceStartTime = this.configService.get<string>('MAINTENANCE_START_TIME') || new Date().toISOString();
|
||
const maintenanceEndTime = this.configService.get<string>('MAINTENANCE_END_TIME');
|
||
const maintenanceReason = this.configService.get<string>('MAINTENANCE_REASON') || '系统维护升级';
|
||
const retryAfter = this.configService.get<number>('MAINTENANCE_RETRY_AFTER') || 1800; // 默认30分钟
|
||
|
||
// 4. 构建维护模式响应
|
||
const maintenanceResponse: MaintenanceResponse = {
|
||
success: false,
|
||
message: '系统正在维护中,请稍后再试',
|
||
error_code: 'SERVICE_UNAVAILABLE',
|
||
maintenance_info: {
|
||
start_time: maintenanceStartTime,
|
||
estimated_end_time: maintenanceEndTime,
|
||
retry_after: retryAfter,
|
||
reason: maintenanceReason
|
||
}
|
||
};
|
||
|
||
// 5. 设置HTTP响应头
|
||
res.setHeader('Retry-After', retryAfter.toString());
|
||
res.setHeader('Content-Type', 'application/json');
|
||
|
||
// 6. 返回503服务不可用状态
|
||
res.status(503).json(maintenanceResponse);
|
||
}
|
||
|
||
/**
|
||
* 检查维护模式是否启用
|
||
*
|
||
* @returns 是否处于维护模式
|
||
*/
|
||
isMaintenanceEnabled(): boolean {
|
||
return this.configService.get<string>('MAINTENANCE_MODE') === 'true';
|
||
}
|
||
|
||
/**
|
||
* 获取维护信息
|
||
*
|
||
* @returns 维护配置信息
|
||
*/
|
||
getMaintenanceInfo() {
|
||
return {
|
||
enabled: this.isMaintenanceEnabled(),
|
||
startTime: this.configService.get<string>('MAINTENANCE_START_TIME'),
|
||
endTime: this.configService.get<string>('MAINTENANCE_END_TIME'),
|
||
reason: this.configService.get<string>('MAINTENANCE_REASON'),
|
||
retryAfter: this.configService.get<number>('MAINTENANCE_RETRY_AFTER')
|
||
};
|
||
}
|
||
} |