Express中间件(Middleware)详解:从零开始掌握(3)

实用中间件模式25例

1. 基础增强模式

请求属性扩展
function extendRequest() {return (req, res, next) => {req.getClientLanguage = () => {return req.headers['accept-language']?.split(',')[0] || 'en';};next();};
}
响应时间头
function responseTime() {return (req, res, next) => {const start = Date.now();res.on('finish', () => {res.setHeader('X-Response-Time', `${Date.now() - start}ms`);});next();};
}

2. 安全相关中间件

CSRF防护
function csrfProtection() {return (req, res, next) => {if (['POST', 'PUT', 'DELETE'].includes(req.method)) {const csrfToken = req.headers['x-csrf-token'];if (!csrfToken || csrfToken !== req.session.csrfToken) {return res.status(403).send('Invalid CSRF token');}}next();};
}
CORS配置
function cors(options = {}) {return (req, res, next) => {res.setHeader('Access-Control-Allow-Origin', options.origin || '*');res.setHeader('Access-Control-Allow-Methods', options.methods || 'GET,POST,PUT,DELETE');res.setHeader('Access-Control-Allow-Headers', options.headers || 'Content-Type,Authorization');options.credentials && res.setHeader('Access-Control-Allow-Credentials', 'true');req.method === 'OPTIONS' ? res.sendStatus(200) : next();};
}

3. 数据转换中间件

