【NestJS系列】核心概念:Middleware中间件
前言
用过express与koa的同学,对中间件这个概念应该非常熟悉了,中间件可以拿到Request、Response对象和next函数.
一般来讲中间件有以下作用:
- 执行任何代码
- 对请求与响应拦截并改造
- 结束
request-response周期 - 通过
next()调用下一个中间件 - 如果当前中间件没有结束当前
request-response周期,必须调用next()函数,否则请求会处于挂起状态,阻塞整个应用
中间件一般有两种:类中间件、函数中间件
类中间件
创建类中间件
使用@Injectable()装饰器,并且需要实现NestMiddleware接口(use方法)
// Logger.middleware.ts
import { Injectable, NestMiddleware } from "@nestjs/common";
import { Request, Response } from "express";
@Injectable()
export class LoggerMiddleware implements NestMiddleware {
use(req: Request, res: Response, next: () => void) {
console.log('logger middleware', `url: ${req.url}`);
next();
}
}
使用类中间件
类中间创建完之后,需要在模块中进行挂载,但@Module装饰器并没有中间件的相关配置,我们需要让module类实现NestModule接口,实现里面configure方法来进行挂载
// user.module.ts
import { Module, NestModule } from '@nestjs/common';
import { UserService } from './user.service';
import { UserController } from './user.controller';
import { LoggerMiddleware } from '../middleware/Logger.middleware';
@Module({
controllers: [UserController],
providers: [UserService]
})
export class UserModule implements NestModule {
configure(consumer) {
consumer
.apply(LoggerMiddleware)
.forRoutes(UserController);
}
}
apply方法表示挂载的是哪个中间件forRoutes方法表示对哪个请求路径起作用,这种方式与app.use(path, middleware)作用是一样,只针对部分路径起作用- 当给
forRoutes方法传递的是一个controller控制器时,那么该中间件则对整个控制器下的路径生效
比如这里传递的是UserController控制器,那么针对该控制器下的路径都会生效

forRootes方法还能做更详细的配置,比如可以针对特定的请求方法、请求路径可以使用正则匹配(需要注意的是使用fastify驱动不能使用)
export class UserModule implements NestModule {
configure(consumer) {
consumer
.apply(LoggerMiddleware)
.forRoutes({ path: 'user', method: RequestMethod.GET});
}
}
apply可以同时挂载多个中间件
export class UserModule implements NestModule {
configure(consumer) {
consumer
.apply(LoggerMiddleware, aaaMiddleware, ...)
.forRoutes({ path: 'user', method: RequestMethod.GET});
}
}
forRoutes可以使用单个string路径,多个string路径,RouteInfo对象,单个Controller,多个Controller
export class AppModule implements NestModule {
configure(consumer) {
consumer
.apply(LoggerMiddleware, NjMiddleware, ...)
.forRoutes(UserController, NjController, ...);
}
}
exclude可以用来排除不使用中间件的路径
export class UserModule implements NestModule {
configure(consumer) {
consumer
.apply(LoggerMiddleware)
.exclude({ path: '/user/a', method: RequestMethod.GET})
.forRoutes(UserController);
}
}
需要注意的是forRoutes需要最后调用
函数中间件
这种方式较为简单,使用起来与类中间件一致
创建函数中间件
export function LoggerMiddleware(req: Request, res: Response, next: () => void) {
console.log('logger middleware', `url: ${req.url}`);
next();
}
使用函数中间件
export class UserModule implements NestModule {
configure(consumer) {
consumer
.apply(LoggerMiddleware)
.exclude({ path: '/user/a', method: RequestMethod.GET})
.forRoutes(UserController);
}
}

全局中间件
可以直接在入口文件main.ts中使用app.use来挂载中间件,这样挂载的中间件将全局生效
app.use(LoggerMiddleware) // 日志中间件

