一、中间件的创建与使用
1. 类中间件
通过实现 NestMiddleware
接口创建类中间件,需定义 use
方法:
typescript
import { Injectable, NestMiddleware } from '@nestjs/common';
import { Request, Response, NextFunction } from 'express';
@Injectable()
export class LoggerMiddleware implements NestMiddleware {
use(req: Request, res: Response, next: NextFunction) {
console.log(`[${new Date().toISOString()}] Request to: ${req.path}`);
next(); // 必须调用 next() 传递请求
}
}
注册方式 :在模块中通过 MiddlewareConsumer
配置作用范围:
typescript
import { Module, NestModule, MiddlewareConsumer } from '@nestjs/common';
@Module({})
export class AppModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
consumer
.apply(LoggerMiddleware)
.forRoutes('*'); // 应用到所有路由,或指定控制器/路径
// 可以指定路由路径方法 或者 某个控制器类
// forRoutes({path:'user',method:RequestMethod.GET})
// forRoutes(UserController)
}
}
2. 函数中间件
更轻量的方式,直接定义函数:
typescript
export function logger(req: Request, res: Response, next: NextFunction) {
console.log(`Request URL: ${req.url}`);
next();
}
注册方式与类中间件相同。
二、全局中间件
全局中间件对所有路由生效,但仅支持函数形式 。需在 main.ts
中配置:
typescript
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import * as cors from 'cors';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
// 应用全局中间件
app.use(LoggerMiddleware);
await app.listen(3000);
}
bootstrap();
注意 :类中间件若需全局生效,需在模块中配置 forRoutes('*')
。
三、使用第三方中间件(以 CORS 为例)
bash
npm install cors
npm install @types/cors -D
1. 通过 NestJS 内置模块
在 main.ts
中启用:
typescript
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
// 配置 CORS
app.enableCors({
origin: 'http://localhost:3000', // 允许的域名
methods: 'GET,POST', // 允许的请求方法
});
await app.listen(3000);
}
bootstrap();
2. 直接使用 Express 中间件
例如使用 cors
包:
typescript
import * as cors from 'cors';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.use(cors()); // 应用第三方中间件
await app.listen(3000);
}
此方式更灵活,支持原生 Express 中间件的所有配置项。
四、高级用法示例
1. 多个中间件链式调用
typescript
consumer
.apply(Middleware1, Middleware2)
.forRoutes(UserController);
中间件按顺序执行,若某个中间件未调用 next()
,后续中间件和路由处理将终止。
2. 动态中间件配置
通过工厂函数传递参数:
typescript
// 定义中间件生成函数
export function rateLimiter(options) {
return (req, res, next) => {
// 根据 options 实现限速逻辑
next();
};
}
// 注册时传入参数
consumer.apply(rateLimiter({ windowMs: 15000, max: 100 })).forRoutes('*');
总结
类型 | 适用场景 | 特点 |
---|---|---|
类中间件 | 复杂逻辑、依赖注入 | 支持模块化配置,可复用性高 |
函数中间件 | 简单逻辑、快速实现 | 无需类结构,轻量级 |
全局中间件 | 跨路由统一处理(如日志) | 仅函数形式,需在入口文件配置 |
第三方中间件 | 跨域、限速等通用功能 | 直接复用 Express 生态 |