Midway v1 全局中间件实战指南:基于 Egg 的中间件编写、配置与 Koa 生态复用
后端微服务云原生【免费下载链接】midway A Node.js Serverless Framework for front-end/full-stack developers. Build the application for next decade. Works on AWS, Alibaba Cloud, Tencent Cloud and traditional VM/Container. Super easy integrate with React and Vue. 项目地址https://gitcode.com/gh_mirrors/mi/midway点击查看免费下载Midway v1 中全局中间件由 Egg 框架提供采用 Egg 的函数式写法与面向特定路由的路由中间件在使用方式和生命周期上存在明确差异。本文以src/app/middleware目录与config.default.ts配置为线索完整讲解全局中间件的编写、注册、Koa 中间件直接复用并结合仓库源码剖析其加载原理与注入限制帮助你写出可运行、可维护的全局拦截逻辑。全局中间件与路由中间件的区别在开始编码之前需要先明确 Midway v1 中两类中间件的定位差异这决定了代码写在哪、怎么注册、能否使用依赖注入维度全局中间件路由中间件提供方Egg 框架沿用 Egg 约定Midway 装饰器体系写法函数式module.exports () (ctx, next) {}类 WebMiddleware接口 resolve()作用范围所有路由单个控制器或单个路由方法注册方式config.default.ts中的middleware数组controller/get/post等装饰器的middleware参数是否支持注入不能使用注入形式类中间件可注入但同样受单例限制官方文档 middleware.md 开篇即强调v1 的全局中间件为 Egg 提供、使用 Egg 写法和路由中间件有所区别并且不能使用注入的形式使用。理解这一点是后续所有实践的前提。目录结构上全局中间件必须放在约定的 web 层目录下。根据 quickstart.md 中的目录树src/app/middleware是“可选”的 web 层中间件目录src ├── app ---- web 层目录 │ ├── controller ---- web 层 controller 目录 │ ├── middleware (可选) ---- web 层中间件目录 │ │ └── trace.ts │ ├── public (可选) ---- web 层静态文件目录 │ └── view (可选) ├── config │ ├── config.default.ts │ ├── config.local.ts │ ├── config.prod.ts │ └── plugin.ts └── service这个目录约定来自 Egg 的约定式目录结构Midway v1 将其原样保留唯一的差异是文件后缀使用*.ts。编写第一个全局中间件以官方文档中的 report 中间件为例在src/app/middleware/report.ts中编写// src/app/middleware/report.ts module.exports () { return async function (ctx, next) { const startTime Date.now(); await next(); // 上报请求时间 reportTime(Date.now() - startTime); }; };这段代码包含三个关键结构module.exports () {...}Egg以及 Koa约定中间件是一个工厂函数调用后返回真正的中间件函数。这样做的目的是让中间件可以在工厂函数中接收配置参数实现同一份逻辑、不同参数的复用。async function (ctx, next)返回的中间件接收 Koa 上下文ctx和next函数。ctx上挂载了request、response、params、query等请求信息。await next()调用next()表示把控制权交给下一个中间件最终到达控制器next()返回后代码继续执行控制器之后的逻辑。这就是 Koa/Egg 经典的洋葱圈模型——中间件可以在控制器执行前后各执行一段逻辑startTime与reportTime的差值即控制器执行耗时。文档明确指出框架的中间件和 Koa 的中间件写法是一样的所以任何 Koa 的中间件都可以直接被框架使用。 这意味着你已有的 Koa 中间件知识可以无缝迁移到 Midway v1 中。在配置文件中注册全局中间件中间件写好后需要在config.default.ts中声明启用// src/config/config.default.ts module.exports { middleware: [report], };这里配置的名字和文件名一致——middleware数组中的字符串report会对应加载src/app/middleware/report.ts或编译后的dist/app/middleware/report.js。需要注意的细节名字即文件名Egg 通过约定式扫描加载中间件数组中的字符串必须与src/app/middleware下的文件名一一对应拼写不一致会导致启动时找不到中间件。顺序即执行顺序middleware数组中的顺序就是中间件的执行顺序。如果配置多个全局中间件如middleware: [report, session]则report先执行随后是session。环境配置与 Egg 的配置体系一致可以针对不同环境拆分配置例如config.local.ts中启用调试类中间件、config.prod.ts中只保留生产必需中间件。Midway v1 支持的配置文件名包括config.default.ts、config.local.ts、config.prod.ts、config.unittest.ts等参见 quickstart.md 中和 Egg 体系相同的部分。源码中的加载印证从仓库源码可以印证这种注册方式的底层机制。packages/web/src/framework/web.ts 中Midway 拦截了app.use方法将其重定向到自己的中间件管理器// 这里拦截 app.use 方法让他可以加到 midway 的 middlewareManager 中 (this.app as any).originUse this.app.use; this.app.use this.app.useMiddleware as any;而 Egg 框架自身的中间件加载逻辑config.middleware中的字符串数组由 Egg 的 Loader 负责Midway 通过 packages/web/src/configuration.ts 在onReady阶段对app.middleware做了快照处理保证 Egg 添加的中间件数组能够被正确接管。也就是说config.default.ts中的middleware数组最终会进入 Egg 的中间件执行链与 Koa 中间件共用同一套洋葱模型。直接复用 Koa 生态中间件由于写法与 Koa 完全一致社区中大量 Koa 中间件可以直接接入。官方文档以koa-compress响应压缩为例。koa-compress暴露的接口为(options) middleware这与框架对中间件的要求一致所以只需一行导出即可// src/app/middleware/compress.ts // koa-compress 暴露的接口((options) middleware)和框架对中间件要求一致 module.exports require(koa-compress);然后在配置中注册// src/config/config.default.js module.exports { middleware: [compress], };这里的原理在于Egg 加载middleware数组中名为compress的中间件时会读取src/app/middleware/compress.ts的导出值并调用它而require(koa-compress)本身就是一个返回中间件函数的工厂函数因此可以直接被 Egg 消费。如果 Koa 中间件需要传参例如压缩阈值、白名单等也可以利用工厂函数模式包一层// src/app/middleware/compress.ts const compress require(koa-compress); module.exports () { return compress({ threshold: 2048, // 其他 koa-compress 选项 }); };只要最终返回(ctx, next) Promisevoid形式的函数任何 Koa 中间件都能以同样的方式接入。全局中间件的执行顺序中间件的执行顺序直接影响业务行为例如日志中间件应尽量靠前才能记录完整链路。在 Midway v1 的 Egg 体系中顺序主要由config.middleware数组决定同时还需注意与 Egg 内置中间件的关系。仓库中 packages/web/src/framework/web.ts 的loadMidwayController展示了 Midway 路由中间件与 Egg 中间件的衔接方式async loadMidwayController() { // move egg router to last this.app.getMiddleware().findAndInsertLast(eggRouterMiddleware); await this.generator.loadMidwayController(newRouter { const dispatchFn newRouter.middleware(); dispatchFn._name midwayController(${newRouter?.opts?.prefix || /}); this.app.useMiddleware(dispatchFn); }); // restore use method this.app.use (this.app as any).originUse; }从源码结构可以推断出以下事实Egg 的全局中间件config.middleware配置的会在路由分发之前执行即先经过全局中间件链再进入具体的路由处理。eggRouterMiddleware被调整到末尾确保路由匹配发生在所有全局中间件之后。Midway 控制器的路由分发函数作为一个整体中间件追加到列表尾部因此全局中间件 → 路由 → 控制器的链路是确定的。这种机制也解释了为什么日志、鉴权、跨域这类拦截逻辑适合写成全局中间件它们需要在路由匹配和控制器执行之前统一处理且对所有请求生效。与路由中间件的对比装饰器用法前文已说明 v1 中全局中间件使用 Egg 写法而路由中间件走 Midway 的装饰器体系。两者的选择原则是全局逻辑cookie、session、统一日志、跨域→ 使用本文介绍的 Egg 全局中间件局部逻辑某个接口的前置校验、数据处理→ 使用路由中间件。根据 controller.md 的说明v1 的路由中间件可以写在任意目录不限定app/middleware使用provide()与WebMiddleware接口定义并在装饰器上引用import { Middleware, WebMiddleware, provide, config } from midway; provide() export class ApiMiddleware implements WebMiddleware { config(hello) helloConfig; resolve(): Middleware { return async (ctx, next) { ctx.api 222 this.helloConfig.b; await next(); }; } }provide() controller(/, { middleware: [homeMiddleware] }) export class My { inject() ctx; get(/, { middleware: [apiMiddleware] }) async index() { this.ctx.body this.ctx.home this.ctx.api; } }middleware参数是数组可以传多个字符串从 IoC 容器中获取WebMiddleware实例的resolve()结果也可以直接传 Koa 中间件函数。这与全局中间件在写法、注册位置、注入能力上形成了完整互补。中间件注入限制与请求作用域这是全局中间件以及 v1 路由中间件最容易踩坑的地方官方文档与 controller.md 的中间件注入的特殊性一节都专门强调中间件在应用请求前就被加载绑定到路由上无法和某个请求上下文关联中间件类固定为单例Singleton所有注入的内容都为单例包括但不限于config、logger、plugin等因此不能在中间件中通过inject()注入依赖了ctx的服务如请求作用域实例否则拿不到上下文。正确的做法是在resolve()返回的中间件函数中通过ctx.requestContext.getAsync(xxx)从请求作用域容器中获取实例从而与当前请求绑定provide() export class ApiMiddleware implements WebMiddleware { inject() myService; // 由于中间件实例属于单例这个实例即使注入也无法获取到 ctx resolve(): Middleware { return async (ctx, next) { // 必须通过从请求作用域中获取对象的方式来绑定上下文 ctx.service await ctx.requestContext.getAsync(myService); await next(); }; } }对于 Egg 写法的全局中间件而言ctx直接作为参数传入天然与请求绑定因此可以直接通过ctx.requestContext.getAsync()获取请求级服务而不存在类中间件那种单例注入的困扰——这也是 v1 全局中间件保持函数式写法的原因之一。常见应用场景小结结合以上内容全局中间件在 Midway v1 项目中适合承担以下职责请求耗时与链路日志如本文的 report 示例在await next()前后记录时间戳输出慢请求告警统一响应处理 / 请求体预处理在进入路由前对请求做统一加工在返回前对响应做统一包装复用 Koa 生态能力压缩koa-compress、静态资源koa-static、跨域koa-cors等一行导出即可接入全局鉴权与安全头基于ctx校验 token、注入安全响应头所有路由统一生效。编写时始终记住三条规则文件放在src/app/middleware下、导出工厂函数返回(ctx, next)中间件、在config.default.ts的middleware数组中用与文件名一致的字符串注册。遇到需要注入请求作用域服务的场景通过ctx.requestContext.getAsync()获取避免单例注入陷阱。赞分享后端微服务云原生【免费下载链接】midway A Node.js Serverless Framework for front-end/full-stack developers. Build the application for next decade. Works on AWS, Alibaba Cloud, Tencent Cloud and traditional VM/Container. Super easy integrate with React and Vue. 项目地址https://gitcode.com/gh_mirrors/mi/midway点击查看免费下载相关推荐Midway Hooks 跨域配置实战基于 koa/cors 中间件的 CORS 实现指南Midway Hooks 跨域配置实战基于 koa/cors 中间件的 CORS 实现指南 导读 在前后端分离的现代 Web 开发中浏览器同源策略导致的跨后端微服务云原生Midway Hooks 中间件完全指南从函数式语法到 Koa 生态复用Midway Hooks 中间件完全指南从函数式语法到 Koa 生态复用 本文围绕 Midway Hooks 的 Web 中间件体系展开讲解如何用「函数 后端微服务云原生Midway Hooks 函数式 Web 中间件实战从日志记录到 Koa 生态复用Midway Hooks 函数式 Web 中间件实战从日志记录到 Koa 生态复用 Midway Hooks 是 Midway 框架面向前端/全栈开发者的函数后端微服务云原生上一篇使用 Go 语言获取终端尺寸olekukonko/ts 库完整实战指南下一篇如何用 XiaoMusic 免费让小爱音箱播放任何音乐新手上手指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

