EMQX 插件 API 网关修复:HTTP 请求头与查询参数透传机制深度解析
后端物联网消息队列通信【免费下载链接】emqxThe most scalable and reliable MQTT broker for AI, IoT, IIoT and connected vehicles项目地址https://gitcode.com/gh_mirrors/em/emqx点击查看免费下载导读本文围绕 EMQX 开源仓库中的一条缺陷修复记录fix-16843.en.md展开插件 API 处理回调on_handle_api_call此前收到的 HTTP 请求头与查询字符串参数为空导致插件无法感知上游请求携带的认证信息、追踪标识与查询条件。文章以该修复为切入点结合emqx_plugins应用源码与测试用例完整讲解 EMQX 插件 API 网关/plugin_api/:plugin/[...]的路由注册、请求信息ReqInfo组装、敏感头脱敏、响应头白名单、超时配置与错误映射等机制帮助读者理解修复原理并掌握插件 API 的调用与调试方法。修复背景插件 API 网关中的“空 headers”问题EMQX 的插件Plugin应用通过emqx_plugins框架与主进程解耦。为了让插件能够暴露自定义 HTTP APIemqx_plugins提供了一条以/plugin_api/:plugin/[...]为前缀的网关路由把请求转发给已激活插件的on_handle_api_call/4回调。修复前的问题正如变更记录所述HTTP 请求头headers和查询字符串参数query string没有被透传给插件 API 处理回调导致插件收到的是空的 headers 和缺失的 query 参数。对于依赖Authorization、X-Request-Id、?limit、?page等信息的插件而言这意味着请求上下文信息在网关层丢失插件既无法做细粒度鉴权也无法实现分页、过滤等常见功能。修复涉及的核心模块为 emqx_plugins_api_endpoint.erl该模块实现了minirest_api行为作为 HTTP 网关把请求转换成插件回调所需的ReqInfo数据结构。网关路由何时注册如何匹配emqx_plugins_api_endpoint的paths/0返回路由列表且路由注册受到功能开关feature gate约束paths() - case emqx_machine_features:is_umbrella_application_enabled(emqx_plugins) of false - []; true - [/plugin_api/:plugin/[...]] end.从源码结构看当EMQX_FEATURES预设中未启用plugins时emqx_plugins应用不会启动网关路由也就不会注册这是保证插件框架作为门控特性gated feature正确工作的关键。模块内的paths_gated_by_feature_test_()测试用例也验证了这一行为启用plugins特性时paths()返回非空列表仅启用dashboard时返回空列表。路由匹配后parse_request_path/1会兼容两种路径形态/api/v5/plugin_api/plugin/path...经 minirest 的 base_path 提供服务即实际对外形态/plugin_api/plugin/path...测试或回退路径中的直连形态。路径剩余部分会逐段做百分号解码uri_string:percent_decode/1保证%2F等转义字符能正确还原为路径片段相关行为由测试t_plugin_api_path_remainder_is_percent_decoded覆盖。修复核心ReqInfo 中 headers 与 query_string 的透传网关入口函数gateway/3是本次修复的核心位置。它从 Cowboy 请求中提取真实数据组装成插件回调可用的请求信息Headers case maps:get(headers, Params, undefined) of undefined - cowboy_req:headers(Request); H - H end, QueryString case maps:get(query_string, Params, undefined) of undefined - maps:from_list(cowboy_req:parse_qs(Request)); Qs - Qs end, ReqInfo #{ method Method, query_string QueryString, headers sanitize_headers(Headers), body maps:get(body, Params, #{}) },修复的关键在于headers 透传当框架未显式提供headers时直接调用cowboy_req:headers/1获取当前 HTTP 请求的全部请求头而不是回退为空 mapquery string 透传通过cowboy_req:parse_qs/1解析查询字符串并转为 key-value map键值均为二进制再放进ReqInfo.query_stringbody 透传ReqInfo.body默认取Params中的body缺省为空 map。同时Context中会携带认证元数据与命名空间Context #{ auth_meta AuthMeta, namespace request_namespace(Params) },request_namespace/1优先取auth_meta.namespace否则回退到全局命名空间?global_ns供插件在多租户/多命名空间场景下识别请求归属。安全边界请求头脱敏与响应头白名单透传不等于全盘转发网关在两个方向上都做了安全约束。请求方向——敏感请求头脱敏。sanitize_headers/1会移除authorization与cookie两个请求头后再传给插件回调避免插件侧误用或泄露网关自身的认证凭据sanitize_headers(Headers) - maps:without([authorization, cookie], Headers).注意 Cowboy 会对请求头名做小写归一化因此脱敏匹配使用小写二进制 key。响应方向——响应头白名单allow-list。插件回调返回的自定义响应头并非全部放行而是经过 emqx_plugins.erl 中filter_plugin_api_headers/1的过滤只有命中?PLUGIN_API_ALLOWED_HEADERS白名单如content-type、etag、cache-control、x-request-id、x-ratelimit-limit等内容元数据、缓存、实体校验、关联 ID、限流相关头部或以x-plugin-为前缀的自定义头部才会被透传回客户端。选用白名单而非黑名单的设计意图在源码注释中写得很明确黑名单永远不完整每出现一个新的浏览器安全机制就要追加一条set-cookie、location、access-control-allow-origin等存在安全风险的响应头一律被拦截。回调调用链与超时配置请求信息组装完成后网关把控制权交给插件框架call_plugin_api(Plugin, Method, PathRemainder, ReqInfo, Context) - Timeout emqx:get_config( [plugins, api_endpoint, timeout], emqx:get_config([plugins, api_gateway, timeout], ?DEFAULT_TIMEOUT) ), Request #{method Method, path PathRemainder, request ReqInfo, context Context}, emqx_plugins:handle_api_call(Plugin, Request, Timeout).完整调用链为HTTP 请求 → emqx_plugins_api_endpoint:gateway/3 组装 ReqInfo/Context → emqx_plugins:handle_api_call/3 解析插件名、执行超时控制 → emqx_plugins_apps:on_handle_api_call/4 定位插件应用模块 → 插件模块:on_handle_api_call(Method, Path, Request, Context)其中emqx_plugins:handle_api_call/3负责两件事插件名解析resolve_active_name_vsn/1先在活跃插件列表中精确匹配再按plugin_name(NameVsn) : Plugin做模糊匹配找不到时返回{error, not_found}并映射为 HTTP 404超时与异常兜底回调通过emqx_utils:nolink_apply/2在受控进程中执行超时默认 5 秒返回 HTTP 503PLUGIN_API_TIMEOUT回调崩溃返回 HTTP 500INTERNAL_ERROR同时记录结构化日志plugin_api_callback_timeout/plugin_api_callback_crash日志中会提示可通过调大plugins.api_endpoint.timeout来延长合法长耗时回调的预算。超时配置定义在 emqx_plugins_schema.erl 的api_endpoint字段下plugins { api_endpoint { timeout 5s } }api_endpoint.timeout类型为timeout_duration_ms默认5s代码中读取时先查新配置键[plugins, api_endpoint, timeout]未设置时回退到旧键[plugins, api_gateway, timeout]最终回退到模块常量?DEFAULT_TIMEOUT5000ms保证升级平滑。测试验证修复如何被锁定emqx_plugins_api_endpoint_SUITE.erl 用 meck 模拟emqx_plugins:handle_api_call/3从真实 HTTP 层面对网关行为做了系统性验证其中与本修复直接相关的用例包括测试用例验证点t_plugin_api_headers_passthrough请求头应来自 Cowboy 请求而非空 mapheader_count 0并断言content-type存在t_plugin_api_sensitive_headers_redactedauthorization、cookie被移除普通自定义头x-test保留t_plugin_api_query_string_passthrough?foobarused_gte1中的参数完整透传且值为二进制字符串t_plugin_api_path_remainder_is_percent_decoded路径段百分号解码user%2Fname→user/namet_plugin_api_forbidden_headers_filtered响应头白名单过滤set-cookie、location、access-control-allow-origin、非x-plugin-前缀的x-custom被剔除x-plugin-custom保留t_plugin_api_ok/not_found/unauthorized/callback_crash200/404/401/500 状态码与响应体映射此外emqx_plugins_tests.erl等测试覆盖了emqx_plugins框架层的回调分发共同保证“修复不再回归”。实际排查插件 API 问题时可参考测试中的请求方式用curl携带自定义头与查询参数直接访问/api/v5/plugin_api/plugin/path观察插件回调收到的ReqInfo是否正确。修复价值与使用建议本次修复补齐了插件 API 网关的请求上下文透传能力使插件可以读取业务自定义请求头如追踪 ID、租户标识参与鉴权与日志关联读取查询参数实现分页、过滤、排序等 RESTful 语义通过Context.auth_meta.namespace感知请求命名空间适配多租户部署。实际开发插件 API 时建议遵循以下约束均可从仓库源码与测试中得到印证不要把网关自身的authorization、cookie请求头当作插件私有输入——它们已被脱敏插件回调如需返回自定义响应头必须使用x-plugin-前缀否则会被响应头白名单拦截长耗时回调应评估plugins.api_endpoint.timeout默认 5s必要时显式调大避免被当作超时返回 503回调返回值遵循{ok, Status, Headers, Body}/{error, Status, Headers, Body}/{error, Code, Msg}/{error, not_found}等约定形态非法返回值统一映射为 500INTERNAL_ERROR。至此从一条缺陷修复记录出发EMQX 插件 API 网关的请求透传、安全边界、超时控制与错误映射机制已完整呈现读者既可以在 emqx_plugins_api_endpoint.erl 中对照实现也可以借助 emqx_plugins_api_endpoint_SUITE.erl 中的用例复现验证。赞分享后端物联网消息队列通信【免费下载链接】emqxThe most scalable and reliable MQTT broker for AI, IoT, IIoT and connected vehicles项目地址https://gitcode.com/gh_mirrors/em/emqx点击查看免费下载相关推荐EMQX 插件自定义 HTTP API深入解析 /api/v5/plugin_api/{plugin}/... 网关机制EMQX 插件自定义 HTTP API深入解析 /api/v5/plugin_api/{plugin}/... 网关机制 本文基于仓库变更记录 changes后端物联网消息队列通信HTTP Prompt请求组合技巧多参数传递与复杂查询构建HTTP Prompt请求组合技巧多参数传递与复杂查询构建 在API测试过程中我们经常需要构建包含多个参数的复杂HTTP请求。传统命令行工具需要记忆繁琐的语开发工具接口测试如何永久保存你的数字记忆微信聊天记录本地化终极指南如何永久保存你的数字记忆微信聊天记录本地化终极指南 你是否曾因手机丢失而懊悔那些无法找回的珍贵对话是否担心重要的商务沟通记录会随时间消失在数字时代微信聊创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

