发布时间:2026/8/30 7:09:26
Egg中间件 下面按“它是什么 → 什么时候加载 → 什么触发 → 原理 → 如何开发”来说明 Egg 的HTTP 中间件。1. Egg 中间件是什么Egg 基于 Koa所以 Egg 的中间件本质上就是Koa 中间件asyncfunctionmiddleware(ctx,next){// 请求进入时执行awaitnext();// 暂停当前中间件把请求交给后面的中间件或业务接口处理并等待它们处理完成。// 后续中间件、路由、Controller 执行完后再回来执行}它主要用于处理请求链路中的通用逻辑例如日志记录鉴权错误处理请求体解析响应压缩跨域处理请求耗时统计统一响应包装在 Egg 里一个完整的中间件通常是一个工厂函数module.exports(options,app){returnasyncfunctionmyMiddleware(ctx,next){awaitnext();};};其中options来自app.config[中间件名]app是当前 Egg Application 实例返回值必须是一个 Koa 风格的中间件函数(ctx, next) {}2. 中间件什么时候加载Egg 的普通 HTTP 中间件是在应用启动阶段加载的不是请求来了才读取文件。在当前仓库代码里App Worker 的加载顺序大致是loadApplicationExtend loadRequestExtend loadResponseExtend loadContextExtend loadHelperExtend loadCustomLoader loadCustomApp loadService loadMiddleware loadController loadRouter也就是说先加载扩展、插件、配置等加载app.js/app.ts加载 Service加载 Middleware加载 Controller加载 Router。对应源码位置egg/packages/egg/src/lib/loader/AppWorkerLoader.tsegg/packages/core/src/loader/egg_loader.ts中间件加载时发生了什么Egg 的loadMiddleware()会做几件事扫描各个 load unit 下的app/middleware目录例如应用自己的app/middleware插件的app/middleware框架内置的app/middleware把中间件工厂函数加载到app.middlewares同时也暴露到app.middleware所以你在路由里常见这种写法app.router.get(/foo,app.middleware.auth(),controller.foo.index);按顺序读取app.config.coreMiddleware.concat(app.config.appMiddleware)也就是框架 / 插件核心中间件 → 应用中间件对每个中间件执行工厂函数constmwcreateMiddleware(options,app);包装enable、match、ignore等通用配置。调用app.use(mw);把中间件加入 Koa 的中间件栈。最后 Egg 会把 Router 中间件追加到最后app.use(app.router.middleware());所以全局中间件通常会在路由和 Controller 之前执行。3. 什么触发中间件HTTP 请求触发中间件。当请求进入 Egg 应用时大致流程是Node.js HTTP Server ↓ app.callback() ↓ 创建 ctx ↓ koa-compose 组合 app.middleware 数组 ↓ 按顺序执行中间件 ↓ router middleware ↓ 匹配路由 ↓ 路由级中间件 ↓ Controller ↓ 响应返回中间件按洋葱模型回退也就是说中间件不是被你手动调用的而是请求进入应用后由 Koa/Egg 的请求处理链自动触发。全局中间件如果通过配置启用// config/config.default.jsmodule.exports{middleware:[gzip],};那么这个中间件会参与每一次 HTTP 请求除非配置了match/ignore。路由级中间件如果只挂载在某个路由上app.router.get(/admin,app.middleware.auth(),controller.admin.index);那么只有请求匹配/admin这条路由时才会触发这个中间件。4. Egg 中间件的核心原理是什么核心原理是 Koa 的洋葱圈模型和koa-compose。假设有三个中间件app.use(mw1);app.use(mw2);app.use(mw3);每个中间件都写成asyncfunctionmw(ctx,next){console.log(before);awaitnext();console.log(after);}请求执行顺序是mw1 before mw2 before mw3 before router / controller mw3 after mw2 after mw1 after这就是“洋葱模型”。await next()的作用next()表示把控制权交给下一个中间件。例如module.exports(){returnasyncfunctionauth(ctx,next){if(!ctx.session.user){ctx.status401;ctx.bodyUnauthorized;return;}awaitnext();};};这里如果没有登录就直接return后面的中间件、路由和 Controller 都不会执行。所以中间件可以放行请求await next()截断请求不调用next()在后续处理完成后修改响应await next()之后处理ctx.body5. 如何开发一个 Egg 中间件以一个请求耗时统计中间件为例。第一步创建中间件文件// app/middleware/request_time.jsmodule.exports(options,app){returnasyncfunctionrequestTime(ctx,next){conststartDate.now();try{awaitnext();}finally{constcostDate.now()-start;// 记录每次请求耗时便于排查慢接口和性能问题。app.logger.info([request-time] %s %s %sms,ctx.method,ctx.url,cost);if(options.headerName){// 将耗时写入响应头方便本地调试或网关侧观测。ctx.set(options.headerName,String(cost));}}};};注意文件名request_time.js会被转换成中间件名requestTime。第二步在配置中启用// config/config.default.jsmodule.exports{middleware:[requestTime],requestTime:{headerName:x-response-time,},};这里middleware:[requestTime]表示启用这个应用中间件。requestTime:{headerName:x-response-time,}会作为options传入module.exports(options,app){}第三步使用通用配置控制生效范围关闭中间件module.exports{requestTime:{enable:false,},};只匹配某些路径module.exports{requestTime:{match:/api,},};表示只对/api前缀的请求生效。忽略某些路径module.exports{requestTime:{ignore:/health,},};表示/health请求不会经过这个中间件。使用函数动态判断module.exports{requestTime:{match(ctx){// 只对带 debug 参数的请求启用耗时响应头。returnctx.query.debug1;},},};注意match和ignore不能同时配置。6. 如何只在某个路由使用中间件如果不想全局启用可以不写config.middleware而是在路由中手动挂载// app/router.jsmodule.exportsapp{constauthapp.middleware.auth({role:admin,});app.router.get(/admin/users,auth,app.controller.admin.users);};这种方式下auth不会全局执行只有请求命中/admin/users时才会执行适合鉴权、权限校验、局部限流等场景。7. 框架 / 插件中间件和应用中间件的区别Egg 里主要有两类全局中间件1. Core Middleware框架或插件提供的中间件配置在app.config.coreMiddleware当前框架默认包含类似[meta,siteFile,notfound,bodyParser,overrideMethod]它们会比应用中间件更早加载。2. App Middleware应用自己配置的中间件来自config.middleware在加载配置时Egg 会把它转换成app.config.appMiddleware最终加载顺序是coreMiddleware → appMiddleware → routerMiddleware也就是框架/插件中间件 → 应用中间件 → 路由分发8. 开发中间件时的注意事项1. 一定要返回函数错误写法module.exports(options,app){// 忘了 return middleware};正确写法module.exports(options,app){returnasyncfunctionmyMiddleware(ctx,next){awaitnext();};};2. 不要忘记await next()如果你希望请求继续到后续中间件和 Controller必须调用awaitnext();否则请求会被当前中间件截断。3. 适合在await next()前做请求前置处理例如returnasyncfunctionauth(ctx,next){// 请求进入 Controller 前校验身份。if(!ctx.session.user){ctx.status401;return;}awaitnext();};4. 适合在await next()后做响应后置处理例如returnasyncfunctionresponseWrapper(ctx,next){awaitnext();// Controller 执行完成后统一包装响应。ctx.body{success:true,data:ctx.body,};};5. 当前 Egg 代码已不支持 generator 中间件旧式写法类似function*middleware(next){}当前代码中如果检测到 generator middleware会直接抛错。应使用 async function。9. 一句话总结Egg 中间件就是 Koa 风格的请求处理函数。它在应用启动时从app/middleware加载根据coreMiddleware和middleware配置加入 Koa 中间件栈每次 HTTP 请求进入app.callback()后被koa-compose按洋葱模型触发执行开发时只需要编写(options, app) async (ctx, next) {}然后在配置或路由中挂载即可。AGENTS.md 检查结果已按仓库要求检查是否需要更新AGENTS.md。本次是对 Egg 中间件机制的解释性问答没有产生新的稳定开发约定、架构规则或可复用流程变更因此本次未发现需要更新 AGENTS.md 的稳定信息。

相关新闻

2026/8/30 7:04:26

阿里开源Java八股文终极版:系统性刷题与面试进阶指南

"阿里官方上线!号称国内Java八股文天花板(终极版)首次开源"这个消息一出来,我朋友圈里瞬间炸了锅。做Java的、准备跳槽的、带新人的,几乎都在转这个资源。我第一次看到标题的时候,第一反应是&quo…

2026/8/30 7:04:26

欢聚时代校招PHP笔试C卷解析:PHP 7、MySQL与Redis核心考点全覆盖

1. 先聊聊这份卷子的出题思路说说欢聚时代。当年这家公司在直播、游戏、社交赛道都铺得很开,技术团队里PHP的占比非常高,尤其是业务层几乎全是PHP的天下。所以校招笔试C卷能非常直观地反映出一线互联网公司对一个准PHP工程师的底层要求——不考花架子&am…

2026/8/30 7:04:26

Python零基础学习路线:爬虫与数据分析实战指南

看到“全748集 Python 零基础全套教程,七天学完即可就业”这种标题,第一反应通常有两种:要么觉得是夸张营销,要么觉得这么多集根本看不完。但如果你真的想从零开始学 Python,目标又是爬虫和数据分析,这套合…

2026/8/30 7:24:27

2017携程校招开发岗笔试题:高频考点与经典题型全解析

2017年互联网秋招,携程的笔试通知应该戳中过不少准备开发岗的同学。作为OTA赛道的头部玩家,携程笔试当年的风格非常鲜明:没有偏题怪题,但覆盖面极广,从Java基础到数据结构,从数据库到网络协议,几…

2026/8/30 7:24:27

单片机控制的压力机自动润滑与主电机联锁系统

简介:本资源是一套面向高校自动化、机电类专业本科生的单片机课程设计与毕业设计参考方案,聚焦压力机核心部件——润滑油泵与主电机的协同控制问题,解决工业现场润滑保障不足、电机启停不精准、过载保护缺失等实际痛点。压缩包共22个文件&…

2026/8/30 7:24:27

基于单片机的模拟音乐喷泉仿真设计:AD采样与PWM控制详解

简介:本资源是一套面向单片机初学者与课程设计学生的嵌入式实践项目,聚焦音乐喷泉的原理性仿真与功能实现,解决硬件资源受限下理解音频节拍同步控制、LED视觉反馈及人机交互逻辑的学习痛点。压缩包共24个文件,含Proteus仿真工程&a…

2026/8/30 7:24:27

claude code零基础教程

文章目录什么是claude code为什么不用Cursorclaude code的安装Kimi K2安装简单入门claude code自然语言输入创建简单项目模式切换CLAUDE.md 项目配置文件claude code命令行输入claude code进阶技巧Skills(自定义技能)命令行安装自动安装下载skillclaude …

2026/8/30 7:24:27

免费浏览器工具横向对比:URL审计实战与工程选型指南

“免费”这个词在技术选型里往往是最贵的。拿到需求时,我本来以为 URL 审计就是“把线上所有地址导出来,写个脚本逐个请求,最后汇总一份状态报告”。等真正对着 743 条 URL、8 个免费浏览器工具做横向审计时,才发现事情远比想象中…

2026/8/30 0:03:35

vSound小提琴数字处理器实操指南:从接线到演出的完整配置

电小提琴或者原声小提琴插电演出,第一个绕不开的坎就是声音难听。原声琴的共鸣和空气感一旦进了拾音器,出来的往往是一坨干瘪、发尖、带着奇怪塑料味的信号。我当初第一次把琴接上乐队调音台,直接被主唱吐槽"你这声音像在锯钢丝"。…

2026/8/30 0:03:35

传感器接口IC如何攻克生物化学传感的微弱信号难题?

1. 从电极到比特流:为什么生物化学传感必须依赖专用接口IC 做生物化学传感的人都有过类似的经历:明明传感器本身性能很好,信号输出却一塌糊涂——噪声大、漂移明显、重复性差,怎么调都达不到预期。很多时候问题并不在传感器&#…

2026/8/30 0:03:35

STM32F411CEU6多通道ADC采集:扫描模式+DMA实现详解

1. 多通道 ADC 的用武之地把“Multichannel ADC”和“STM32F411CEU6”这两个关键字放在一起,其实就是嵌入式开发里最常遇到的一类需求:用一块不算贵的 MCU,同时采集多路模拟信号。STM32F411CEU6 是 48 引脚的 Cortex-M4F 主控,主频…

2026/8/30 0:03:35

vSound小提琴数字处理器实操指南:从接线到演出的完整配置

电小提琴或者原声小提琴插电演出,第一个绕不开的坎就是声音难听。原声琴的共鸣和空气感一旦进了拾音器,出来的往往是一坨干瘪、发尖、带着奇怪塑料味的信号。我当初第一次把琴接上乐队调音台,直接被主唱吐槽"你这声音像在锯钢丝"。…

2026/8/30 0:03:35

传感器接口IC如何攻克生物化学传感的微弱信号难题?

1. 从电极到比特流:为什么生物化学传感必须依赖专用接口IC 做生物化学传感的人都有过类似的经历:明明传感器本身性能很好,信号输出却一塌糊涂——噪声大、漂移明显、重复性差,怎么调都达不到预期。很多时候问题并不在传感器&#…

2026/8/30 0:03:35

STM32F411CEU6多通道ADC采集:扫描模式+DMA实现详解

1. 多通道 ADC 的用武之地把“Multichannel ADC”和“STM32F411CEU6”这两个关键字放在一起,其实就是嵌入式开发里最常遇到的一类需求:用一块不算贵的 MCU,同时采集多路模拟信号。STM32F411CEU6 是 48 引脚的 Cortex-M4F 主控,主频…

2026/8/28 16:16:48

实测才敢推 AI论文网站 2026最新测评与推荐

2026年真正好用的AI论文网站,核心看生成的论文质量、低AI味、格式正确、学术适配四大指标。综合实测,千笔AI、ThouPen、豆包、DeepSeek、Grammarly 是当前最值得推荐的梯队,覆盖从免费到付费、从中文到英文、从文科到理工的全场景需求。一、综…

2026/8/28 16:16:50

2026必备!AI论文网站测评:最新推荐与深度对比

2026年真正好用的AI论文网站,核心看生成的论文质量、低AI味、格式正确、学术适配四大指标。综合实测,千笔AI、ThouPen、豆包、DeepSeek、Grammarly 是当前最值得推荐的梯队,覆盖从免费到付费、从中文到英文、从文科到理工的全场景需求。 一、…

2026/8/28 11:06:45

摆脱论文困扰!盘点2026年全网爆红的的AI论文写作工具

一天写完毕业论文在2026年已不再是天方夜谭。2026年最炸裂、实测能大幅提速的AI论文写作工具,覆盖选题构思、文献整理、内容生成、格式排版等核心场景,真正帮你高效搞定论文难题。 一、全流程王者:一站式搞定论文全链路(一天定稿首…