Repository navigation
[P1][openapi] 分离文档生成与端点挂载,明确中间件覆盖范围 #88
Copy link
Copy link
Closed
Labels
bugSomething isn't workingSomething isn't working
Description
问题与影响
开启 openapi feature 后,into_axum_router 在用户已配置的路由及 layer 之后自动追加 /openapi.json、/redoc 和 /scalar。配置在 GotchaRouter 上的鉴权等中间件不会覆盖这些新端点。编译期功能开关同时决定了 HTTP 暴露策略,应用无法只生成 schema 或显式选择文档挂载策略。
此外 Gotcha::with_openapi() 只返回 self,是一个没有行为的公开方法。
已验证的复现
在本地源码上通过 GotchaApp::build_router 装配应用,为业务路由添加始终返回 401 的 middleware:
- 请求业务路由返回 401。
- 请求
/openapi.json返回 200。
这说明中间件覆盖范围与应用级配置直觉不一致;应用仍可通过在最终 Axum router 上额外加 layer 规避。
代码位置
调整方向
将文档生成、文档路由挂载和最终全应用 middleware 装配分开。提供显式的文档端点开关、路径及覆盖策略;明确区分业务路由 middleware 与最终全应用 middleware。处理 with_openapi() 的实际语义或弃用迁移。
验收标准
- 能生成 schema 而不暴露文档 HTTP 端点(与 [openapi] The assembled spec is unreachable without an HTTP request #77 协同)。
- 文档端点可以禁用或自定义挂载路径。
- 显式应用于整个应用的鉴权覆盖业务接口和三个文档端点。
- 支持业务受保护、文档公开这一显式配置,避免只能依赖调用顺序。
- 测试覆盖两套 API 的装配行为及
with_openapi()的最终语义。 - 写明默认行为变化与迁移方式。
当前版本复查与已批准方案
基于 PR #114 合入后的 main 7cea0fef855cd0b16a3df2d101a1f26a8cc92d09 复查:
GotchaRouter::into_axum_router仍在已有业务路由/layer 之后追加三个固定文档端点。Gotcha::with_openapi()仍只返回 self;Redoc/Scalar 模板的文档地址也固定为/openapi.json。openapitransform 为FnOnce,因此无 HTTP 导出应采用消费构建对象的入口,保留现有 transform 顺序和单次执行约定;不应为导出而将回调改成 Clone/Fn。
用户已批准以下范围,已实现于 PR #115:
- 编译
openapifeature 只提供文档能力,默认不挂载文档 HTTP 端点。with_openapi()显式启用默认的/openapi.json、/redoc、/scalar;应用级端点配置支持关闭和自定义路径,两个 UI 使用实际配置的 JSON 地址。 - 文档端点配置属于顶层应用(Gotcha builder / GotchaApp 对应入口),不随业务子路由 nest/merge 隐式传播。
- 保留现有
layer对已注册业务路由的 Axum 语义,新增 builderapp_layer及 trait 对应的最终装配 hook。全应用 middleware 在业务路由和文档端点组装完成后统一应用,覆盖范围不依赖with_openapi的调用顺序。仅在业务路由上加layer时,文档可以显式保持公开。 - 提供消费路由构建对象的文档导出入口,直接取得经过全部 transform 的 OpenAPI 文档,不初始化应用状态、绑定端口或启动后台任务;与 HTTP 文档复用同一生成流程,协同解决 [openapi] The assembled spec is unreachable without an HTTP request #77。
- 通过两套 API 的必要集成测试验证默认禁用、显式启用、自定义文档地址、全应用鉴权和业务鉴权的覆盖范围;验证导出与 HTTP 文档等价,并沿用既有 transform 顺序测试。
默认行为的迁移必须明确:此前仅打开 feature 就暴露文档的应用,需要显式启用端点;已有 with_openapi() 调用获得实际行为。现有业务 layer 不静默改变范围,全应用覆盖通过新入口明确选择。
本次提案只覆盖文档生成/挂载和 middleware 装配边界,#81 的其他路由能力继续单独跟踪。PR #115 已由用户于 2026-09-14 合入,merge commit 90e0efeff99ebcd032f054193cf632bafb5e5a95。
实现与验证
- PR refactor(openapi)!: make documentation endpoints explicit #115:默认关闭文档 HTTP 端点;
with_openapi()显式启用默认路径。OpenApiEndpoints配置 JSON、Redoc、Scalar 路径及 UI 关闭,两个 UI 使用配置后的 JSON URL。 - 共享
assembly::assemble依次装配业务路由、可选文档、全应用 middleware。Builderapp_layer和 traitfinish_router覆盖全部端点及 fallback,原有layer保留已注册业务路由范围。 Gotcha::into_openapi()、GotchaRouter::into_openapi()、GotchaApp::openapi_document()使用同一生成/transform 流程直接导出文档;无需配置加载、状态初始化、端口或任务,协同解决 [openapi] The assembled spec is unreachable without an HTTP request #77。未启用文档且未请求导出时不生成文档、不执行 transform。- 7 项装配测试覆盖两套 API、开关/自定义地址/单独关闭 UI、HTML 地址转义、鉴权范围、全应用 layer 顺序与 fallback、配置错误提前返回、导出与 HTTP 字节等价和回调次数、无 runtime 导出。1 项 unit test 集中覆盖端点路径验证。
- 原有文档集成测试和 OpenAPI/Extension 示例已显式开启端点,README/API 文档/MIGRATION 完成迁移说明。移除不再使用的 gotcha 直接 cfg-if 依赖。
- 本地 gotcha 默认/all-features 测试(含 doctest)、workspace all-features check、默认 check、workspace Clippy、格式检查及拒绝 warning 的文档构建全部通过。
- 实际执行 OpenAPI 示例
--export-openapi,工作目录包含无效配置文件仍成功输出 7 条路径、5 个 component schema;不创建运行时或启动应用。 - GitHub CI:commit
4b25e914e3abba446bd6dcd77898e9c757570c5c的 11 项检查全部通过,见 run 34817382358。
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
bugSomething isn't workingSomething isn't working
Activity