芯片IP选型避坑指南:架构适配、工艺兼容与验证完备性实战

芯片IP选型避坑指南:架构适配、工艺兼容与验证完备性实战

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

2026/9/24 8:25:41 阅读更多 →
LTspice第三方SPICE模型集成全流程指南

LTspice第三方SPICE模型集成全流程指南

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

2026/9/24 8:25:41 阅读更多 →
SWIR051AU短波红外相机:从InGaAs原理到工业检测实战

SWIR051AU短波红外相机:从InGaAs原理到工业检测实战

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

2026/9/24 8:25:41 阅读更多 →

最新新闻

寒地专网云原生架构:边缘自治与智能运维实战

寒地专网云原生架构:边缘自治与智能运维实战

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

2026/9/24 9:01:12 阅读更多 →
华为EC6110T刷机指南:CA高安版与普通版区别及救砖方案

华为EC6110T刷机指南:CA高安版与普通版区别及救砖方案

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

2026/9/24 9:01:12 阅读更多 →
stm32学习日志-ADC单通道模拟电压信号转离散数字量

stm32学习日志-ADC单通道模拟电压信号转离散数字量

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

2026/9/24 9:01:12 阅读更多 →
校园网综合布线系统设计方案:从图纸到机柜的工程落地指南

校园网综合布线系统设计方案:从图纸到机柜的工程落地指南

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