Flask-Admin 多语言界面实战:基于 Flask-Babel 的国际化(i18n)集成指南

Flask-Admin 多语言界面实战:基于 Flask-Babel 的国际化(i18n)集成指南

后端 【免费下载链接】flask-admin Simple and extensible administrative interface framework for Flask 项目地址: https://gitcode.com/gh_mirrors/fl/flask-admin 点击查看 免费下载 本指南以 examples/babel 示例为骨架,完整讲解如何在 Flask-Adm…

2026/10/10 14:11:53 阅读更多 →
OKX AI 口碑查询指南:用 `agent feedback-list` 查看 Agent 评价与星级信誉(identity-reputation 流程)

OKX AI 口碑查询指南:用 `agent feedback-list` 查看 Agent 评价与星级信誉(identity-reputation 流程)

【免费下载链接】internet-court-skill The trust layer for agent-to-agent commerce — natural-language mandates, ERC-7710 delegated permissions, x402 payments, escrow, and dispute resolution as one open, catch-all Agent Skill / Claude Code plugin. 项目地址&a…

2026/10/10 14:11:53 阅读更多 →
爬虫笔记(10/2)——用 TaoToken 统一 Key 跑通 Scrapy 爬虫框架

爬虫笔记(10/2)——用 TaoToken 统一 Key 跑通 Scrapy 爬虫框架

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 14:11:53 阅读更多 →

