Express中间件(Middleware)详解:从零开始掌握(4)
下面我将为你提供四个实战项目的完整实现代码,每个项目都展示了Express中间件的实际应用场景。
1. API网关实现
const express = require('express');
const rateLimit = require('express-rate-limit');
const helmet = require('helmet');
const morgan = require('morgan');const app = express();// 1. 安全中间件
app.use(helmet());// 2. 请求日志
app.use(morgan('combined'));// 3. API密钥验证
app.use((req, res, next) => {const apiKey = req.headers['x-api-key'];const validKeys = ['key123', 'key456'];if (!validKeys.includes(apiKey)) {return res.status(401).json({ error: 'Invalid API Key' });}next();
});// 4. 限流中间件
const apiLimiter = rateLimit({windowMs: 15 * 60 * 1000, // 15分钟max: 100, // 每个IP限制100个请求message: 'Too many requests from this IP, please try again later'
});
app.use(apiLimiter);// 5. 路由转发
const { createProxyMiddleware } = require('http-proxy-middleware');
app.use('/users', createProxyMiddleware({ target: 'http://user-service:3000', changeOrigin: true
}));
app.use('/products', createProxyMiddleware({ target: 'http://product-service:3000', changeOrigin: true
}));// 6. 错误处理
app.use((err, req, res, next) => {console.error(err.stack);res.status(500).json({ error: 'Internal Server Error' });
});app.listen(3000, () => {console.log('API Gateway running on port 3000');
});
2. 文件处理管道
const express = require('express');
const multer = require('multer');
const path = require('path');
const fs = require('fs');
const sharp = require('sharp');const app = express();// 1. 文件存储配置
const storage = multer.diskStorage({destination: (req, file, cb) => {const uploadDir = 'uploads/';if (!fs.existsSync(uploadDir)) {fs.mkdirSync(uploadDir);}cb(null, uploadDir);},filename: (req, file, cb) => {cb(null, `${Date.now()}-${file.originalname}`);}
});const upload = multer({ storage });// 2. 文件类型验证中间件
function validateFile(req, res, next) {const allowedTypes = ['image/jpeg', 'image/png'];if (!allowedTypes.includes(req.file.mimetype)) {return res.status(400).json({ error: 'Invalid file type' });}next();
}// 3. 图片处理中间件
async function processImage(req, res, next) {try {const outputPath = `processed/${req.file.filename}`;await sharp(req.file.path).resize(800, 800, { fit: 'inside' }).toFormat('jpeg', { quality: 80 }).toFile(outputPath);req.file.processedPath = outputPath;next();} catch (err) {next(err);}
}// 4. 文件上传路由
app.post('/upload', upload.single('file'), // 1. 接收文件validateFile, // 2. 验证类型processImage, // 3. 处理图片(req, res) => { // 4. 返回结果res.json({ original: req.file.path,processed: req.file.processedPath });}
);// 错误处理
app.use((err, req, res, next) => {console.error(err);res.status(500).json({ error: 'File processing failed' });
});app.listen(3000, () => {console.log('File processor running on port 3000');
});
3. A/B测试框架
const express = require('express');
const cookieParser = require('cookie-parser');
const app = express();app.use(cookieParser());// 1. A/B测试分配中间件
app.use((req, res, next) => {// 如果已经有分组cookie,继续使用if (req.cookies.abTestGroup) {req.abTestGroup = req.cookies.abTestGroup;return next();}// 随机分配A组或B组const group = Math.random() < 0.5 ? 'A' : 'B';res.cookie('abTestGroup', group, { maxAge: 30 * 24 * 60 * 60 * 1000 }); // 30天req.abTestGroup = group;next();
});// 2. 不同版本的页面处理
function variantA(req, res) {res.send(`<h1 style="color: blue">Version A</h1><p>This is the original version of our page</p>`);
}function variantB(req, res) {res.send(`<h1 style="color: green">Version B</h1><p>This is the experimental version of our page</p>`);
}// 3. 路由处理
app.get('/home', (req, res) => {// 根据分组显示不同版本req.abTestGroup === 'A' ? variantA(req, res) : variantB(req, res);
});// 4. 结果跟踪
app.get('/track-conversion', (req, res) => {const { group } = req.query;console.log(`Conversion recorded for group ${group}`);res.sendStatus(200);
});// 5. 分析仪表板
app.get('/dashboard', (req, res) => {// 这里应该是从数据库获取实际数据const stats = {A: { views: 1000, conversions: 100 },B: { views: 950, conversions: 120 }};res.json(stats);
});app.listen(3000, () => {console.log('A/B Testing Framework running on port 3000');
});
4. 多租户系统
const express = require('express');
const app = express();// 模拟租户数据
const tenants = {'tenant1': { dbConfig: { host: 'tenant1.db.example.com',name: 'tenant1_db'},theme: 'blue'},'tenant2': { dbConfig: { host: 'tenant2.db.example.com',name: 'tenant2_db'},theme: 'green'}
};// 1. 租户识别中间件
app.use((req, res, next) => {// 从子域名识别租户 (tenant1.example.com)const hostParts = req.hostname.split('.');const tenantId = hostParts.length > 2 ? hostParts[0] : null;// 或者从请求头识别// const tenantId = req.headers['x-tenant-id'];if (!tenantId || !tenants[tenantId]) {return res.status(404).send('Tenant not found');}req.tenant = tenants[tenantId];req.tenant.id = tenantId;next();
});// 2. 租户数据库连接中间件
app.use((req, res, next) => {// 模拟数据库连接console.log(`Connecting to tenant database: ${req.tenant.dbConfig.host}`);// 实际应用中这里会建立数据库连接next();
});// 3. 租户特定路由
app.get('/dashboard', (req, res) => {res.send(`<h1 style="color: ${req.tenant.theme}">Dashboard for ${req.tenant.id}</h1><p>Connected to database: ${req.tenant.dbConfig.name}</p>`);
});// 4. 租户配置API
app.get('/api/config', (req, res) => {res.json({tenant: req.tenant.id,theme: req.tenant.theme,dbConfig: req.tenant.dbConfig});
});// 错误处理
app.use((err, req, res, next) => {console.error(`[${req.tenant?.id}]`, err);res.status(500).send('Tenant-specific error occurred');
});app.listen(3000, () => {console.log('Multi-tenant system running on port 3000');
});
项目部署与测试建议
-
API网关:
- 测试不同API密钥的访问
- 测试限流功能
- 使用Postman测试路由转发
-
文件处理管道:
- 测试不同文件类型的上传
- 检查处理后的图片质量
- 测试大文件上传性能
-
A/B测试框架:
- 清除cookie测试分组分配
- 模拟转换事件
- 分析不同版本的表现
-
多租户系统:
- 测试不同子域名的访问
- 模拟租户特定的错误
- 测试租户隔离性
相关文章:
Express中间件(Middleware)详解:从零开始掌握(4)
下面我将为你提供四个实战项目的完整实现代码,每个项目都展示了Express中间件的实际应用场景。 1. API网关实现 const express require(express); const rateLimit require(express-rate-limit); const helmet require(helmet); const morgan require(morgan)…...
Ubuntu22环境下,Docker部署阿里FunASR的gpu版本
番外: 随着deepseek的爆火,人工智能相关的开发变得异常火爆,相关的大模型开发很常见的agent智能体需要ASR语音识别的功能,阿里开源的FunASR几乎是把一个商业的项目放给我们使用了。那么我们项目中的生产环境怎么部署gpu版本的语音识别服务呢?经过跟deepseek的一上午的极限…...
vue springboot 案例 收集
vue springboot 案例 收集 SpringbootVue前后端分离项目-管理系统 https://blog.csdn.net/m0_56308072/article/details/130893828...
Windows环境下本地部署deepseek-r1或其他大模型 【保姆级教程】
目录 背景准备工作开始部署下载olloma安装olloma下载deepseek-r1模型使用如何使用 结束语 背景 最近deepseek本地部署的概念越来越火,勾起了我学习的兴趣。 我就在思考如何使用家用机或者平时打游戏的机器来本地部署deepseek,给自己开发个智能体来辅佐…...
ubuntu20.04系统安装apollo10.0系统
文章目录 前言一、安装基础软件1、更新相关软件2 安装 Docker Engine 二、获取 GPU 支持1、安装显卡驱动2、安装 Nvidia container toolkit 三、安装 Apollo 环境管理工具1、安装依赖软件2、在宿主机添加 Apollo 软件源的 gpg key,并设置好源和更新3、安装aem 四、安…...
图片文本识别OCR+DeepSeekapi实现提取图片关键信息
用到的技术: 通过腾讯OCR文字识别,deepseek的api实现 目录 需求分析: 文字识别(OCR)具体实现步骤 起步工作 代码编写 deepseek整合消息,返回文本关键信息 起步工作 编写工具类 具体调用实现 具体…...
minio改成https+域名访问
思路有两个: 方式一:通过nginx反向代理,将https配置在nginx,内部的MinIO还是使用HTTP;方式二:MinIO服务端直接配置成HTTPS; 注意: 私钥需要命名为:private.key 公钥需要…...
unity与usb串口通信(web版)
一、本文介绍在web环境下unity与usb串口进行通信的代码 本篇使用本地服务器作为unity与串口的中介,unity发送数据到服务器,服务器发送给串口收到响应并解析返回给uinty。 使用websocket协议。 注: 1.我的硬件是检测磁阻液位,用…...
UE5每次都打开上一次的工程文件 , 如何取消?
点击左上角 - 文件 点击 打开项目 取消勾选 - 启动时固定加载上次打开的项目...
AI大模型与人类未来的协作图景:从工具到“数字共生体”
📝个人主页🌹:慌ZHANG-CSDN博客 🌹🌹期待您的关注 🌹🌹 一、引言:技术跃迁与文明重塑的十字路口 2020年代以来,人工智能特别是**AI大语言模型(Large Language Models, LLMs)**的迅猛发展,正在从根本上改变人类与技术的关系。从最初的“智能写作助手”到今日…...
C++ I/O 性能优化指南
在高性能计算和大规模数据处理中,I/O 性能优化是提升系统整体效率的关键环节。C 作为一种高性能编程语言,提供了丰富的工具和机制来优化 I/O 操作。本文将详细介绍在 Linux 环境下,如何通过代码层面的优化、系统调用的选择以及多线程技术等手…...
Idea忽略已提交文件
全局忽略 项目根目录下新增.gitignore文件,写入想要忽略的信息,以下可参考 **/src/main/resources/application-local.yamltarget/ !.mvn/wrapper/maven-wrapper.jar !**/src/main/**/target/ !**/src/test/**/target/### IntelliJ IDEA ### .idea/mod…...
Mamba原理及在low-level vision的工作[持续更新]
文章目录 Mamba原理选择性扫描(Selective Retain Information):选择有关/无关信息状态空间模型(SSM)Mamba的选择性保留信息Mamba的扫描操作(The Scan Operation) 硬件感知(Hardware-…...
openlayers入门02 -- 地图控件
地图控件 1.视图跳转控件(ZoomToExtent) 视图跳转控件用于将地图快速跳转到指定的范围。示例: // 视图跳转控件(extent这里用的是学校的经纬度范围,可以按照需要修改) const ZoomToExtent new ol.contro…...
Python 装饰器(Decorator)
文章目录 代码解析1. 装饰器定义 timer(func)2. 应用装饰器 timer **执行流程****关键点****实际应用场景****改进版本(带 functools.wraps)** 这是一个 Python 装饰器(Decorator) 的示例,用于测量函数的执行时间。下…...
UE的AI判断队伍归属的机制:IGenericTeamAgentInterface接口
从官方论坛老哥那学来的,优点在于使用项目设置,像配置碰撞一样,能配置碰撞通道对其他碰撞通道的反应,如阻挡,忽略,重叠,全局配置队伍归属,也能配置当前队伍对其他队伍的身份识别&…...
安宝特新闻丨Vuzix Core™波导助力AR,视角可调、高效传输,优化开发流程
Vuzix Core™ 光波导技术 近期,Vuzix Core™光波导技术赋能AR新视界!该系列镜片支持定制化宽高比调节及20至40视场角范围,可灵活适配各类显示引擎。通过创新的衍射光波导架构,Vuzix Core™实现了光学传输效率与图像质量的双重突破…...
基于springboot留守儿童网站的设计与实现 docx
收藏关注不迷路!! 🌟文末获取源码数据库🌟 感兴趣的可以先收藏起来,还有大家在毕设选题(免费咨询指导选题),项目以及论文编写等相关问题都可以给我留言咨询,希望帮助更多…...
AST 技术进行 JavaScript 反混淆实战
一、AST 技术核心原理 抽象语法树(AST) 是代码的“骨架”,它把代码拆解成一个个节点,就像把一棵大树拆成树枝、树叶一样。通过分析和修改这些节点,我们可以精准地还原代码的逻辑。 二、实战案例 1:还原字…...
基于ECharts+Spark的疫情防控数据分析平台(源码+lw+部署文档+讲解),源码可白嫖!
摘要 时代在飞速进步,每个行业都在努力发展现在先进技术,通过这些先进的技术来提高自己的水平和优势,特别是近几年来,新冠疫情出现以来,疫情防控数据分析平台当然不能排除在外。我本次开发的疫情防控数据分析平台是在…...
wireshark过滤器表达式的规则
1.抓包过滤器语法和实例 抓包过滤器类型Type(host、net、port)、方向Dir(src、dst)、协议Proto(ether、ip、tcp、udp、http、icmp、ftp等)、逻辑运算符(&&与、|| 或、!非&am…...
使用 Python 扫描 Windows 下的 Wi-Fi 网络实例演示
使用 Python 扫描 Windows 下的 Wi-Fi 网络 代码实现代码解析 1. 导入库2. 解码混合编码3. 扫描 Wi-Fi 网络4. 运行函数 这是我当前电脑的 wifi 连接界面。 这个是运行的效果图: 代码实现 我们使用了 Python 的 subprocess 模块来调用 Windows 的内置命令 netsh…...
Redis 字符串(String)详解
1. 什么是字符串类型 在 Redis 中,字符串(String) 是最基本的数据类型。它可以包含任何数据,比如文本、JSON、甚至二进制数据(如图片的 Base64 编码),最大长度为 512 MB。 字符串在 Redis 中不…...
【Taro3.x + Vue3】搭建微信小程序
IOS环境为例 打开终端环境有多种办法,例举一个:在访达里新建一个文件夹,鼠标右键选择。 一、先安装Taro的环境 npm install -g tarojs/cli安装完成后,可以输入命令检验是否安装成功: taro --version二、创建项目 …...
P8668 [蓝桥杯 2018 省 B] 螺旋折线
题目 思路 一眼找规律题,都 1 0 9 10^9 109说明枚举必然超时,找规律,每个点找好像没有什么规律,尝试找一下特殊点,比如:对角线上的点 4 16 36(右上角) 4k^2,看在第几层(…...
【14】数据结构之哈夫曼树篇章
目录标题 哈夫曼树哈夫曼树的定义哈夫曼树的构造哈夫曼编码哈夫曼树的实现 哈夫曼树 哈夫曼树的定义 路径:从一个结点到另一个结点的路线树的路径长度:从树根到树中每个结点的路径长度之和结点的权:在一些应用中,赋予树中结点的…...
初识SpringAI(接入硅基流动deepseek)
①创建项目 ②application.yml spring:application:name: pgs-aiai:openai:api-key: sk-vrozloxjpjgkozaggtodbmwyfmubmxqpdpbvbbxpcgleanugbase-url: https://api.siliconflow.cn/chat:options:model: deepseek-ai/DeepSeek-V3 api-key:去硅基流动官网生成你的密钥…...
两个有序序列合并算法分析
一 问题背景 合并两个有序序列是常见操作,例如在归并排序中。传统方法需要额外空间,时间复杂度为 O(n)。但若要求原地合并(不占用额外内存),则需借助 手摇算法(或称内存反转或三次反转算法)。 二 手摇算法原理 手摇算法通过三次反转操作,实现数组片段的原…...
Robot---SPLITTER行星探测机器人
1 背景 先给各位读者朋友普及一个航天小知识,截止到目前为止,登陆火星的火星车有哪些?结果比较令人吃惊:当前只有美国和中国登陆过火星。 “勇气”号(Spirit):2004年1月4日,美国国家…...
kafka的topic扩容分区会对topic任务有什么影响么
在 Kafka 中对 Topic 进行扩容分区会对相关任务产生多方面的影响,下面为你详细介绍: 积极影响 增强并发处理能力:Kafka 中数据是以分区为单位进行并行处理的,增加分区数量意味着可以让更多的消费者并行消费数据。比如࿰…...
每日一题(小白)模拟娱乐篇27
由题意可以得知这是一道暴力模拟的题目,我们只需要根据题意说的模拟整个过程即可。首先需用循环接收n个数字,每次判断这个数字是否出现过,若没有出现则为对应的负值,若出现过则需要将这个坐标减去之前坐标的值再减一返回ÿ…...
进行性核上性麻痹患者,饮食 “稳” 健康
进行性核上性麻痹作为一种复杂且罕见的神经系统退行性疾病,给患者的身体机能和日常生活带来严重挑战。在积极接受专业治疗的同时,合理的饮食安排对于维持患者营养状况、缓解症状及提升生活质量起着关键作用。以下为患者提供一些健康饮食建议。 首先&…...
GitLab之搭建(Building GitLab)
GitLab之搭建 “ 在企业开发过程中,GitLab凭借其强大的版本管理、CI/CD集成和项目管理功能,成为许多团队的首选工具。本文将探讨GitLab的基础介绍、搭建过程、权限管理、代码审查以及团队知识管理等方面。通过详细的步骤和实用的技巧,旨在帮…...
R 语言科研绘图第 38 期 --- 饼状图-玫瑰
在发表科研论文的过程中,科研绘图是必不可少的,一张好看的图形会是文章很大的加分项。 为了便于使用,本系列文章介绍的所有绘图都已收录到了 sciRplot 项目中,获取方式: R 语言科研绘图模板 --- sciRplothttps://mp.…...
array和list在sql中的foreach写法
在MyBatis中,<foreach>标签用于处理集合或数组类型的参数,以便在SQL语句中动态生成IN子句或其他需要遍历集合的场景。以下是array和list在SQL中的<foreach>写法总结。 <if test"taskIds ! null and taskIds.length > 0">…...
国内MCP服务有哪些?MCP服务器搜索引擎哪家好?
随着MCP(Model Context Protocol)协议的广泛应用,国内出现了越来越多的MCP服务提供商,这些服务覆盖了从开发工具、数据科学到金融、游戏等多个领域。 如果你对MCP协议和相关开发感兴趣,可以访问AIbase(htt…...
二叉树的应用
目录 一、二叉树遍历算法的应用 二、树的存储结构 1、双亲表示法 2、孩子表示法 带双亲的孩子链表 3、孩子兄弟表示法(左孩子、右兄弟)较为普遍 三、森林与二叉树的转换 四、哈夫曼树 哈夫曼(Huffman)树的构造 一、二叉树…...
【LaTeX】
基本使用 \documentclass 类型:文章(article)、报告(report)、书(book) 中文的文章是ctexart,中文字体是UTF8 \documentclass[UTF8]{ctexart} []说明可以省略不写的意思…...
Java基础 - 泛型(基本概念)
文章目录 基本概念参数化类型类型安全和编译时检查 为什么需要泛型?解决类型安全问题避免重复代码提高可读性和维护性 泛型(Generics)是编程语言中一种支持参数化类型的特性,允许在定义类、接口、方法时使用类型参数(T…...
面试之《前端信息加密》
前端代码是直接暴漏给用户的,请求的接口也可以通过控制台network看到参数,这是不够安全的,如果遇到坏人想要破坏,可以直接修改参数,或者频繁访问导致系统崩溃,或数据毁坏。 所以信息加密在某些场合就变得非…...
【含文档+PPT+源码】基于微信小程序的小区物业收费管理系统
项目视频介绍: 毕业作品基于微信小程序的小区物业收费管理系统 课程简介: 本课程演示的是一款基于微信小程序的小区物业收费管理系统,主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的 Java 学习者。 1.包含:项目…...
KDD 2025 顶会最新力作,多变量时间序列预测登顶!
在多变量时间序列预测领域,如何高效捕捉时间分布变化和通道间复杂关系是两大核心挑战。传统方法往往难以同时处理时间模式的异质性和通道间的噪声影响。近期,基于时频结合的方法在这一领域取得了显著进展。本文总结了两篇创新性论文,分别从时…...
for循环的优化方式、循环的种类、使用及平替方案。
本篇文章主要围绕for循环,来讲解循环处理数据中常见的六种方式及其特点,性能。通过本篇文章你可以快速了解循环的概念,以及循环在实际使用过程中的调优方案。 作者:任聪聪 日期:2025年4月11日 一、循环的种类 1.1 默认有以下类型 原始 for 循环 for(i = 0;i<10;i++){…...
OpenFeign 的实现原理详解
前言 OpenFeign 是一个声明式的 HTTP 客户端,它简化了服务间的 HTTP 调用。通过简单的注解和接口定义,开发者可以轻松调用远程服务,而无需手动编写复杂的 HTTP 请求代码。本文将深入探讨 OpenFeign 的实现原理,并结合源码分析其核…...
const关键字理解
const关键字主要的作用是告诉编译器这个东西是个常量,不可被修改。 或者是用来和指针玩一些奇奇怪怪的东西,这玩意面试八股文常青树。 const int* p://表示指针指向的内容不能更改,指针可以更改。 int* const p: //表示指针不能…...
操作系统 4.3-生磁盘的使用
磁盘的物理组成 盘面: 磁盘由多个盘面组成,每个盘面上都有数据存储的区域。 磁道: 每个盘面上都有若干个同心圆,这些同心圆称为磁道。磁道是数据存储的路径。 扇区: 磁道被进一步划分为若干个扇区,扇区…...
Uniapp Vue 实现当前日期到给定日期的倒计时组件开发
应用场景与需求分析 在移动端应用开发中,倒计时功能是常见的交互需求,例如限时促销活动、订单超时提醒、考试倒计时等场景。本文将基于 Uniapp 框架,实现一个从当前日期到给定日期的倒计时组件,支持显示 HH:mm:ss 格式的剩余时间…...
3dmax标准材质/vr/cr材质贴图转PBR材质贴图插件,支持多维子材质转换
3dmax标准材质/vr/cr材质贴图转PBR材质贴图插件,支持多维子材质转换 3dmax标准材质/vr/cr材质贴图转PBR材质贴图插件,支持多维子材质转换...
操作系统 3.3-多级页表和快表
分页的问题 这张幻灯片讨论了操作系统中内存管理的一个核心问题:页大小与页表大小之间的权衡。 页(Page)是内存管理中的一个基本概念,指的是将虚拟内存分割成固定大小的块,以便于管理和访问。页的大小直接影响内存空间…...
Java常用工具算法-7--秘钥托管云服务2(阿里云 KMS)
阿里云的KMS(Key Management Service)也是一种托管式密钥管理服务,帮助用户安全地创建、控制和使用密钥,保护敏感数据。通过使用KSM,您可以专注于构建和优化应用程序,而不必担心密钥管理的复杂性。 1、主要…...