2026/9/24 9:01:12 阅读更多 →
RK3588开发板USB OTG烧录全攻略:原理、实操与避坑指南

RK3588开发板USB OTG烧录全攻略:原理、实操与避坑指南

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

2026/9/24 9:01:12 阅读更多 →
人力资源服务双体系认证:ISO 27001与ISO 20000-1融合实践

人力资源服务双体系认证:ISO 27001与ISO 20000-1融合实践

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

2026/9/24 9:00:10 阅读更多 →

日新闻

基于YOLOv8的渔船作业监控系统:从环境搭建到边缘部署全流程

基于YOLOv8的渔船作业监控系统:从环境搭建到边缘部署全流程

简介:这是一套面向计算机、人工智能、自动化等专业学生与教师的毕业设计级项目资源,围绕YOLOv8实现渔船作业监控系统,可用于毕设、课程设计、大作业或项目立项演示。压缩包共97个文件,约24.21MB,以70个Python源码文件为…

2026/9/24 0:00:19 阅读更多 →
单细胞注释实战:基于Scanpy的标记基因与参考映射流程解析

单细胞注释实战:基于Scanpy的标记基因与参考映射流程解析

简介:一份基于单细胞RNA测序数据的细胞类型注释算法研究Python毕业设计源码,针对计算机相关专业正在做毕设或需要项目实战的学习者,可用于课程设计与期末大作业。项目代码完整、经导师指导评审通过,可直接运行,覆盖数据…

