Skip to content

fix(openapi)!: describe HTTP response contracts independently of schemas - #107

Merged
Kilerd merged 1 commit into
mainfrom
fix/response-contracts
Sep 14, 2026
Merged

Kilerd merged 1 commit into
mainfrom
fix/response-contracts

Conversation

@Kilerd

@Kilerd Kilerd commented Sep 13, 2026 •

Copy link
Copy Markdown
Owner

问题与行为变化

原先 Schematic 自动得到 200 application/json 的响应描述:String 的媒体类型错误,自定义类型无法同时提供 schema 和自己的 HTTP 契约,错误状态通常只能落到 default。现在数据 schema 与 HTTP 响应描述分离,状态码、媒体类型和响应体由 Responsible 描述。

  • 标准返回类型分别描述文本、JSON、HTML、二进制和空响应。
  • WithStatus<T, STATUS> 同时设置真实 HTTP 状态和文档状态,且无需开启 OpenAPI 即可使用。Result<WithStatus<Json<User>, 201>, WithStatus<Json<ApiError>, 409>> 可直接表达成功和错误状态。
  • #[api(responses(response(status = 404, body = "ApiError", description = "Not found")), drop_default)] 声明显式响应;content_type 可自定义,省略 body 表示无响应体。显式条目按状态覆盖推断值,drop_default 删除推断的默认条目。声明仅影响文档。
  • 自定义类型可以同时实现 Schematic 和 Responsible。公开 response、empty_response、default_response、merge_responses 辅助函数,避免手工拼装整棵 OAS 结构。

Result<T, E> 合并两侧的响应。相同状态的不同媒体类型被保留,同一媒体类型的不同 schema 使用 anyOf;schema 引用继续参与统一组件收集与重写。

兼容变化与边界

移除 Schematic -> Responsible blanket impl、ErrorResponsible 和 Schematic::empty_body。schema-only 自定义响应/错误需实现 Responsible 或改用 Json<T> / WithStatus 等明确 HTTP 类型。README 和迁移指南给出新契约、宏语法和迁移方式。

运行时才确定的 (StatusCode, T) 状态记录为 default;原生 Response 不推断 body schema。固定状态必须在 100..=599;无响应体状态会清空 body 及相关 headers。外层 WithStatus 与 Axum 的状态 tuple 一样会覆盖内层错误状态,建议将它放在 Result 的成功分支。

响应合并支持 schema-level refs;不同的 response-level refs 无法直接组成 union,会在组装时明确失败,应使用内联 Response 包含 schema refs。宏声明不得将所有响应删除。

验证

  • 一个 HTTP 集成测试验证 201/204/404/409、文本/HTML/二进制/CSV、动态状态的显式声明、默认条目移除和覆盖,以及仅从显式声明收集组件。
  • core 单元测试验证同状态的媒体/schema 合并、固定状态重映射和未约束 schema;宏单元测试验证状态、重复声明和 body 类型校验,不在集成测试中重跑这些用例矩阵。
  • 默认与 OpenAPI 的 gotcha 全套测试通过;gotcha_core all-features / no-default-features 测试、gotcha_macro 测试通过。
  • workspace all-features 编译与 Clippy -D warnings、格式检查通过。
  • CI 的 Test job 增加 gotcha_core 两种配置的单元测试,确保响应合并逻辑持续受检查。

GitHub CI:11/11 项检查通过(run 34764773671,commit d779dd7)。

Closes #76

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[openapi] A handler cannot declare its own status codes or content types

1 participant