NestJS 如何自定义中间件以及实际项目基于中间件提升项目开发效率

前言

NestJS 作为一个强大的 Node.js 框架,允许你通过中间件对请求和响应进行处理。中间件的概念在其他许多框架中也存在,它们在请求处理流程的早期执行,因此非常适合执行如日志记录、请求验证、设置响应头等任务。

在这篇教程中,我将通过一个简单的示例,展示如何在 NestJS 应用中创建和使用自定义中间件。

使用步骤

第一步:创建中间件

在 NestJS 中创建中间件很简单,你只需要创建一个实现了 NestMiddleware 接口的类。这个类将包含一个 use 方法,该方法接收 requestresponse 对象和 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('*'); // 应用到所有路由}
}

在这里,我们使用 MiddlewareConsumerapply 方法来注册中间件,并通过 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 的请求,并允许 GETPOSTOPTIONS 方法,同时允许 Content-TypeAuthorization 请求头。

结论

中间件是 NestJS 框架灵活性的关键组成部分,能够通过简单有效的方式实现请求的预处理。上面介绍的高级使用方式,包括请求验证、速率限制和CORS设置,都是实际应用中常见并且非常实用的场景。合理地使用中间件可以让你的应用更加安全和稳定,同时提高用户体验。

结论

中间件是 NestJS 框架灵活性的关键组成部分,能够通过简单有效的方式实现请求的预处理。通过创建 NestMiddleware 接口的实现类,你可以在请求处理链中插入自己的逻辑。注册中间件方法是直观而灵活的,让你可以精确控制中间件的应用范围。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/617613.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Mac 下载 nvm 后执行nvm -v 命令报错 nvm: command not found

1、问题&#xff1a;Mac 使用命令下载nvm 成功后执行 nvm -v 查看&#xff0c;报错&#xff1a;nvm command not found 2、原因&#xff1a;可能是系统更新后&#xff0c;默认的 shell 是 zsh&#xff0c;所以找不到配置文件 3、解决&#xff1a;可添加编辑.bash_profile 和 …

回归和拟合的关系

在统计学和机器学习中&#xff0c;回归&#xff08;Regression&#xff09;和拟合&#xff08;Fitting&#xff09;是密切相关的概念&#xff0c;它们通常一起使用来描述如何通过模型来逼近或拟合数据。 回归&#xff08;Regression&#xff09;&#xff1a; 回归是一种统计学…

Docker 安装部署

1、Docker 安装 ① 卸载docker&#xff0c;清空之前的docker文件 yum remove docker \docker-client \docker-client-latest \docker-common \docker-latest \docker-latest-logrotate \docker-logrotate \docker-selinux \docker-engine-selinux \docker-engine \docker-ce…

2021腾讯、华为前端面试题集(基础篇)

Vue 面试题 生命周期函数面试题 1.什么是 vue 生命周期2.vue 生命周期的作用是什么 3.第一次页面加载会触发哪几个钩子 4.简述每个周期具体适合哪些场景 5.created 和 mounted 的区别 6.vue 获取数据在哪个周期函数 7.请详细说下你对 vue 生命周期的理解&#xff1f; **vue 路由…

达梦数据库主备集群

1&#xff1a;服务器硬件需求 按实际业务需求&#xff0c;选择合适的服务器&#xff0c;准备 3 台服务器&#xff0c;一台主库服务器&#xff0c;一台备库服务器&#xff0c;一台监视器服务器&#xff0c;服务器参数建议如下&#xff1a; 硬件要求物理内存>16 GB交换区Swa…

MySQL同步ES的几种方案

MySQL数据同步ES的几种方案 1. 同步双写 与业务耦合深&#xff0c;且业务响应时间长 2. 异步双写 这时可以使用类似MQ这样的中间件&#xff0c;业务主写时向MQ发送一条信息&#xff0c;再由一个聚合服务区消费&#xff0c;最终同步到ES 3. 定时任务 不好配置时间&#xff0c;…

Spring Boot - Application Events 的发布顺序_ContextRefreshedListener

文章目录 Pre概述Code源码分析 Pre Spring Boot - Application Events 的发布顺序_ApplicationEnvironmentPreparedEvent 概述 Spring Boot 的广播机制是基于观察者模式实现的&#xff0c;它允许在 Spring 应用程序中发布和监听事件。这种机制的主要目的是为了实现解耦&#…

2024年最新软件测试面试题

Part1 1、你的测试职业发展是什么&#xff1f;【文末有面试文档免费领取】 测试经验越多&#xff0c;测试能力越高。所以我的职业发展是需要时间积累的&#xff0c;一步步向着高级测试工程师奔去。而且我也有初步的职业规划&#xff0c;前3年积累测试经验&#xff0c;按如何做…

Python——猜猜心里的数字(2)