2026/9/24 0:00:19 阅读更多 →
C#源生成器实战:用增量生成器替代反射,告别AOT崩溃

C#源生成器实战:用增量生成器替代反射,告别AOT崩溃

第一次在项目里被反射卡住,是在一个老旧的WinForms模块里:几十个类依赖PropertyChanged通知,运行时反射读属性、发通知,每次启动慢半拍不说,一上.NET Native/AOT裁剪模式几乎全面崩盘。后来我把这段逻辑全部改成C#源生…

2026/9/24 0:00:19 阅读更多 →

周新闻

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

直接铺开项目本身吧。这几个月我一直在折腾一件事:用Flutter给OpenHarmony做一款游戏集合类的App,说白了就是把若干小游戏塞进一个壳里,用统一入口分发。这个方向本身不算新鲜,真正让我花了不少心思的,是首页那堆游戏卡…

2026/9/23 4:55:02 阅读更多 →
Word表格编号全攻略:从列表编号到题注交叉引用

Word表格编号全攻略:从列表编号到题注交叉引用

写Word文档,最让人头疼的往往是那些“看起来不起眼”的小问题。比如表格编号这事:今天在表后面多加了两个空白行,明天给客户交稿前发现整个章节的编号全部错位,光是挨个改序号就能耗掉大半个下午。我前阵子帮人整理一份上百页的技…

2026/9/23 4:49:06 阅读更多 →
从第一个站到第二个站:独立开发者的静态网站选型与落地实践

从第一个站到第二个站:独立开发者的静态网站选型与落地实践

1. 项目概述1.1 核心需求解析做独立开发者这几年,说实话,第一个网站上线的那天晚上我兴奋得没睡着。但等它跑了半年,流量惨淡、功能臃肿、代码自己都懒得看第二遍之后,我才慢慢琢磨明白一个道理:第一个网站是练手&…

2026/9/23 9:53:41 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/23 9:53:40 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/23 9:53:40 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/23 9:53:40 阅读更多 →