中间件是在路由处理程序之前调用的函数。在中间件中可以访问请求和响应对象,也可以访问next()函数,当中间件处理完毕后必须调用next()将控制权交给下一个中间件,否则,请求将会被挂起。中间件的处理如下图:
1.自定义Middleware
自定义Middleware只需要做两件事,第一是使用@Injectable装饰器将中间件注入到IOC容器,第二步是实现NestMiddleware接口并重写该接口的use方法,use方法接收请求对象、响应对象、next函数3个参数,注意必须调用next()将控制权交给下一个中间件,否则请求将会被挂起。未使用@Injectable装饰器修饰中间件仍能正常访问。
/**
* src/common/middleware
*
* 自定义middleware只需两步操作,第一使用@Injectable装饰器将中间件注入到IOC容器,
* 第二步是实现NestMiddleware接口重写该接口的use方法。
*/
import { Injectable, NestMiddleware } from '@nestjs/common';
@Injectable()
export class LoggerMiddleware implements NestMiddleware {
/*
* req 为请求对象,res为响应对象,next()用于调用下一个中间件
*/
use(req: any, res: any, next: () => void) {
console.log('我是Logger Middleware');
next();
}
}
在module中使用中间件,使用中间件需要实现NestModule并重写configure函数,configure函数接收一个中间件消费者对象,通过调用该对象的apply可以使用Middleware,也可以使用exclude()排除不需要被中间件处理的请求,也可以使用forRoutes对包含某个路由前缀进行处理。
//app.module.ts
import {
Module,
NestModule,
MiddlewareConsumer,
RequestMethod,
} from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { LoggerMiddleware } from './common/middleware/logger.middleware';
@Module({
imports: [],
controllers: [AppController],
providers: [AppService],
})
export class AppModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
/**
* exclude用于排除请求,例如下面例子中表示排除路径为/getUser并且请求类型为get的请求。
* forRoutes表示中间件只应用于请求url前缀为app的请求。
* apply()中可以传入多个中间件,以逗号隔开
*/
consumer
.apply(LoggerMiddleware)
.exclude({ path: '/getUser', method: RequestMethod.GET })
.forRoutes('app');
}
}
//app.controller.ts
import { Controller, Get } from '@nestjs/common';
import { AppService } from './app.service';
@Controller('/app')
export class AppController {
constructor(private readonly appService: AppService) {}
//当访问localhost:3000/app/hello时请求会被中间件拦截到
@Get('/hello')
getHello(): string {
return this.appService.getHello();
}
}
2.函数Middleware
import { Request, Response, NextFunction } from 'express';
/*
* req 为请求对象,res为响应对象,next()用于调用下一个中间件
*/
export default function (req: Request, res: Response, next: NextFunction) {
console.log('我是函数中间件....');
next();
}
2.使用全局中间件
import FuncMiddleware from './common/middleware/func.middleware';
const app = await NestFactory.create(AppModule);
//使用create()创建的INestApplication实例,通过该实例的use()调用中间件,注意use()调用的中间件必须是函数中间件
app.use(logger);
await app.listen(3000)