Files
whale-town-end/src/business/security/middleware/maintenance.middleware.ts
moyin 47a738067a feat: 重构业务模块架构
- 新增auth模块处理认证逻辑
- 新增security模块处理安全相关功能
- 新增user-mgmt模块管理用户相关操作
- 新增shared模块存放共享组件
- 重构admin模块,添加DTO和Guards
- 为admin模块添加测试文件结构
2025-12-24 18:04:30 +08:00

137 lines
3.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 维护模式中间件
*
* 功能描述:
* - 检查系统是否处于维护模式
* - 在维护期间阻止用户访问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')
};
}
}