最新新闻

WinSxS文件夹清理指南:用DISM安全释放系统盘空间

WinSxS文件夹清理指南:用DISM安全释放系统盘空间

1. 先搞清楚 WinSxS 到底是个什么东西很多人第一次打开C:\Windows\WinSxS这个文件夹,看到属性里显示十几个 G,甚至二十几个 G,第一反应就是:这玩意儿是不是垃圾?能不能直接删掉腾空间?我当年也是这么想的&a…

2026/10/10 14:54:00 阅读更多 →
Kettle(PDI)安装配置完全指南:版本匹配与避坑实践

Kettle(PDI)安装配置完全指南:版本匹配与避坑实践

简介:面向数据集成初学者、数据分析师及需要快速搭建ETL环境的开发人员,这是一份以Pentaho Data Integration(PDI)下载安装与基础配置为核心的PDF速查教程。Kettle作为开源ETL工具,常用于多平台数据抽取、转换与加载&a…

2026/10/10 14:54:00 阅读更多 →
Clude安装流程全解析:四步跑通本地AI命令行工作台

Clude安装流程全解析:四步跑通本地AI命令行工作台

前阵子有个朋友跑来问我,说手里的AI工具一直停留在网页聊天框的阶段,想要找个能接进本地工作流的方式,问我有没有推荐的方案。我直接丢给他一款叫Clude的开源个人AI工作台——它跟那种只能在浏览器里对话的产品不太一样,装好之后你…