1、数字随机产生&#xff0c;范围1-10 2、有三次机会猜数字通过三层嵌套 3、每次猜不中&#xff0c;提示大小 import random numrandom.randint(1,10) guess_num int(input("请输入您猜测的值&#xff1a;")) if guess_numnum:print("恭喜你&#xff0c;第一次…

【漏洞复现】Office365-Indexs-任意文件读取

漏洞描述 Office 365 Indexs接口存在一个任意文件读取漏洞,攻击者可以通过构造精心设计的请求,成功利用漏洞读取服务器上的任意文件,包括敏感系统文件和应用程序配置文件等。通过利用此漏洞,攻击者可能获得系统内的敏感信息,导致潜在的信息泄露风险 免责声明 技术文章…

LLM之长度外推(二)| Self-Extend:无需微调的自扩展大模型上下文窗口

论文链接&#xff1a;https://simg.baai.ac.cn/paperfile/a34ae7f4-f0ce-4f8f-b8f2-e8e4d84bbee5.pdf 目前大模型基本都采用transformer结构&#xff0c;而transformer中attention机制的计算复杂度与序列长度呈平方关系&#xff0c;因此大模型在训练时候通常会设置固定的上下文…

案例117:基于微信小程序的新闻资讯系统设计与实现

文末获取源码 开发语言&#xff1a;Java 框架&#xff1a;springboot JDK版本&#xff1a;JDK1.8 数据库&#xff1a;mysql 5.7 开发软件&#xff1a;eclipse/myeclipse/idea Maven包&#xff1a;Maven3.5.4 小程序框架&#xff1a;uniapp 小程序开发软件&#xff1a;HBuilder …

NES 模拟器中音画同步问题

背景 模拟器是与游戏和播放器都有相似之处的系统。模拟器与游戏的相似之处&#xff0c;在于都需要一个采集输入–执行逻辑–然后按一定帧率&#xff08;通常是 60 FPS&#xff09;把画面显示出来的循环。但是模拟器又需要模拟音频设备&#xff0c;播放音频设备产生的声音样本&…

Ubuntu搭建OpenCV环境(C++)

Ubuntu搭建OpenCV环境(C) 文章目录 Ubuntu搭建OpenCV环境(C)一、环境介绍二、依赖安装三、安装包下载四、opencv安装五、测试 一、环境介绍 虚拟机 &#xff1a;VMware 15.5 OS &#xff1a; Ubuntu 20.04 opencv 版本 &#xff1a; 4.9.0 操作系统安装本文不再赘述&#x…

学习Vue封装的过渡与动画总结

今天学习了Vue封装的过渡与动画&#xff0c;接下来说一下Vue是如何实现的&#xff0c;首先原生的方法是在style元素中给指定元素添加过渡的过渡或动画&#xff0c;但Vue就不需要直接获取到需要过渡或动画的元素&#xff0c;而是使用一个<transition>的标签来包裹住想要过…

py的函数讲解

前言:本章节我们来讲函数&#xff0c;主播略微感觉到有点小难&#xff0c;友友们需要认真看 目录 一.初始函数 1.1关于函数 1.2举例 1.3小结 二.函数的基础语法 2.1关于函数的语法 2.2举例 2.3小结 三.函数的参数 3.1关于函数的参数 3.2举例 3.3小结 四.函数的返回…

Arduino实现简易颜色识别机械臂

机械臂 一 功能原理1 硬件设备2 arduino库3 工作原理 二 代码设计全局参数1 颜色识别2 机械臂转动3 机械臂复位 三 展示效果 一 功能原理 识别出不同颜色的物体&#xff0c;让机械臂进行夹取并放入不同位置。 1 硬件设备 2 arduino库 3 工作原理 二 代码设计 项目重点划分…

如何在 SwiftUI 中实现音频图表

文章目录 前言DataPoint 结构体BarChartView 结构体ContentView 结构体实现协议实现线图总结 前言 在可访问性方面&#xff0c;图表是复杂的事物之一。iOS 15 引入了一项名为“音频图表”的新功能。 下面我们将学习如何通过使用 accessibilityChartDescriptor 视图修饰符为任…

用友NC Cloud IUpdateService接口存在XXE漏洞

免责声明:请勿利用文章内的相关技术从事非法测试,由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损失,均由使用者本人负责,所产生的一切不良后果与文章作者无关。该文章仅供学习用途使用。 1. 用友NC 简介 微信公众号搜索:南风漏洞复现文库 该…

Shutter Encoder多媒体转换v17.8

软件介绍 多媒体包含种类繁多的各种文件格式&#xff0c;每种格式都有其不同的特征和所谓的“怪癖”。 因此&#xff0c;如果使用多种图像、视频或音频格式&#xff0c;找到一个集中的软件来从一个地方处理所有这些格式可能会非常棘手。 这就是 Shutter Encoder 基本上允许做的…