中间件其实可以用来实现很多功能,比如:日志系统、cors跨域处理、图片防盗等...
对图片防盗感兴趣的可以看我这篇文章:你不知道的 HTTP Referer
【NestJS系列】核心概念:Middleware中间件的更多相关文章
- Spark系列-核心概念
Spark系列-初体验(数据准备篇) Spark系列-核心概念 一. Spark核心概念 Master,也就是架构图中的Cluster Manager.Spark的Master和Workder节点分别 ...
- fusionjs 学习二 核心概念
核心概念 middleware 类似express 的中间件模型(实际上是构建在koa中间件模型上的),但是和koa 的中间件有差异 fusionjs 的中间件同时可以运行在浏览器页面加载的时候 se ...
- ZooKeeper 系列(一)—— ZooKeeper核心概念详解
一.Zookeeper简介 二.Zookeeper设计目标 三.核心概念 3.1 集群角色 3.2 会话 3.3 数据节点 3.4 节点 ...
- ZooKeeper系列(一)—— ZooKeeper 简介及核心概念
一.Zookeeper简介 Zookeeper 是一个开源的分布式协调服务,目前由 Apache 进行维护.Zookeeper 可以用于实现分布式系统中常见的发布/订阅.负载均衡.命令服务.分布式协调 ...
- Storm 系列(二)—— Storm 核心概念详解
一.Storm核心概念 1.1 Topologies(拓扑) 一个完整的 Storm 流处理程序被称为 Storm topology(拓扑).它是一个是由 Spouts 和 Bolts 通过 Stre ...
- 框架源码系列十:Spring AOP(AOP的核心概念回顾、Spring中AOP的用法、Spring AOP 源码学习)
一.AOP的核心概念回顾 https://docs.spring.io/spring/docs/5.1.3.RELEASE/spring-framework-reference/core.html#a ...
- Redux 核心概念
http://gaearon.github.io/redux/index.html ,文档在 http://rackt.github.io/redux/index.html .本文不是官方文档的翻译. ...
- Laravel 核心概念
工欲善其事,必先利其器.在开发Xblog的过程中,稍微领悟了一点Laravel的思想.确实如此,这篇文章读完你可能并不能从无到有写出一个博客,但知道Laravel的核心概念之后,当你再次写起Larav ...
- Laravel 的核心概念
工欲善其事,必先利其器.在开发Xblog的过程中,稍微领悟了一点Laravel的思想.确实如此,这篇文章读完你可能并不能从无到有写出一个博客,但知道Laravel的核心概念之后,当你再次写起Larav ...
- 后端技术杂谈11:十分钟理解Kubernetes核心概念
本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 本文转自 https://github.com/h2pl/Java-Tutorial 喜欢的 ...
随机推荐
- Go 开源库运行时依赖注入框架 Dependency injection
Dependency injection 一个Go编程语言的运行依赖注入库.依赖注入是更广泛的控制反转技术的一种形式.它用于增加程序的模块化并使其具有可扩展性. 实例展示(High API): typ ...
- 生信服务器 | Linux 时间戳和标准时间
在 Linux 系统中,有许多场合都使用时间戳的方式表示时间,即从1970年1月1日起至当前的天数或秒数.如/etc/shadow里的密码更改日期和失效日期,还有代理服务器的访问日志对访问时间的记录等 ...
- DOS系统中EXE程序加载过程
1.在内存区中寻找一段容量足够的空闲内存区. 2.这段内存区的前256字节中,创建一个称为程序段前缀(PSP)的数据区. 3.这段内存区256字节之后,将程序装入,程序的地址被设为SA+10H : 0 ...
- 分布式数据库 Join 查询设计与实现浅析
相对于单例数据库的查询操作,分布式数据查询会有很多技术难题. 本文记录 Mysql 分库分表 和 Elasticsearch Join 查询的实现思路,了解分布式场景数据处理的设计方案. 文章从常用的 ...
- 2023-06-11:redis中,如何在100个亿URL中快速判断某URL是否存在?
2023-06-11:redis中,如何在100个亿URL中快速判断某URL是否存在? 答案2023-06-11: 传统数据结构的不足 当然有人会想,我直接将网页URL存入数据库进行查找不就好了,或者 ...
- 闺蜜机 StanbyME 产品随想
今天媳妇告诉我,现在小度这边推出一款叫 "闺蜜机"的可用移动的IPAD设备,我点开链接一看,就感觉兴趣不大,不就是一款把屏幕做的更大些的IPAD了吗? 有哪些更多创新呢?为什么会需 ...
- js修改css样式
修改宽度: document.getElementById("div1").style.width="200px"; 修改border-radius: docu ...
- 从AWS中学习如何使用AmazonDynamoDB存储卷
目录 <35. <从 AWS 中学习如何使用 Amazon DynamoDB 存储卷>>:从 AWS 中学习如何使用 Amazon DynamoDB 存储卷 随着云计算技术的迅 ...
- 2023-06-28:你想要用小写字母组成一个目标字符串 target。 开始的时候,序列由 target.length 个 ‘?‘ 记号组成 而你有一个小写字母印章 stamp。 在每个回合,你可
2023-06-28:你想要用小写字母组成一个目标字符串 target. 开始的时候,序列由 target.length 个 '?' 记号组成 而你有一个小写字母印章 stamp. 在每个回合,你可以 ...
- qrcode模块生成二维码
安装qrcode模块 pip install qrcode 简单使用 import qrcode data = 'hello world' img = qrcode.make(data) # 显示二维 ...