2026/10/10 14:54:00 阅读更多 →
Kettle(PDI)安装与启动实战:从下载到跑通第一个转换

Kettle(PDI)安装与启动实战:从下载到跑通第一个转换

简介:Kettle(Pentaho Data Integration,简称 PDI)是一款开源 ETL 工具,面向需要进行数据抽取、转换与加载的开发者,重点解决该工具在 Windows、Linux、macOS 等平台下的获取、安装与基础配置难题。资料以单…

2026/10/10 14:54:00 阅读更多 →
AIRI 浏览器本地语音识别(Browser Local ASR/STT):当前状态、WIP 占位实现与可用替代方案

AIRI 浏览器本地语音识别(Browser Local ASR/STT):当前状态、WIP 占位实现与可用替代方案

AI 应用人工智能大模型数字人AI Agent语音前端后端 【免费下载链接】airi 💖🧸 Self hosted, you-owned Grok Companion, a container of souls of waifu, cyber livings to bring them into our worlds, wishing to achieve Neuro-samas altitude. Capa…

2026/10/10 14:54:00 阅读更多 →
统一登录与单点登录实战:网关与认证中心的搭建全解

统一登录与单点登录实战:网关与认证中心的搭建全解

这段时间我一直在折腾一件事:把我们内部几个各自为战的业务系统,统一到一个登录入口底下。项目代号倒是很形象,sward 负责守门,soular 负责认人。说白了,sward 是一个网关层,soular 是一个身份认证中心&…

2026/10/10 14:52:58 阅读更多 →

日新闻

卫星轨道分类全解析:从LEO到GEO的选型逻辑与工程实践

卫星轨道分类全解析:从LEO到GEO的选型逻辑与工程实践

1. 从“卫星轨道分类”这个标题说起:为什么值得花时间搞懂第一次接触“卫星轨道分类”这个概念,很多人会觉得它离自己很远——不就是天上的星星怎么转吗?但如果你正在做航天任务规划、遥感数据接收、星座设计,甚至只是准备一场航天…

2026/10/10 0:00:39 阅读更多 →
Spring AOP 核心原理与实战:从概念到日志切面落地

Spring AOP 核心原理与实战:从概念到日志切面落地

1. 从一个真实痛点说起:为什么你的代码里到处都是重复逻辑刚入行那会儿,我写过一个用户管理模块,注册、登录、改密码、注销四个接口。每个接口里都塞了几乎一样的日志打印、参数校验、事务开启和提交。当时觉得没什么,能跑就行。直…

2026/10/10 0:00:40 阅读更多 →
Python招聘数据采集与分析可视化:从采集清洗到薪资技能城市可视化全链路

Python招聘数据采集与分析可视化:从采集清洗到薪资技能城市可视化全链路

简介:这是一套面向计算机相关专业学生与项目实战学习者的Python数据采集与分析可视化完整项目,以Boss直聘岗位数据为对象,适合用作毕业设计、课程设计或期末大作业。资源包共38个文件,约246KB,以13个py源码文件为核心&…

2026/10/10 0:00:40 阅读更多 →

周新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 11:14:25 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 1:36:08 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 11:14:58 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 5:23:50 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 21:32:20 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 10:38:42 阅读更多 →