API设计文档后端【免费下载链接】OpenAPI-SpecificationThe OpenAPI Specification Repository项目地址https://gitcode.com/gh_mirrors/op/OpenAPI-Specification点击查看免费下载导读本文围绕 OpenAPI-Specification 仓库中的提案 2024-08-01-Self-Identification.md 展开它提出在 OpenAPI 文档根对象中引入一个self字段让文档拥有与获取位置URL无关的稳定身份标识URI从而支撑跨环境复用、离线解析与文档迁移。该提案已部分落地为 OAS 3.2.0 的$self字段见 versions/3.2.0.md阅读本文后你将理解 identifier 与 locator 分离的来龙去脉、self字段的语法与解析规则、它在多文档 OpenAPI DescriptionOAD中的实际用法以及其与 JSON Schema$id的异同。一、背景OAS 3.1 的引用语义是「标识符」而非「定位符」1.1 URI 与 URL 的分离OpenAPI 3.1 的引用reference在语义上被当作**标识符identifier而非定位符locator**处理。这一行为继承自 JSON Schema 2020-12并在 OAS 3.1.1 中变得更加明确。在 versions/3.1.1.md 中规范明确指出OpenAPI Description 内部的引用 URI 作为标识符解析因此一个 URI 可以与资源实际所在的位置retrieval URI不一致。这种分离带来的直接收益是文档可以拥有稳定、自分配的标识符从而允许对 OpenAPI Description 进行某些重构——例如移动、复制或重命名文档——而无需改写$ref等关键字的值。1.2 目前只有 Schema Object 能做到在 OAS 3.1 中只有 Schema Object 能够设置稳定、与位置无关的标识符方式有两种$id设置完整资源的绝对 URI同时按 RFC3986 §5.1.1 充当资源的 base URI$anchor以及技术上还有$dynamicAnchor设置不依赖 JSON/YAML 结构位置的「plain name」URI 片段类似 HTML 中的id属性。也就是说整个 OpenAPI Description 文档本身、以及文档内除 Schema 之外的其他对象都无法声明自己的稳定标识。同时由于 Schema 的递归结构$id的解析可能很复杂——每个$id本身可以是相对 URI 引用需要先基于父级 Schema 的$id解析。对于 OpenAPI Description 的其他部分这种复杂度并没有清晰的用例。二、动机为什么要让文档「自我标识」2.1 核心用例提案列举了若干需要身份与位置分离的典型场景应对网络挑战受限的网络安全策略间歇性连接高延迟/低带宽文档宿主需要认证这是社区已知痛点。抽象开发/测试/部署的差异开发期使用.json/.yaml扩展名IDE 偏好生产期使用 HTTP 内容协商共享文档在源码仓库中的组织方式与部署目录/服务器布局不同同一套引用在本地文件系统、staging 与 production 之间可移植。作为 bundling 的前提身份与位置分离是虽然单独并不充分实现 JSON Schema / OpenAPI 文档 bundling将多文档合并为单文档的必要条件。2.2 现有变通方案的代价这些用例并非无解但现有变通手段要么限制部署方式要么依赖易出错的引用目标重写reference target rewriting。更关键的是很多执行引用重写的工具并未考虑 OAS 3.1 相比 3.0 及更早版本新增的引用复杂度如 base URI 的多来源优先级容易在重写过程中引入语义错误。2.3 既有先例JSON Schema 世界$id的广泛实现证明「位置无关的自我标识」不仅可行而且经过充分验证——尤其考虑到$id的实现难度要高于本提案。OASComply 项目其使用的 JSON Schema 包jschon内置 schema catalog支持可配置的文件与网络来源来管理 URI 到 URL 的映射本地文件可视为file:URL这正是「工具如何根据self定位文档」的现成参考实现。Atom 格式Atom 最早通过relself的 web link 实现自我标识。三、提案方案在根对象放置唯一的self字段3.1 核心设计提案建议引入 JSON Schema$id的一个简化类比它只出现在一个位置在根 OpenAPI ObjectOAS和 Arazzo ObjectArazzo中新增self字段。当引用一个带有self字段的文档时引用值 SHOULD 使用该self值这样即使文档被移动引用值也保持不变。只把self放在根对象使其与既有的解析引导bootstrapping流程天然对齐。3.2 解析引导流程带self的新版本提案给出的解析步骤序列如下检查根 OpenAPI/Arazzo Object 中的openapi或arazzo字段确定规范版本检查jsonSchemaDialect字段确定默认的 Schema Object 方言按 RFC3986 §5.1.2–5.1.4 确定 base URI大多数情况下使用 §5.1.3 的 retrieval URL**新增**检查self字段按 RFC3986 §5.1.1 提供 base URI若存在则将其与上一步的 base URI 解析并把结果作为文档的实际 base URI继续按常规解析文档其余部分。OAS 3.1.1 已经明确为了支持 Schema Object区分位置与身份已是强制要求。当前若想给文档关联一个与当前 URL 不同的 URI只能通过外部手段——很多工具允许手动设置 retrieval URL却不验证文档是否真的位于该 URL。这种方式依赖用户使用非标准实现特性而非基于文档作者意图的明确定义行为。有了self字段后工具需要被配置为「如何定位self值与位置不匹配的文档」可参考前述 JSON Schema 实现catalog的多种做法。四、详细设计OpenAPI Object 的字段定义提案为 OAS 规范起草了如下字段表原文以 OAS 结构书写Arazzo 的适配方式同理## OpenAPI Object ### Fixed Fields Field Name | Type | Description ---|:---|:--- self | URI-reference (without a fragment) | Sets the URI of this document, which also serves as its base URI in accordance with RFC 3986 §5.1.1; the value MUST NOT be the empty string and MUST NOT contain a fragment要点归纳属性约束位置仅限根 OpenAPI Object / Arazzo Object全文恰好出现一次类型URI 引用不带 fragment空值禁止为空字符串语义既是文档 URI也按 RFC3986 §5.1.1 充当文档的 base URI此外提案指出在规范的「引用解析」与「base URI」章节中很可能还需要补充「如何配置工具解析与位置不匹配的self引用」的指导。五、落地印证OAS 3.2.0 中的$self提案发布后该功能已作为 OAS 3.2 的正式字段落地命名为$self带$前缀。在 versions/3.2.0.md 中可以找到完整定义5.1 字段定义versions/3.2.0.md 第 98 行$self|string| 该字符串必须符合 RFC3986 第 4.1 节定义的 URI 引用形式。$self字段提供本文档的自分配 URI并同时按 RFC3986 §5.1.1 充当其 base URI。当该字段存在时实现必须支持使用该字段定义的 URI 来标识 API description URI 的引用目标。与提案相比落地版本有两个差异值得注意字段名提案建议selfOAS 3.2.0 采用$self与 JSON Schema 的$id、$anchor等关键字风格一致类型措辞落地版类型为string约束为「URI 引用形式」提案的「非空、不含 fragment」约束在 versions/3.2.0.md 的参考解析章节中以行为语义体现见下文。5.2 互操作约束versions/3.2.0.md 第 111–112 行OAS 3.2.0 明确了引用目标文档时的强制性规则为确保互操作性若目标文档存在$self字段引用必须使用目标文档的$selfURI。实现可以选择支持使用 retrieval URI 等其他 URI 引用$self存在的文档但这种行为不具互操作性且不建议依赖。这正对应提案中「引用值 SHOULD 使用 self」的升级版——落地时从 SHOULD 强化为 MUST针对引用方。5.3 相对$self的解析versions/3.2.0.md 第 154–156 行若$self是相对 URI 引用则先按 RFC3986 §5.1.2–5.1.4 的「下一个可用 base URI 来源」解析再用于解析其他相对引用缺失或相对$self时最常见的 base URI 来源是retrieval URI实现应允许用户提供「带预期 retrieval URI 的文档」使引用解析如同执行了检索一样——这与提案「工具需要配置如何定位不匹配文档」的建议一致。5.4 对 API URL 不生效versions/3.2.0.md 第 292–303 行OAS 3.2.0 明确区分了两类引用API description URI引用内部资源作为标识符解析受$self影响API URLServer Object 等指向实际服务地址忽略$self仍使用 retrieval URI。规范给出的示例中$self: https://apidescriptions.example.com/foo只用于标识 OpenAPI 文档本身而服务的生产 URLhttps://device1.example.com与测试 URLhttps://device1.example.com/test仍由 Server Object 与 retrieval URI 决定。这一点非常重要$self绝不改变 API 服务的真实地址它只影响「文档身份」与「文档内相对引用的解析基准」。5.5 多文档解析示例versions/3.2.0.md 附录 F第 5237–5297 行规范附录给出了完整的 base URI 确定与引用解析示例是理解$self用法的最佳素材。第一个文档假设 retrieval URI 是本地文件file://home/someone/src/api/openapi.yaml但该 URI 因$self的存在而变得无关紧要openapi: 3.2.0 $self: https://example.com/api/openapi info: title: Example API version: 1.0 paths: /foo: get: requestBody: $ref: shared/foo#/components/requestBodies/Foo第二个共享组件文档假设 retrieval URI 是https://git.example.com/shared/blob/main/shared/foo.yaml同样被$self取代openapi: 3.2.0 $self: https://example.com/api/shared/foo info: title: Shared components for all APIs version: 1.0 components: requestBodies: Foo: content: application/json: schema: $ref: ../schemas/foo schemas: Foo: $id: https://example.com/api/schemas/foo properties: bar: $ref: bar Bar: $id: https://example.com/api/schemas/bar type: string解析过程第一个文档中相对引用shared/foo#/components/requestBodies/Foo基于$self解析为https://example.com/api/shared/foo#/components/requestBodies/Foo该 URI 的 fragment 前部分与第二个文档的$self精确匹配于是定位到第二个文档的#/components/requestBodies/Foo第二个文档中../schemas/foo基于它自己的$self解析为https://example.com/api/schemas/foo匹配 SchemaFoo的$id从而指向该 Schema ObjectSchemaFoo内子模式$ref: bar再基于$id解析为https://example.com/api/schemas/bar匹配 SchemaBar的$id。两个 retrieval URI 在此例中完全无关——这正是「身份与位置分离」的直观演示同一组文档可以放在本地、staging 或生产环境的任意路径只要各自声明了$self/$id引用关系就不变。规范还特别提醒一个陷阱Schema 内的 JSON Pointer 片段会相对最近的$id解析而不是相对文档$self的 base URI因此仅靠#/components/schemas/Bar这类 JSON Pointer无法从 SchemaFoo内部引用 SchemaBar。5.6 相对$self的多环境部署versions/3.2.0.md 第 5400–5448 行附录进一步展示了相对$self的用法openapi: 3.2.0 $self: /api/openapi ...openapi: 3.2.0 $self: /api/shared/foo ...此时$self是仅含绝对路径的相对引用由 retrieval URI 提供主机与协议在 staging 得到https://staging.example.com/...在生产得到https://example.com/...在本地开发则是https://localhost:8080/...。这意味着同一组文档无需任何修改即可部署到不同主机只需替换宿主环境即可。六、向后兼容性提案明确指出OAS 3.2 与 Arazzo 1.1 中不使用self字段的文档行为将与 OAS 3.1 和 Arazzo 1.0 文档完全一致。由于次版本号升级足以管理兼容性问题——只支持到 3.1/1.0 的软件不应尝试解析 3.2/1.1 文档。即self是纯增量字段不写它所有既有行为不变写它才启用新的 base URI 语义。这也符合 OAS 3.2.0 中「缺失或相对$self时回退到 retrieval URI」的实现见 versions/3.2.0.md 第 156 行。七、备选方案每个对象都支持 plain name fragment提案也评估了一个更具雄心的替代方案在每个 Object中提供等价于 JSON Schema$anchor的关键字类似 HTML/XML 的id属性创建与对象在 JSON/YAML 结构中的位置无关的 plain name fragment。分析要点可行性已被证明JSON Schema 对$anchor的支持表明该方案可实现且「HTML 的 id 属性」这一心智模型对开发者很熟悉成本更高处理 fragment 声明关键字需要在声明「含 plain name fragment 的引用目标无法解析」之前扫描全部对象以查找该关键字——通常在文档加载时完成也可以按需增量处理定位self字段是该方案的前置条件无论日后是否支持 plain name fragmentself都值得先行加入。因此它被列为「备选」而非替代本提案的选项。八、总结与后续维度要点解决的问题OAS 3.1 只有 Schema Object 能自标识身份文档整体与其他对象不能提案方案根 OpenAPI/Arazzo Object 新增self字段URI 引用、无 fragment、非空落地状态以$self进入 versions/3.2.0.md并配套解析规则与附录 F 示例对 API URL不生效服务地址仍由 Server Object / retrieval URI 决定兼容性不写即等价于 3.1/1.0 行为纯增量对于读者而言若你正在维护一套跨环境本地开发 / staging / 生产共享的 OpenAPI 多文档结构或正被「文档移动后$ref全部失效」所困扰$self是值得优先试用的机制它用最少的侵入仅一个根字段换取「引用永不因位置变化而失效」的稳定性。更进一步它也是未来实现 OpenAPI Description bundling 与 plain name fragment 支持的基础。相关提案与规范正文可在本仓库的 proposals/2024-08-01-Self-Identification.md 与 versions/3.2.0.md 中持续跟踪。赞分享API设计文档后端【免费下载链接】OpenAPI-SpecificationThe OpenAPI Specification Repository项目地址https://gitcode.com/gh_mirrors/op/OpenAPI-Specification点击查看免费下载相关推荐TEngine与服务器集成.NET Core 8.0前后端一体化开发指南TEngine与服务器集成.NET Core 8.0前后端一体化开发指南 TEngine作为Unity商用级别开发框架原生支持与.NET Core 8.0服游戏开发10个Python Wechaty实用技巧让你的聊天机器人更智能10个Python Wechaty实用技巧让你的聊天机器人更智能 Python Wechaty是一款为聊天机器人开发者打造的对话式RPA SDK它能帮助开发后端即时通讯RPAReminiscence REST API使用指南自动化管理书签的10个技巧Reminiscence REST API使用指南自动化管理书签的10个技巧 Reminiscence是一个功能强大的自托管书签和存档管理器通过其REST上一篇告别模糊界面GLFW高DPI自动适配Retina显示器全指南下一篇Umi-OCR安全加固终极指南10个关键步骤保护你的离线OCR应用创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
阅读完成 · 觉得有帮助?