Skip to content

中间件

基本使用

通过 nest cli 创建 middleware

bash
nest g mi <middleware-name>

手动创建

新建 /middleware/index.ts

ts
import { Injectable, NestMiddleware } from '@nestjs/common';
import { Request, Response, NextFunction } from 'express';
@Injectable()
export class Logger implements NestMiddleware {
  use(req: Request, res: Response, next: NextFunction) {}
}

导出一个类,继承自 NestMiddleware 接口。需要实现一个 use 方法,需要三个参数 reqresnest()(与 express 类似)。

ts
use(req: Request, res: Response, next: NextFunction) {
    console.log('Request...');
    next();
}

use 方法中,执行 next() 方法会放行,也可以使用 res.send() 进行拦截。

在模板中使用中间件

在 user.module.ts 中,将 UserModule 继承 NestModule,需要实现一个 configure 方法,在其中规定需要使用的中间件。

ts
@Module({
  controllers: [UserController],
  providers: [UserService],
  exports: [UserService],
})
export class UserModule implements NestModule {
  configure(consumer: MiddlewareConsumer) {
    consumer.apply(Logger).forRoutes('user');
  }
}

apply() 方法约定了需要使用的中间件,forRoutes() 方法约定了指定路由。

forRoutes 也支持传递对象

ts
consumer.apply(Logger).forRoutes({
  path: 'user',
  method: RequestMethod.GET,
});

如果在这里制定了 GET 方法,那么如果客户端使用 POST 方法访问则不会触发中间件拦截。

也可以将 UserController 直接传递进去,这样控制器中约定的所有路由都会经由中间件处理。

ts
configure(consumer: MiddlewareConsumer) {
  consumer.apply(Logger).forRoutes(UserController);
}

全局中间件

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

创建一个函数

ts
function MiddlewareAll(req:Request, res:Response, next:NextFunction) {
  console.log(req.originalUrl, req.method);
  next();
}

在 app 对象中调用 use 方法,将该中间件传递过去

ts
async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.use(MiddlewareAll);
  await app.listen(process.env.PORT ?? 3000);
}

制作简单的路由白名单

ts
function MiddlewareAll(req: Request, res: Response, next: NextFunction) {
  const whitelist = ['/list'];
  if (whitelist.includes(req.originalUrl)) {
    next();
  } else {
    res.send('Access Denied');
  }
}

第三方中间件

安装 cors

bash
pnpm add cors 

pnpm add @types/cors -D

导入 cors

ts
import * as cors from 'cors'

在 app.use() 中使用,以解决跨域问题。

ts
app.use(cors())