NestJS学习笔记之中间件

中间件

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

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

  • 执行任何代码。
  • 对请求和响应对象进行更改。
  • 结束请求-响应周期。
  • 调用堆栈中的下一个中间件函数。
  • 如果当前的中间件函数没有结束请求-响应周期, 它必须调用 next() 将控制传递给下一个中间件函数。否则, 请求将被挂起。
1.创建一个依赖注入中间件

要求我们实现use函数,返回req,res,next参数,如果不调用next 程序将被挂起

先新建一个中间件logger

nest g mi logger

use方法源码,可以看到req是客户端传递给服务端的数据对象,里面包含了一些请求参数等,res是服务端返回给客户端的数据对象。

然后在user.module中实现NestModule,实现接口里面的configure方法,返回一个消费者 ,consumer通过apply注册中间件,通过forRoutes指定Controller路由

第一种在forRoutes使用字符串
import { Global, MiddlewareConsumer, Module, NestModule } from '@nestjs/common';
import { UserService } from './user.service';
import { UserController } from './user.controller';
import { LoggerMiddleware as Logger } from '../logger/logger.middleware'

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

中间件Logger

import { Injectable, NestMiddleware } from '@nestjs/common';

@Injectable()
export class LoggerMiddleware implements NestMiddleware {
  use(req: any, res: any, next: () => void) {
    console.log("zl");
    next();
  }
}

访问http://localhost:3000/user,控制台输出zl

如果注释掉next(),访问http://localhost:3000/user,此时服务被挂起,页面一直加载

也可以服务端直接返回数据给客户端,告诉客户端“我被拦截了”

注意,res.send和next只能存在一个

第二种在forRoutes使用对象配置

也可以指定拦截的方法,比如拦截GET、 POST等,在forRoutes使用对象配置

import { Global, MiddlewareConsumer, Module, NestModule, RequestMethod } from '@nestjs/common';
import { UserService } from './user.service';
import { UserController } from './user.controller';
import { LoggerMiddleware as Logger } from '../logger/logger.middleware'

@Global()
@Module({
  controllers: [UserController],
  providers: [UserService],
  exports: [UserService]
})
export class UserModule implements NestModule {
  configure(consumer: MiddlewareConsumer) {
    consumer.apply(Logger).forRoutes({ path: "user", method: RequestMethod.GET })
  }
}

此时访问http://localhost:3000/user,调用的是controller里面的findAll方法,它为GET方法,所以被拦截了

如果换成拦截POST方法,则页面正常输出了

consumer.apply(Logger).forRoutes({ path: "user", method: RequestMethod.POST })

第三种在forRoutes直接把Controller塞进去
export class UserModule implements NestModule {
  configure(consumer: MiddlewareConsumer) {
    consumer.apply(Logger).forRoutes(UserController)
  }
}
2.全局中间件

注意全局中间件只能使用函数模式。

案例:可以做白名单拦截之类的,比如只让'/list'接口访问,其余都拦截

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { VersioningType } from '@nestjs/common';

const whiteList = ['/list']

function middleWareAll(req: any, res: any, next: any) {
  console.log(req.originalUrl);
  if (whiteList.includes(req.originalUrl)) {
    next()
  } else {
    res.send('我无法访问了')
  }
}

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.enableVersioning({
    type: VersioningType.URI
  })
  app.use(middleWareAll)
  await app.listen(3000);
}
bootstrap();

比如访问http://localhost:3000/list,正常放行

访问http://localhost:3000/user,被拦截

3.接入第三方中间件

例如cors处理跨域

npm install cors
npm install @types/cors -D

在百度页面,控制台利用fetch访问http://localhost:3000/user会出现跨域问题

fetch('http://localhost:3000/user').then((res)=>res.json()).then((res)=>{
  console.log(res)
})

解决办法:

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { VersioningType } from '@nestjs/common';
import * as cors from 'cors';

const whiteList = ['/list']

function middleWareAll(req: any, res: any, next: any) {
  console.log(req.originalUrl);
  if (whiteList.includes(req.originalUrl)) {
    next()
  } else {
    res.send({
      message: 'wozuishuai'
    })
  }
}

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.enableVersioning({
    type: VersioningType.URI
  })
  app.use(cors())
  app.use(middleWareAll)
  await app.listen(3000);
}
bootstrap();

注意: app.use(cors())和app.use(middleWareAll)的调用顺序不要弄反了,先是解决跨域再使用中间件,顺序出错跨域还是会出现。

再次访问就不会有跨域了

  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值