ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

http-api-design 指南解读:从 Heroku Platform API 提炼的 HTTP+JSON API 设计规范

http-api-design 指南解读:从 Heroku Platform API 提炼的 HTTP+JSON API 设计规范 API设计教程【免费下载链接】http-api-designHTTP API design guide extracted from work on the Heroku Platform API项目地址https://gitcode.com/gh_mirrors/ht/http-api-design点击查看免费下载本篇文章系统解读当前仓库 http-api-design 中的核心规范文档 it/SUMMARY.md意大利语版完整指南。该指南最初从 Heroku Platform API 的实际工程实践提炼而成覆盖 API 设计的基础原则、请求与响应模式以及交付工件Schema、文档、示例、稳定性四大层面。读完本文你将掌握一套可直接落地的 HTTPJSON API 设计清单包括版本化、缓存、分页、错误结构、状态码语义、资源命名与路径规划等关键决策。指南背景与仓库定位本仓库的核心是 en/SUMMARY.md 与 it/SUMMARY.md 等语言版本指南。英文版按章节拆分为 基础原则、请求、响应 三个子目录另有工件章节意大利语版则以单个 SUMMARY.md 文件承载完整正文本文即以其为主体展开。指南的立场非常明确目标是一致性与聚焦业务逻辑避免在设计细节上空耗时间——追求的是一套良好、一致、文档完善的设计方法而非唯一/理想的方法论。它假定读者已熟悉 HTTPJSON API 的基础原理因此不重复理论只给出可直接采用的工程决策。一、基础原则Foundations本部分确立整份指南的根基性设计原则。1.1 分离关注点Separate Concerns设计组件时要保持结构简单在请求-响应周期的不同环节中分离关注点。组件保持简单才能把精力聚焦到更大、更难解决的问题上。具体的职责划分规则请求与响应各自负责管理某个特定资源或资源的集合路径path用于表达身份标识identity请求体body用于传输内容请求头headers用于传递附加元数据metadata。关于 query 参数URL 中的查询参数只在极少数情况下可以作为 header 的替代方案。header 始终是首选因为它更灵活能承载更细致的信息。详见英文版 分离关注点。1.2 强制安全连接TLS要求 API 访问必须使用 TLS 安全连接没有任何例外。不要试图判断何时该用 TLS、何时不必直接全部强制。理想情况下直接拒绝一切非 TLS 请求避免不安全的数据与信息交换若服务端无法执行此类拦截规则则至少对非 TLS 请求返回403 Forbidden不推荐使用重定向客户端遭遇多次重定向会成倍增加服务器流量且首次 HTTP 调用中敏感信息即已明文暴露使 TLS 形同虚设。详见英文版 强制安全连接。1.3 在 Accept 头中强制版本化版本管理及版本间迁移是 REST API 设计与运营中最具挑战性的方面之一因此最好从一开始就内置相应机制。强制所有请求显式声明 API 版本避免给用户带来意外与破坏性变更避免设置默认版本——默认版本在未来极难更改一旦用户依赖它迁移成本极高最佳做法是把版本信息放在 HTTP header 中与其他元数据一起通过Accept头配合自定义Content-Type传递。Accept: application/vnd.herokujson; version3这里的application/vnd.herokujson是供应商特定vendor-specific的媒体类型version3是版本参数。详见英文版 Accept 头版本化。1.4 用 ETag 支持缓存在所有响应中包含ETag头用于标识所返回资源的特定版本。用户据此可将资源加入缓存在后续请求中携带If-None-Match头携带上次拿到的 ETag 值让服务端判断缓存是否需要更新。这实际上是 HTTP 标准中的条件请求conditional request机制若资源未变化服务端可返回304 Not Modified从而显著节省带宽。详见英文版 ETag 缓存。1.5 提供 Request-Id 便于追踪在每个 API 响应的 header 中包含Request-Id参数以 UUID 值填充。客户端、服务器及其他辅助服务对Request-Id进行日志记录后即可获得一套请求级追踪、诊断与调试机制这在排查跨服务调用链问题时尤为关键——通过同一个请求 ID 可以串联起网关、业务服务与下游依赖的日志。详见英文版 Request-Id 追踪。1.6 用 Range 将超大响应拆分为多次请求超大响应应当拆分为多次请求通过Range头说明是否还有更多数据以及如何继续获取。请求方用Range头表达想获取的数据区间服务端通过响应头、状态码、限制limits、排序ordering与迭代iteration语义配合完成分页式拉取其细节请求/响应头、状态码、限制、排序与迭代方式可参考 Heroku Platform API 官方文档中关于 Ranges 的讨论章节指南直接引用了该实践作为权威细节来源。详见英文版 Range 分页。同时注意Range分页与后文响应章节的206 Partial Content状态码直接配套使用。二、请求设计Requests本节概述 API 请求侧的结构模式。2.1 请求体接受序列化 JSONPUT/PATCH/POST请求体应接受序列化 JSON可以替代、也可以在表单编码form-encoded数据之外额外支持。这使请求体与响应体的 JSON 序列化形式形成对称对开发者更友好。$ curl -X POST https://service.com/apps \ -H Content-Type: application/json \ -d {name: demoapp} { id: 01234567-89ab-cdef-0123-456789abcdef, name: demoapp, owner: { email: usernameexample.com, id: 01234567-89ab-cdef-0123-456789abcdef }, ... }注意示例中请求头声明Content-Type: application/json请求体为紧凑 JSON响应体同样是 JSON且资源对象内含id、name、嵌套的owner对象——这些细节对应后文的 UUID、外键嵌套等规范。详见英文版 请求体 JSON。2.2 资源命名Resource Names除非资源本身属于系统级单数概念否则一律使用复数形式的资源名。例如某些系统中单个用户只能拥有一个账户此时account可保持单数。保持这一约定可以在引用资源时维持一致性。详见英文版 资源命名。2.3 动作Actions优先采用不需要特殊动作的端点布局。当确实需要动作时用标准的actions前缀清晰地划出动作语义/resources/:resource/actions/:action示例——停止某次特定的运行run/runs/{run_id}/actions/stop此外集合上的动作也应尽量最小化。确有必要时使用顶层actions划分以避免命名空间冲突并清晰表达动作的作用范围/actions/:action/resources示例——重启所有服务器/actions/restart/servers该模式比在资源名上强行加动词如/runs/stop或/stop-runs更可预测、更易路由。详见英文版 动作。2.4 一致的路径格式Consistent Path Formats2.4.1 路径与属性使用小写路径统一使用小写并以连字符-分隔与主机名hostname的书写习惯保持一致service-api.com/users service-api.com/app-setups属性同样使用小写但单词间用下划线_分隔这样在 JavaScript 中可以直接书写而无需引号service_class: first也就是说路径层面用kebab-case属性字段层面用snake_case两者都是小写。详见英文版 路径与属性小写。2.4.2 支持非 ID 引用以提升便利性某些场景下让终端用户提供 ID 来定位资源并不方便。例如用户习惯用应用名称思考但应用在系统内以 UUID 标识。此时可同时接受ID 与名称两种引用方式$ curl https://service.com/apps/{app_id_or_name} $ curl https://service.com/apps/97addcf0-c182 $ curl https://service.com/apps/www-prod但绝不能只接受名称而不保留指定 ID 的能力——ID 必须是始终可用的兜底引用方式。详见英文版 非 ID 引用。2.4.3 最小化路径嵌套在父/子关系嵌套的数据模型中路径极易变得冗长/orgs/{org_id}/apps/{app_id}/dynos/{dyno_id}应限制嵌套深度优先把资源定位在路径根部嵌套只用于表达集合关系。例如对于 dyno 依赖 app、app 依赖 org 的场景改为扁平化设计/orgs/{org_id} /orgs/{org_id}/apps /apps/{app_id} /apps/{app_id}/dynos /dynos/{dyno_id}这样每个层级都提供独立、可缓存的资源入口避免深层路径带来的耦合与路由复杂度。详见英文版 最小化路径嵌套。三、响应设计Responses本节概述 API 响应侧的模式。3.1 返回恰当的状态码每个响应都必须返回恰当的 HTTP 状态码。成功响应建议如下状态码适用场景200 OK同步GET、DELETE、PATCH请求成功完成或同步PUT完成资源更新201 Created同步POST成功或PUT创建了新资源202 AcceptedPOST、PUT、DELETE、PATCH被异步处理并成功受理206 Partial ContentGET成功但只返回部分内容配合 Range 分页认证与授权错误码要格外谨慎401 Unauthorized请求因用户未认证而失败403 Forbidden请求因用户无权访问该资源而失败。业务错误码需附加错误类型信息422 Unprocessable Entity请求已被理解但包含无效参数429 Too Many Requests超出请求限额请稍后重试500 Internal Server Error服务端出错应检查服务状态并视情况上报。状态码与错误的权威定义以 HTTP 响应码规范RFC 7231 第 6 节为准。详见英文版 状态码。3.2 尽可能返回完整资源只要可能就返回完整资源表示即包含全部属性的对象。200或201响应应始终返回完整资源包括PUT/PATCH/DELETE请求$ curl -X DELETE \ https://service.com/apps/1f9b/domains/0fd4 HTTP/1.1 200 OK Content-Type: application/json;charsetutf-8 ... { created_at: 2012-01-01T12:00:00Z, hostname: subdomain.example.com, id: 01234567-89ab-cdef-0123-456789abcdef, updated_at: 2012-01-01T12:00:00Z }而202 Accepted响应不包含完整资源表示$ curl -X DELETE \ https://service.com/apps/1f9b/dynos/05bd HTTP/1.1 202 Accepted Content-Type: application/json;charsetutf-8 ... {}这与状态码语义一致202只是已受理操作尚未完成因此无需、也无法返回最终资源状态。详见英文版 完整资源。3.3 提供资源 (UU)ID默认给每个资源分配id属性优先使用 UUID除非有充分的理由不用。不要使用自增 ID——它们不是全局唯一的尤其在存在多个服务实例或多种资源时极易冲突。UUID 以小写8-4-4-4-12格式呈现id: 01234567-89ab-cdef-0123-456789abcdef这保证了资源标识的全局唯一性与可预测性便于客户端缓存、去重与跨服务引用。详见英文版 资源 UUID。3.4 提供标准时间戳默认给资源提供created_at与updated_at两个时间戳{ // ... created_at: 2012-01-01T12:00:00Z, updated_at: 2012-01-01T13:00:00Z, // ... }若某类资源的时间戳没有意义可以省略。详见英文版 标准时间戳。3.5 时间统一为 UTC 并采用 ISO8601 格式只接受并只返回 UTC 时间并以ISO8601格式展示finished_at: 2012-01-01T12:00:00Z末尾的Z表示 UTC零时区。这消除了客户端与服务端之间的时区歧义是全篇示例2012-01-01T12:00:00Z统一采用的形式。详见英文版 UTC/ISO8601。3.6 用嵌套对象表达外键关系用嵌套对象序列化外键引用{ name: service-production, owner: { id: 5d8201b0... }, // ... }而不是扁平化的owner_id字段{ name: service-production, owner_id: 5d8201b0..., // ... }嵌套方案的核心收益在于在不改变响应结构、不引入额外字段的前提下可以向嵌套对象中追加更多关于被引用资源的信息{ name: service-production, owner: { id: 5d8201b0..., name: Alice, email: aliceheroku.com }, // ... }详见英文版 外键嵌套。3.7 生成结构化错误错误响应体要一致且结构化包含三个字段id机器可读的错误标识message用户可理解的错误说明url可选指向该错误的详细说明与解决方法文档。示例HTTP/1.1 429 Too Many Requests{ id: rate_limit, message: Account reached its API rate limit., url: https://docs.service.com/rate-limits }同时要求将错误格式及用户可能遇到的错误id写入文档让客户端能够编程化地识别与处理各类错误。详见英文版 结构化错误。3.8 展示速率限制状态对客户端测量请求限额以保护服务稳定性、维持其他客户端的服务质量。指南建议采用**令牌桶算法token bucket**来测量与监控请求限额。在该方案下每次响应都在RateLimit-Remaining头中返回剩余可用请求数。客户端据此可以自适应地调节请求频率避免触发429。详见英文版 速率限制状态。3.9 所有响应保持 JSON 最小化额外空白会无谓地增大请求/响应体积而且许多客户端会自动对 JSON 做美化prettify处理。因此默认输出最小化 JSON{beta:false,email:aliceheroku.com,id:01234567-89ab-cdef-0123-456789abcdef,last_login:2012-01-01T12:00:00Z,created_at:2012-01-01T12:00:00Z,updated_at:2012-01-01T12:00:00Z}而不是美化后的多行形式{ beta: false, email: aliceheroku.com, id: 01234567-89ab-cdef-0123-456789abcdef, last_login: 2012-01-01T12:00:00Z, created_at: 2012-01-01T12:00:00Z, updated_at: 2012-01-01T12:00:00Z }若确需让客户端获得更易读的输出可以可选地提供更啰嗦的途径例如查询参数?prettytrue或通过Accept头协商例如Accept: application/vnd.herokujson; version3; indent4;。详见英文版 JSON 最小化。四、交付工件Artifacts本部分描述支撑 API 设计与交付的各类工件。4.1 提供机器可读的 JSON Schema提供机器可读的 JSON Schema以形式化、精确地描述 API。指南推荐使用prmd工具来管理 Schema并用以下命令校验其合法性prmd verifySchema 是文档、示例、客户端代码生成的单一事实来源避免文档与实现漂移。4.2 提供开发者可读的文档提供开发者与客户端可查阅的、清晰易读的文档。若已按上文用prmd创建 Schema即可用如下命令为全部端点一键生成 Markdown 格式文档prmd doc除端点规格外API 总览文档还应包含以下信息认证说明如何获取并使用 access token稳定性与版本化说明如何选择 API 版本常见请求头与响应头序列化错误格式多种语言的 API 使用示例。4.3 提供可执行示例提供简单、可直接运行的示例让用户能快速在终端中体验 API 调用。示例要尽可能详尽显著降低用户试用与接入的成本$ export TOKEN... # acquire from dashboard $ curl -is https://$TOKENservice.com/users使用prmd生成 Markdown 文档时每个端点会自动附带可执行示例。4.4 明确 API 稳定性明确说明 API或各端点的成熟度与稳定性例如用prototype/development/production之类的标志位来标注。稳定性与策略变更的参考框架可参照 Heroku 的 API 兼容性策略API compatibility policy一旦 API 进入生产环境并稳定运行就不得再做不向后兼容的变更若确需不兼容变更应创建带新版本号的新 API对应前文 Accept 头版本化机制让旧版本按自己的生命周期逐步退役。五、规范速查清单综合全文落地一个 HTTPJSON API 时可对照以下清单自检安全所有请求强制 TLS非 TLS 请求返回403不用重定向版本Accept: application/vnd.vendorjson; versionN无默认版本缓存响应带ETag支持If-None-Match条件请求可观测每个响应带 UUID 格式的Request-Id全链路打日志分页大响应用Range头分页配206状态码请求体PUT/PATCH/POST接受 JSON可同时支持表单编码资源与路径复数资源名、小写路径-分隔、小写属性_分隔、actions前缀、最小化嵌套、支持 ID/名称双引用状态码200/201/202/206区分成功语义401/403/422/429/500覆盖错误场景资源表示默认返回完整资源含小写8-4-4-4-12的 UUID、created_at/updated_atUTC ISO8601、外键用嵌套对象错误与限流结构化错误体id/message/url响应头返回RateLimit-Remaining输出默认最小化 JSONpretty与缩进作为可选项工件机器可读 JSON Schemaprmd verify、开发者文档prmd doc、可执行示例、显式稳定性声明prototype/development/production生产后不做不兼容变更。结语it/SUMMARY.md 这份指南的价值在于它不是空泛的设计哲学而是一组可以直接对照执行的工程决策——从 TLS 强制、Accept 头版本化到状态码语义、UUID/时间戳/嵌套外键的结构化响应再到 Schema、文档、示例与稳定性声明四大交付工件。英文原版各章节散落在 en/foundations、en/requests、en/responses 中而意大利语版 SUMMARY.md 将全部正文整合为单文件是快速通读整套规范的便捷入口仓库根目录的 README.md 与 it/README.md 则提供了指南背景与多语言版本信息。遵循这套规范API 团队可以把设计讨论收敛为查清单把精力真正留给业务逻辑本身。赞分享API设计教程【免费下载链接】http-api-designHTTP API design guide extracted from work on the Heroku Platform API项目地址https://gitcode.com/gh_mirrors/ht/http-api-design点击查看免费下载相关推荐http-api-design 精读从 Heroku Platform API 提炼的 HTTPJSON API 设计实践规范意大利语版全文解析http api design 精读从 Heroku Platform API 提炼的 HTTPJSON API 设计实践规范意大利语版全文解析 这份指API设计教程HTTP API Design Guide 全指南解读源自 Heroku Platform API 的 HTTPJSON 接口设计规范详解HTTP API Design Guide 全指南解读源自 Heroku Platform API 的 HTTPJSON 接口设计规范详解 本篇文章是对开源API设计教程HTTP API Design Guide源自 Heroku Platform API 实践的 HTTPJSON 接口设计指南HTTP API Design Guide源自 Heroku Platform API 实践的 HTTPJSON 接口设计指南 导读 README.md hAPI设计教程上一篇kcmd 语义模型部署实战一次 push 同时治理 Knowledge Catalog 并部署 BigQuery/Spanner 属性图下一篇PHP FIG 的 PSR 生命周期工作流详解从提案萌芽到废弃归档的完整治理机制创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进