中间件Middleware

中间件位于是在路由处理程序调用之前调用的函数,Middleware可以访问请求和响应对象

中间件函数可以执行的任务:

  • 执行任何代码
  • 对请求和响应对象进行更改
  • 结束请求-响应周期
  • 调用堆栈中的下一个中间件函数

如果当前的中间件函数没有结束请求-响应周期,它必须调用next()将控制传递给下一个中间件函数;否则,请求将被挂起

使用

依赖注入中间件

创建中间件

类中要求实现use函数,返回req、res、next参数

如果最后不调用next(),程序将被挂起

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import { Injectable, NestMiddleware } from '@nestjs/common';

@Injectable()
export class LoggerMiddleware implements NestMiddleware {
use(req: any, res: any, next: () => void) {
console.log("I'm comming~");
const random = Math.random();
// 记得不要让next()和res.send()位于同一个逻辑
if (random < 0.5) {
next();
} else {
res.send("I'm pending...");
}
}
}

使用中间件

在某个模块里实现configure,它返回一个消费者consumer,通过apply注中间件并通过forRoutes指定Controller路由

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import {
MiddlewareConsumer,
Module,
NestModule,
RequestMethod,
} from '@nestjs/common';
import { UserService } from './user.service';
import { UserController } from './user.controller';
import { LoggerMiddleware } from '../logger/logger.middleware';

@Module({
controllers: [UserController],
providers: [UserService],
// 导出UserService
exports: [UserService],
})
export class UserModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
// 注册中间件,需要指定路由才能生效,user及其子路由都能生效
// consumer.apply(LoggerMiddleware).forRoutes('user');
// ---------------------------------------------
// 这样也能拦截user,只有user路由且方法对应时生效
// consumer
// .apply(LoggerMiddleware)
// .forRoutes({ path: 'user', method: RequestMethod.GET });
// ---------------------------------------------
// 直接传个Controller,里面所有路由都会被拦截
consumer.apply(LoggerMiddleware).forRoutes(UserController);
}
}

访问相应的路由,注册的中间件都会生效

全局中间件

给整个app都设置一个中间件,拦截全局路由

全局中间件是一个函数,不能使用类形式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import { NestFactory } from '@nestjs/core';
import { VersioningType } from '@nestjs/common';
import { AppModule } from './app.module';

const whiteList = ['/list'];

function middlewareAll(req, res, next) {
console.log(req.originalUrl);
// 在整个app中,只有白名单内的路由才允许通过,否则阻塞
if (whiteList.includes(req.originalUrl)) {
next();
} else {
res.send("I'm pending...");
}
}

async function bootstrap() {
const app = await NestFactory.create(AppModule);
// app.use注册全局中间件
app.use(middlewareAll);
await app.listen(3000);
}
bootstrap();

接入第三方中间件

例如允许跨域:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import { NestFactory } from '@nestjs/core';
import { VersioningType } from '@nestjs/common';
import { AppModule } from './app.module';
import * as cors from 'cors';

const whiteList = ['/list'];

function middlewareAll(req, res, next) {
console.log(req.originalUrl);
if (whiteList.includes(req.originalUrl)) {
next();
} else {
res.send({ code: 114514 });
}
}

async function bootstrap() {
const app = await NestFactory.create(AppModule);
// 较新版的Nest已经集成了跨域:
// const app = await NestFactory.create(AppModule, {cors:true});
// 第三方库进行跨域
app.use(cors());
app.use(middlewareAll);
await app.listen(3000);
}
bootstrap();