NestJS 如何自定义中间件以及实际项目基于中间件提升项目开发效率
前言
NestJS 作为一个强大的 Node.js 框架,允许你通过中间件对请求和响应进行处理。中间件的概念在其他许多框架中也存在,它们在请求处理流程的早期执行,因此非常适合执行如日志记录、请求验证、设置响应头等任务。
在这篇教程中,我将通过一个简单的示例,展示如何在 NestJS 应用中创建和使用自定义中间件。
使用步骤
第一步:创建中间件
在 NestJS 中创建中间件很简单,你只需要创建一个实现了 NestMiddleware
接口的类。这个类将包含一个 use
方法,该方法接收 request
、response
对象和 next
函数。
import { Injectable, NestMiddleware } from '@nestjs/common';
import { Request, Response, NextFunction } from 'express';@Injectable()
export class LoggingMiddleware implements NestMiddleware {use(req: Request, res: Response, next: NextFunction) {console.log(`[${new Date().toISOString()}] Request made to: ${req.path}`);next();}
}
在这个例子中,LoggingMiddleware
类会记录请求到达的时间和路径。
第二步:注册中间件
接下来,你需要在模块中注册这个中间件。这通常在模块的 configure
方法中完成,你需要实现 NestModule
接口并定义这个方法。
import { Module, NestModule, MiddlewareConsumer } from '@nestjs/common';@Module({})
export class AppModule implements NestModule {configure(consumer: MiddlewareConsumer) {consumer.apply(LoggingMiddleware).forRoutes('*'); // 应用到所有路由}
}
在这里,我们使用 MiddlewareConsumer
的 apply
方法来注册中间件,并通过 forRoutes
指定中间件应用的路径。在这个例子中,中间件将应用于所有路由。
第三步:测试中间件
一旦你注册了中间件,它就会在每个请求到来时执行。要测试它,你可以启动你的 NestJS 应用并向任意端点发送请求。
npm run start
然后,打开一个新的命令行窗口发送一个请求(使用 curl 或者任何 API 测试工具):
curl <http://localhost:3000/your-endpoint>
你应该可以在 NestJS 应用的控制台输出中看到日志行,类似于:
[2024-01-01T12:00:00.000Z] Request made to: /your-endpoint
高级使用
中间件不仅仅限于记录日志。你可以利用中间件做很多有用的事情,比如:
- 请求验证: 确认请求是否包含所需的凭证或参数。
- 速率限制: 限制来自同一来源的请求频率,以预防滥用。
- CORS 设置: 在跨域请求中设置必要的头信息,以支持安全的跨域交互。
记住,中间件执行顺序很重要。如果你注册了多个中间件,它们会按顺序执行。这意味着,如果第一个中间件不调用 next()
,后续的中间件和路由处理器都不会被执行。
一、请求验证
假设我们有一个API端点 /secure
,它需要验证请求是否带有有效的API密钥。我们可以创建一个中间件来校验请求头中的 x-api-key
字段。
import { Injectable, NestMiddleware, UnauthorizedException } from '@nestjs/common';
import { Request, Response, NextFunction } from 'express';@Injectable()
export class ApiKeyMiddleware implements NestMiddleware {private readonly VALID_API_KEY = 'secret';use(req: Request, res: Response, next: NextFunction) {const apiKey = req.headers['x-api-key'];if (apiKey && apiKey === this.VALID_API_KEY) {next();} else {throw new UnauthorizedException('Invalid API Key');}}
}
注册这个中间件:
configure(consumer: MiddlewareConsumer) {consumer.apply(ApiKeyMiddleware).forRoutes('/secure');
}
任何请求 /secure
端点的客户端都需要提供有效的API密钥,否则请求会被拒绝。
二、速率限制
为了防止滥用,你可能需要限制客户端在一定时间内能够发送到某个端点的请求数量。这样的中间件可以利用第三方库如 express-rate-limit
实现。
import rateLimit from 'express-rate-limit';export function RateLimiterMiddleware() {return rateLimit({windowMs: 15 * 60 * 1000, // 15分钟max: 100, // 限制每个IP在15分钟内最多100个请求});
}
注册中间件:
configure(consumer: MiddlewareConsumer) {consumer.apply(RateLimiterMiddleware()).forRoutes('/*'); // 适用于所有路由
}
这将会对所有请求施加速率限制,每个IP地址每15分钟只允许最多100个请求。
三、CORS 设置
跨源资源共享(CORS)是一种安全特性,限制了网页上可以加载和使用哪些资源。如果你想允许来自特定来源的请求,你可以使用中间件来设置CORS相关的响应头。
虽然 NestJS 提供了内置的CORS支持,但如果你需要更高级的配置,可以自定义CORS中间件,例如:
import { Injectable, NestMiddleware } from '@nestjs/common';
import { Request, Response, NextFunction } from 'express';@Injectable()
export class CorsMiddleware implements NestMiddleware {use(req: Request, res: Response, next: NextFunction) {res.header('Access-Control-Allow-Origin', '<https://example.com>');res.header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization');next();}
}
注册中间件:
configure(consumer: MiddlewareConsumer) {consumer.apply(CorsMiddleware).forRoutes('/*'); // 适用于所有路由
}
这个简单的CORS中间件允许来自 https://example.com
的请求,并允许 GET
、POST
和 OPTIONS
方法,同时允许 Content-Type
和 Authorization
请求头。
结论
中间件是 NestJS 框架灵活性的关键组成部分,能够通过简单有效的方式实现请求的预处理。上面介绍的高级使用方式,包括请求验证、速率限制和CORS设置,都是实际应用中常见并且非常实用的场景。合理地使用中间件可以让你的应用更加安全和稳定,同时提高用户体验。
结论
中间件是 NestJS 框架灵活性的关键组成部分,能够通过简单有效的方式实现请求的预处理。通过创建 NestMiddleware
接口的实现类,你可以在请求处理链中插入自己的逻辑。注册中间件方法是直观而灵活的,让你可以精确控制中间件的应用范围。
相关文章:
NestJS 如何自定义中间件以及实际项目基于中间件提升项目开发效率
前言 NestJS 作为一个强大的 Node.js 框架,允许你通过中间件对请求和响应进行处理。中间件的概念在其他许多框架中也存在,它们在请求处理流程的早期执行,因此非常适合执行如日志记录、请求验证、设置响应头等任务。 在这篇教程中࿰…...

CMake入门教程【核心篇】设置和使用缓存变量
😈「CSDN主页」:传送门 😈「Bilibil首页」:传送门 😈「动动你的小手」:点赞👍收藏⭐️评论📝 文章目录 概述设置缓存变量使用缓存变量更改缓存变量完整代码示例实战使用技巧注意事项总结与分析...
MinIO (五) .net core实现分片上传
开发环境 Win11 vs2022 appsettings.json添加配置项 //minIO配置"MinIO": {//服务器IP"Endpoint": "192.168.xx.xx:9090",//账号"AccessKey": "3xR7i4zs1vLnxxxxxxxx",//密码"SecretKey": "P6bAnyzJm47Ub…...

如何有效提高矢量网络分析仪的动态范围
动态范围是网络分析仪(VNA)接收机的最大输入功率与最小可测量功率(本底噪声)之间的差值,如图所示,要使测量有效,输入信号必须在这些边界内。 如果需要测量信号幅度非常大的变化,例如…...

Python 安卓开发:Kivy、BeeWare、Flet、Flutter
kivy:https://github.com/kivy python-for-android :https://python-for-android.readthedocs.io/en/latest/ BeeWare:https://docs.beeware.org/en/latest/ Flet:https://github.com/flet-dev/flet 把 PySide6 移植到安卓上去&a…...
50天精通Golang(第16天)
beego框架介绍和流程分析 beego官方文档:https://beego.me/ 一、beego框架介绍 1.1 beego框架介绍–beego简介 1.1.1 什么是beego beego是一个使用Go语言来开发WEB引用的GoWeb框架,该框架起始于2012年,由一位中国的程序员编写并进行公开…...

imx6ull基于yocto工程的l汇编点亮ed
通过汇编点亮led 在裸机状态下通过汇编点亮led,即没有操作系统,(uboot kernel rootfs 都不需要实现)。 led点亮原理 1.GPIO复用 根据原理图,找到led对应的引脚(pin),复用为GPIO(只有GPIO才能…...
vue 前端等比例压缩图片(再转换成文件后上传后端)
前端压缩图片总的来说还是转base64 然后等比例放小宽和高 这个是上次压缩图片的一个扩展 压缩完之后 再将base64 转成blob再转成文件然后再上传 一生要强的前端崽子(后端不支持base64上传) 自己改吧改吧 // 图片上传async changePic(e) {this.isshang…...

解决在eclipse2021中,用mysql-connector-java-8.0.18.jar不兼容,导致无法访问数据库问题
1.环境场景 组件版本mysql5.7.44mysql-connector-java80.18 2. 问题描述 报mysql-connector-java 驱动连不上mysql数据库。 3. 可能的原因分析 查看数据库连接句柄是否对 如果数据库连接句柄中没有 useSSLfalse 的话可能会导致这样的问题。 就像下面这样: jdb…...

5 微信小程序
功能开发 5 功能开发概要今日详细1.发布1.1 发布流程的问题1.2 组件:进度条1.3 修改data中的局部数据1.4 发布示例效果前端后端 1.5 闭包 2.获取前10条新闻(动态/心情,无需分页)3.复杂版4.文章详细页面 各位小伙伴想要博客相关资料…...

百度面经整理(2024最新)
百度 面经1 shiro的组件分布式一致性算法zookeeper那些能参与投票,leader能投票吗?netty零拷贝实现volatile,如何感知到变量变化的redis高可用http如何跨域?tcp如何长链接。http如何操作浏览器缓存。用过消息队列吗?…...

c++的构造函数
目录 构造函数 1.构造函数: 2.构造函数的特点: 默认构造函数 -- 没有参数的构造函数 1. 合成(自动)的默认构造函数(一般不常用) 1) 介绍,以及为什么不使用 2)可以使用合成默认构造函数的情况 2. 自定义的默认…...

基于ZU19EG的100G-UDP解决方案
概述 本文档介绍ZU19EG与Mellanox CX6 100G网卡通信解决方案。 环境配置 FPGA硬件:519-ZU19EG的4路100G光纤PCIe加上计算卡 电脑:国产国鑫主板(双PCU):Gooxi G2DA-B CPU:Intel Xeon Silver 2.2GHz 内存࿱…...

行为型设计模式——备忘录模式
备忘录模式 备忘录模式提供了一种状态恢复的实现机制,使得用户可以方便地回到一个特定的历史步骤,当新的状态无效或者存在问题时,可以使用暂时存储起来的备忘录将状态复原,很多软件都提供了撤销(Undo)操作…...

自定义HBase负载均衡器MyCustomBalancer实现步骤与代码解析
目录 1.HBase默认负载均衡策略 1.1 负载均衡总体流程 1.2 不能触发负载均衡的情况 1.3 负载均衡算法 2.自定义的 HBase 负载均衡器的步骤 3.MyCustomBalancer的代码细节 3.1 balanceCluster 方法的作用 3.2balanceCluster 对数据的影响 3.3监控HBase的性能指标 3.3.…...

企业网站建设中常用的英文翻译
下面好代码网在长期的网站建设业务中总结的,一些在企业网站建设中词语的常用翻译,可以让你的企业网站更具有专业性。如果你做中英文双语版本网站或者外贸网站的请收藏备用。 网站导航 site map 公司简介 PROFILE or COMPANY Profile or Company 综述 Gen…...
vscode运行Python的两种方法,及无法运行的原因
vscode运行Python代码 下面介绍的vscode运行Python代码的方法基于的一个前提条件是:当前的计算机已经安装好了Python,且已经配置好了相关的环境变量。如果要查看是否已经都安装好了,可以打开Windows系统的命令行工具Windows PowerShell&…...

【猫头虎分享】全面揭秘鸿蒙4.0:华为的技术革新与市场影响
博主猫头虎的技术世界 🌟 欢迎来到猫头虎的博客 — 探索技术的无限可能! 专栏链接: 🔗 精选专栏: 《面试题大全》 — 面试准备的宝典!《IDEA开发秘籍》 — 提升你的IDEA技能!《100天精通Golang》…...

Java内存模型之可见性
文章目录 1.什么是可见性问题2.为什么会有可见性问题3.JMM的抽象:主内存和本地内存3.1 什么是主内存和本地内存3.2 主内存和本地内存的关系 4.Happens-Before原则4.1 什么是Happens-Before4.2 什么不是Happens-Before4.3 Happens-Before规则有哪些4.4 演示ÿ…...
【docker】Docker Compose 使用介绍
一、什么是Docker Compose Docker Compose是一个用于定义和运行多个Docker容器的工具。它允许您使用YAML文件来配置应用程序的服务、网络和卷等方面,并通过单个命令即可快速启动和停止整个应用程序的多个容器。 Docker Compose的主要作用如下: 管理多个…...

JavaSec-RCE
简介 RCE(Remote Code Execution),可以分为:命令注入(Command Injection)、代码注入(Code Injection) 代码注入 1.漏洞场景:Groovy代码注入 Groovy是一种基于JVM的动态语言,语法简洁,支持闭包、动态类型和Java互操作性,…...

手游刚开服就被攻击怎么办?如何防御DDoS?
开服初期是手游最脆弱的阶段,极易成为DDoS攻击的目标。一旦遭遇攻击,可能导致服务器瘫痪、玩家流失,甚至造成巨大经济损失。本文为开发者提供一套简洁有效的应急与防御方案,帮助快速应对并构建长期防护体系。 一、遭遇攻击的紧急应…...
【磁盘】每天掌握一个Linux命令 - iostat
目录 【磁盘】每天掌握一个Linux命令 - iostat工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景 注意事项 【磁盘】每天掌握一个Linux命令 - iostat 工具概述 iostat(I/O Statistics)是Linux系统下用于监视系统输入输出设备和CPU使…...

[10-3]软件I2C读写MPU6050 江协科技学习笔记(16个知识点)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16...

DBAPI如何优雅的获取单条数据
API如何优雅的获取单条数据 案例一 对于查询类API,查询的是单条数据,比如根据主键ID查询用户信息,sql如下: select id, name, age from user where id #{id}API默认返回的数据格式是多条的,如下: {&qu…...
在鸿蒙HarmonyOS 5中使用DevEco Studio实现录音机应用
1. 项目配置与权限设置 1.1 配置module.json5 {"module": {"requestPermissions": [{"name": "ohos.permission.MICROPHONE","reason": "录音需要麦克风权限"},{"name": "ohos.permission.WRITE…...

自然语言处理——循环神经网络
自然语言处理——循环神经网络 循环神经网络应用到基于机器学习的自然语言处理任务序列到类别同步的序列到序列模式异步的序列到序列模式 参数学习和长程依赖问题基于门控的循环神经网络门控循环单元(GRU)长短期记忆神经网络(LSTM)…...
Rapidio门铃消息FIFO溢出机制
关于RapidIO门铃消息FIFO的溢出机制及其与中断抖动的关系,以下是深入解析: 门铃FIFO溢出的本质 在RapidIO系统中,门铃消息FIFO是硬件控制器内部的缓冲区,用于临时存储接收到的门铃消息(Doorbell Message)。…...

ubuntu22.04有线网络无法连接,图标也没了
今天突然无法有线网络无法连接任何设备,并且图标都没了 错误案例 往上一顿搜索,试了很多博客都不行,比如 Ubuntu22.04右上角网络图标消失 最后解决的办法 下载网卡驱动,重新安装 操作步骤 查看自己网卡的型号 lspci | gre…...
用递归算法解锁「子集」问题 —— LeetCode 78题解析
文章目录 一、题目介绍二、递归思路详解:从决策树开始理解三、解法一:二叉决策树 DFS四、解法二:组合式回溯写法(推荐)五、解法对比 递归算法是编程中一种非常强大且常见的思想,它能够优雅地解决很多复杂的…...