请求体格式化
function formatBody() {return (req, res, next) => {if (req.body) {// 去除字符串两端的空格Object.keys(req.body).forEach(key => {if (typeof req.body[key] === 'string') {req.body[key] = req.body[key].trim();}});}next();};
}
响应数据包装
function wrapResponse() {return (req, res, next) => {const originalSend = res.send;res.send = function(data) {const wrapped = {status: 'success',data: data,timestamp: new Date().toISOString()};originalSend.call(this, wrapped);};next();};
}

高级组合技巧

1. 中间件条件执行

function when(predicate, middleware) {return (req, res, next) => {predicate(req) ? middleware(req, res, next) : next();};
}// 使用示例
app.use(when(req => req.path.startsWith('/api'),helmet()
));

2. 中间件并行执行

function parallel(middlewares) {return (req, res, next) => {let completed = 0;const done = () => ++completed === middlewares.length && next();middlewares.forEach(mw => {mw(req, res, done);});};
}// 使用示例
app.use(parallel([requestLogger,responseTime,bodyParser.json()
]));

3. 中间件管道

function pipe(...middlewares) {return (req, res, next) => {const run = i => i < middlewares.length ? middlewares[i](req, res, () => run(i + 1)): next();run(0);};
}

性能优化中间件

1. 缓存中间件

function cache(duration) {const cacheStore = new Map();return (req, res, next) => {const key = req.originalUrl;const cached = cacheStore.get(key);if (cached && cached.expiry > Date.now()) {return res.send(cached.data);}const originalSend = res.send;res.send = function(body) {cacheStore.set(key, {data: body,expiry: Date.now() + duration});originalSend.call(this, body);};next();};
}

2. 压缩中间件

const zlib = require('zlib');function compression() {return (req, res, next) => {const acceptEncoding = req.headers['accept-encoding'] || '';const originalSend = res.send;res.send = function(body) {if (acceptEncoding.includes('gzip')) {res.setHeader('Content-Encoding', 'gzip');zlib.gzip(Buffer.from(body), (err, result) => {if (err) return originalSend.call(this, body);originalSend.call(this, result);});} else {originalSend.call(this, body);}};next();};
}

调试与错误处理

1. 调试中间件

function debugMiddleware() {return (req, res, next) => {console.log('--- Request Start ---');console.log(`Method: ${req.method}`);console.log(`Path: ${req.path}`);console.log('Headers:', req.headers);console.log('Query:', req.query);console.log('Body:', req.body);const originalSend = res.send;res.send = function(body) {console.log('--- Response ---');console.log(`Status: ${res.statusCode}`);console.log('Body:', body);originalSend.call(this, body);};next();};
}

2. 错误处理增强

function errorHandler() {return (err, req, res, next) => {console.error(err.stack);const status = err.status || 500;const message = status === 500 ? 'Internal Server Error' : err.message;res.status(status).json({error: {message: message,code: err.code,timestamp: new Date().toISOString(),path: req.path}});};
}

实战项目推荐

  1. API网关:组合各种验证、限流、日志中间件
  2. 文件处理管道:创建文件上传处理链
  3. A/B测试框架:基于中间件的流量分配
  4. 多租户系统:通过中间件识别租户

下节将带来以上更加详尽的项目实践。

Express中间件(Middleware)详解:从零开始掌握(4)-CSDN博客

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

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

相关文章

05--MQTT物联网协议

一、MQTT的概念 MQTT 协议快速入门 2025&#xff1a;基础知识和实用教程 | EMQ 1.MQTT&#xff08;Message Queuing Telemetry Transport&#xff09;是一种轻量级、基于发布-订阅模式的消息传输协议&#xff0c;适用于资源受限的设备和低带宽、高延迟或不稳定的网络环境。它…

数据结构与算法——链表OJ题详解(2)

文章目录 一、前言二、OJ续享2.1相交链表2.2环形链表12.2环形链表2 三、总结 一、前言 哦了兄弟们&#xff0c;咱们上次在详解链表OJ题的时候&#xff0c;有一部分OJ题呢up并没有整理完&#xff0c;这一个星期呢&#xff0c;up也是在不断的学习并且沉淀着&#xff0c;也是终于…

SQL Server AlwaysOn (SQL 查询数据详解及监控用途)

修正后的完整查询 SELECT ar.replica_server_name AS [副本名称],ar.availability_mode_desc AS [同步模式],DB_NAME(dbr.database_id) AS [数据库名称],dbr.database_state_desc AS [数据库状态],dbr.synchronization_state_desc AS [同步状态],dbr.synchronization_health_d…

力扣热题100刷题day63|49.字母异位词分组

目录 一、哈希表相关理论 二、思路 核心思路 三、相关题目 四、总结 一、哈希表相关理论 代码随想录刷题day15|&#xff08;哈希表篇&#xff09;242.有效的字母异位词、383.赎金信-CSDN博客 二、思路 首先&#xff0c;创建一个map集合&#xff0c;遍历字符串数组&…

爱普生可编程晶振SG8201CJ和SG8200CJ在胃镜机器人发挥重要作用

在医疗机器人技术高速发展的今天&#xff0c;胃镜机器人作为胃肠道疾病诊断与治疗的创新设备&#xff0c;正逐渐改变传统诊疗模式。其复杂精密的系统需要精准的时间同步与稳定的信号输出&#xff0c;胃镜机器人是一种先进的医疗设备&#xff0c;用于无创性地检查胃部疾病。与传…

Ubuntu22环境下,Docker部署阿里FunASR的gpu版本

番外: 随着deepseek的爆火,人工智能相关的开发变得异常火爆,相关的大模型开发很常见的agent智能体需要ASR语音识别的功能,阿里开源的FunASR几乎是把一个商业的项目放给我们使用了。那么我们项目中的生产环境怎么部署gpu版本的语音识别服务呢?经过跟deepseek的一上午的极限…

图解Java设计模式

1、设计模式面试题 2、设计模式的重要性 3、7大设计原则介绍 3.1、单一职责原则

transformers的 pipeline是什么:将模型加载、数据预处理、推理等步骤进行了封装

transformers的 pipeline是什么:将模型加载、数据预处理、推理等步骤进行了封装 pipe = pipeline("text-generation", model=model, tokenizer=tokenizer, max_new_tokens=50 )pipeline :这是 transformers 库中一个非常实用的工具函数。它可以基于预训练模型快速构…

jmeter插件安装

1、下载 下载地址&#xff1a; Documentation :: JMeter-Plugins.org 然后复制到D:\apache-jmeter-5.6.3\lib\ext 复制后 2、重启jmeter 在菜单【选项】找到“Plugins Manager” 在 Plugins Manager 界面上&#xff0c;点击“Available Plugins”标签页&#xff0c;可以浏览所…

VSCode CMake调试CPP程序

文章目录 1 安装C与CMake插件2 配置CMakeLists.txt3 使用CMake编译调试3.1 编译3.2 调试 4 自定义构建调试参考 1 安装C与CMake插件 C插件 CMake插件 2 配置CMakeLists.txt 编写测试程序 #include<iostream>int main(int argc, char const *argv[]) {int a 1, b 2;i…

【前端】【css】flex布局详解

Flex 布局&#xff08;Flexible Box Layout&#xff0c;弹性盒子布局&#xff09;是 CSS3 中的一种布局模式&#xff0c;用于在容器中更高效地分配空间并对齐内容&#xff0c;即使它们的大小是动态未知的。它非常适用于响应式设计。 一、Flex 布局的基本概念 1. 启用 Flex 布局…

LEARNING DYNAMICS OF LLM FINETUNING【论文阅读笔记】

LEARNING DYNAMICS OF LLM FINETUNING 一句话总结 作者将LLM的学习动力机制拆解成AKG三项&#xff0c;并分别观察了SFT和DPO训练过程中​​正梯度信号​​和​​负梯度信号​​的变化及其带来的影响&#xff0c;并得到以下结论&#xff1a; ​​SFT通过梯度相似性间接提升无关…

Mac 下载 PicGo 的踩坑指南

Mac 下载 PicGo 的踩坑指南 一、安装问题 下载地址&#xff1a;https://github.com/Molunerfinn/PicGo/releases 下载之后直接安装即可&#xff0c;此时打开会报错&#xff1a;Picgo.app 文件已损坏&#xff0c;您应该将它移到废纸篓。 这是因为 macOS 为了保护用户不受恶意…

Element UI 设置 el-table-column 宽度 width 为百分比无效

问题描述&#xff1a; 想要每列宽度不同&#xff0c;不想使用 px 固定值&#xff0c;将 width 设置成百分比&#xff0c;但是每一列还是很窄 原因&#xff1a; el-table 组件会被 vue 解析成 html&#xff0c;vue 直接把百分号去掉把数值当做列宽来呈现&#xff0c;所以&#x…

第五篇:Python面向对象编程(OOP)深度教程

1. 类与对象 1.1 基本概念 ​​类​​是创建对象的蓝图,定义了对象的​​属性​​(数据)和​​方法​​(行为)。​​对象​​是类的实例化实体,每个对象拥有独立的属性值和共享的类方法 ​​示例​​:定义Dog类 class Dog:species = "Canis familiaris" …

【数据结构】2.顺序表实现通讯录

文章目录 一、通讯录的要求二、通讯录的具体实现0、 准备工作1、通讯录的初始化2、通讯录的销毁3、通讯录的展示4、通讯录添加数据5、通讯录删除数据6、通讯录的查找7、通讯录的修改8、保存通讯录数据到文件9、读取文件内容到通讯录 三、 通讯录的完整实现 一、通讯录的要求 通…

程序化广告行业(79/89):技术革新与行业发展脉络梳理

程序化广告行业&#xff08;79/89&#xff09;&#xff1a;技术革新与行业发展脉络梳理 大家好&#xff01;一直以来&#xff0c;我都热衷于在技术领域不断探索&#xff0c;也深知知识共享对于进步的重要性。写这篇博客&#xff0c;就是希望能和大家一起深入研究程序化广告行业…

【C++游戏引擎开发】第9篇:数学计算库GLM(线性代数)、CGAL(几何计算)的安装与使用指南

写在前面 两天都没手搓实现可用的凸包生成算法相关的代码&#xff0c;自觉无法手搓相关数学库&#xff0c;遂改为使用成熟数学库。 一、GLM库安装与介绍 1.1 vcpkg安装GLM 跨平台C包管理利器vcpkg完全指南 在PowerShell中执行命令&#xff1a; vcpkg install glm# 集成到系…

python文件打包无法导入ultralytics模块

&#x1f4a5;打包的 .exe 闪退了&#xff1f;别慌&#xff01;教你逐步排查 PyInstaller 打包的所有错误&#xff01; &#x1f6e0; 运行 .exe 查看报错信息✅ 正确姿势&#xff1a; ⚠ importlib 动态导入导致打包失败❓什么是动态导入&#xff1f;✅ 解决方式&#xff1a; …

【React框架】什么是 Vite?如何使用vite自动生成react的目录?

什么是 Vite&#xff1f; Vite 是一个基于原生 ES Modules 开发的前端构建工具&#xff0c;由 Evan You&#xff08;Vue 的作者&#xff09;开发。它最大的特点包括&#xff1a; 极速冷启动&#xff1a;因为利用了浏览器原生的 ES Modules&#xff0c;所以在开发时无需等待整…