{"id":13601367,"url":"https://github.com/ZhangBohan/http-api-design-ZH_CN","last_synced_at":"2025-04-11T04:30:49.598Z","repository":{"id":26223252,"uuid":"29669838","full_name":"ZhangBohan/http-api-design-ZH_CN","owner":"ZhangBohan","description":"HTTP API 设计指南(http-api-design-ZH_CN)，翻译自https://github.com/interagent/http-api-design","archived":false,"fork":true,"pushed_at":"2020-03-04T01:55:42.000Z","size":2064,"stargazers_count":1480,"open_issues_count":0,"forks_count":227,"subscribers_count":76,"default_branch":"master","last_synced_at":"2024-08-02T18:40:22.920Z","etag":null,"topics":["api","chinese-translation","docs","http","rest-api","restful"],"latest_commit_sha":null,"homepage":null,"language":"HTML","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"cocoajin/http-api-design-ZH_CN","license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ZhangBohan.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-01-22T08:54:02.000Z","updated_at":"2024-07-24T09:33:06.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/ZhangBohan/http-api-design-ZH_CN","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ZhangBohan%2Fhttp-api-design-ZH_CN","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ZhangBohan%2Fhttp-api-design-ZH_CN/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ZhangBohan%2Fhttp-api-design-ZH_CN/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ZhangBohan%2Fhttp-api-design-ZH_CN/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ZhangBohan","download_url":"https://codeload.github.com/ZhangBohan/http-api-design-ZH_CN/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":223458273,"owners_count":17148443,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api","chinese-translation","docs","http","rest-api","restful"],"created_at":"2024-08-01T18:01:01.597Z","updated_at":"2024-11-07T04:30:43.796Z","avatar_url":"https://github.com/ZhangBohan.png","language":"HTML","funding_links":[],"categories":["HTML","best practises from industry"],"sub_categories":["API-Blueprint"],"readme":"# HTTP API 设计指南\n\u003e 翻译自 `HTTP API Design Guide` [https://github.com/interagent/http-api-design](https://github.com/interagent/http-api-design)\n\n- 更新时间：`2015-10-08` 更新至 [#50bda6](https://github.com/interagent/http-api-design/commit/50bda693252a4f52653d638fd5503b39b88b8470)\n- 欢迎大家问题和共同维护这个文档\n- HTML和PDF通过`MWeb`生成\n- 翻译人员见`CONTRIBUTORS.md`\n\n## 前言\n\n这篇指南介绍描述了 HTTP+JSON API 的一种设计模式，最初摘录整理自 Heroku 平台的 API 设计指引 [Heroku 平台 API 指引](https://devcenter.heroku.com/articles/platform-api-reference)。\n\n这篇指南除了详细介绍现有的 API 外，Heroku 将来新加入的内部 API 也会符合这种设计模式，我们希望非 Heroku 员工的API设计者也能感兴趣。\n\n我们的目标是保持一致性，专注业务逻辑同时避免过度设计。我们一直试图找出一种良好的、一致的、显而易见的 API 设计方法，而并不是所谓的\"最终/理想模式\"。\n\n我们假设你熟悉基本的 HTTP+JSON API 设计方法，所以本篇指南并不包含所有的 API 设计基础。\n\n我们欢迎你为这篇指南做[贡献](https://github.com/interagent/http-api-design/blob/master/CONTRIBUTING.md)。\n\n## 目录\n\n* 基础\n  * 强制使用安全连接（Secure Connections）\n  * 强制头信息 Accept 中提供版本号\n  * 支持Etag缓存\n  * 为内省而提供 Request-Id\n  * 通过请求中的范围（Range）拆分大的响应\n* 请求（Requests）\n  * 在请求的body体使用JSON格式数据\n  * 使用统一的资源路径格式\n  * 路径和属性要小写\n  * 支持方便的无id间接引用\n  * 最小化路径嵌套\n* 响应（Responses）\n  * 返回合适的状态码\n  * 提供全部可用的资源\n  * 提供资源的(UU)ID\n  * 提供标准的时间戳\n  * 使用UTC（世界标准时间）时间，用ISO8601进行格式化\n  * 嵌套外键关系\n  * 生成结构化的错误\n  * 显示频率限制状态\n  * 保证响应JSON最小化\n* 工件（Artifacts）\n  * 提供机器可读的JSON模式\n  * 提供人类可读的文档\n  * 提供可执行的例子\n  * 描述稳定性\n* 译者注\n\n\n### 基础\n\n#### 隔离关注点\n设计时通过将请求和响应之间的不同部分隔离来让事情变得简单。保持简单的规则让我们能更关注在一些更大的更困难的问题上。\n\n请求和响应将解决一个特定的资源或集合。使用路径（path）来表明身份，body来传输内容（content）还有头信息（header）来传递元数据（metadata）。查询参数同样可以用来传递头信息的内容，但头信息是首选，因为他们更灵活、更能传达不同的信息。\n\n#### 强制使用安全连接（Secure Connections）\n\n所有的访问API行为，都需要用 TLS 通过安全连接来访问。没有必要搞清或解释什么情况需要 TLS 什么情况不需要 TLS，直接强制任何访问都要通过 TLS。\n\n理想状态下，通过拒绝所有非 TLS 请求，不响应 http 或80端口的请求以避免任何不安全的数据交换。如果现实情况中无法这样做，可以返回`403 Forbidden`响应。\n\n把非 TLS 的请求重定向(Redirect)至 TLS 连接是不明智的，这种含混/不好的客户端行为不会带来明显好处。依赖于重定向的客户端访问不仅会导致双倍的服务器负载，还会使 TLS 加密失去意义，因为在首次非 TLS 调用时，敏感信息就已经暴露出去了。\n\n#### 强制头信息 Accept 中提供版本号\n\n制定版本并在版本之间平缓过渡对于设计和维护一套API是个巨大的挑战。所以，最好在设计之初就使用一些方法来预防可能会遇到的问题。\n\n为了避免API的变动导致用户使用中产生意外结果或调用失败，最好强制要求所有访问都需要指定版本号。请避免提供默认版本号，一旦提供，日后想要修改它会相当困难。\n\n最适合放置版本号的位置是头信息(HTTP Headers)，在 `Accept` 段中使用自定义类型(content type)与其他元数据(metadata)一起提交。例如:\n\n```\nAccept: application/vnd.heroku+json; version=3\n```\n\n#### 支持Etag缓存\n\n在所有返回的响应中包含`ETag`头信息，用来标识资源的版本。这让用户对资源进行缓存处理成为可能，在后续的访问请求中把`If-None-Match`头信息设置为之前得到的`ETag`值，就可以侦测到已缓存的资源是否需要更新。\n\n#### 为内省而提供 Request-Id\n\n为每一个请求响应包含一个`Request-Id`头，并使用UUID作为该值。通过在客户端、服务器或任何支持服务上记录该值，它能为我们提供一种机制来跟踪、诊断和调试请求。\n\n#### 通过请求中的范围（Range）拆分大的响应\n\n一个大的响应应该通过多个请求使用`Range`头信息来拆分，并指定如何取得。详细的请求和响应的头信息（header），状态码(status code)，范围(limit)，排序(ordering)和迭代(iteration)等，参考[Heroku Platform API discussion of Ranges](https://devcenter.heroku.com/articles/platform-api-reference#ranges).\n\n###请求（Requests）\n\n#### 在请求的body体使用JSON格式数据\n\n在 `PUT`/`PATCH`/`POST` 请求的正文（request bodies）中使用JSON格式数据，而不是使用 form 表单形式的数据。这与我们使用JSON格式返回请求相对应，例如:\n\n```\n$ curl -X POST https://service.com/apps \\\n    -H \"Content-Type: application/json\" \\\n    -d '{\"name\": \"demoapp\"}'\n\n{\n  \"id\": \"01234567-89ab-cdef-0123-456789abcdef\",\n  \"name\": \"demoapp\",\n  \"owner\": {\n    \"email\": \"username@example.com\",\n    \"id\": \"01234567-89ab-cdef-0123-456789abcdef\"\n  },\n  ...\n}\n```\n\n#### 使用统一的资源路径格式\n\n##### 资源名（Resource names）\n\n使用复数形式为资源命名，除非这个资源在系统中是单例的 (例如，在大多数系统中，给定的用户帐户只有一个)。 这种方式保持了特定资源的统一性。\n\n##### 行为（Actions）\n\n好的末尾不需要为资源指定特殊的行为，但在特殊情况下，为某些资源指定行为却是必要的。为了描述清楚，在行为前加上一个标准的`actions`：\n\n```\n/resources/:resource/actions/:action\n```\n\n例如：\n\n```\n/runs/{run_id}/actions/stop\n```\n\n#### 路径和属性要小写\n\n为了和域名命名规则保持一致，使用小写字母并用`-`分割路径名字，例如：\n\n```\nservice-api.com/users\nservice-api.com/app-setups\n```\n\n属性也使用小写字母，但是属性名要用下划线`_`分割，以便在Javascript中省略引号。 例如：\n\n```json\nservice_class: \"first\"\n```\n\n#### 支持方便的无id间接引用\n\n在某些情况下，让用户提供ID去定位资源是不方便的。例如，一个用户想取得他在Heroku平台app信息，但是这个app的唯一标识是UUID。这种情况下，你应该支持接口通过名字和ID都能访问，例如:\n\n```\n$ curl https://service.com/apps/{app_id_or_name}\n$ curl https://service.com/apps/97addcf0-c182\n$ curl https://service.com/apps/www-prod\n```\n不要只接受使用名字而放弃了使用id。\n\n#### 最小化路径嵌套\n\n在一些有父路径/子路径嵌套关系的资源数据模块中，路径可能有非常深的嵌套关系，例如:\n\n```\n/orgs/{org_id}/apps/{app_id}/dynos/{dyno_id}\n```\n\n推荐在根(root)路径下指定资源来限制路径的嵌套深度。使用嵌套指定范围的资源。在上述例子中，dyno属于app，app属于org可以表示为：\n\n```\n/orgs/{org_id}\n/orgs/{org_id}/apps\n/apps/{app_id}\n/apps/{app_id}/dynos\n/dynos/{dyno_id}\n```\n\n### 响应（Responses）\n\n#### 返回合适的状态码\n\n为每一次的响应返回合适的HTTP状态码。 好的响应应该使用如下的状态码:\n\n* `200`: `GET`请求成功，及`DELETE`或`PATCH`同步请求完成，或者`PUT`同步更新一个已存在的资源\n* `201`: `POST` 同步请求完成，或者`PUT`同步创建一个新的资源\n* `202`: `POST`，`PUT`，`DELETE`，或`PATCH`请求接收，将被异步处理\n* `206`: `GET` 请求成功，但是只返回一部分，参考：[上文中范围分页](#按范围分页)\n\n使用身份认证（authentication）和授权（authorization）错误码时需要注意：\n\n* `401 Unauthorized`: 用户未认证，请求失败\n* `403 Forbidden`: 用户无权限访问该资源，请求失败\n\n当用户请求错误时，提供合适的状态码可以提供额外的信息：\n\n* `422 Unprocessable Entity`: 请求被服务器正确解析，但是包含无效字段\n* `429 Too Many Requests`: 因为访问频繁，你已经被限制访问，稍后重试\n* `500 Internal Server Error`: 服务器错误，确认状态并报告问题\n\n对于用户错误和服务器错误情况状态码，参考：  [HTTP response code spec](https://tools.ietf.org/html/rfc7231#section-6)\n\n#### 提供全部可用的资源\n\n提供全部可显现的资源表述 (例如： 这个对象的所有属性) ，当响应码为200或是201时返回所有可用资源，包含 `PUT`/`PATCH` 和 `DELETE`\n请求，例如:\n\n\n```json\n$ curl -X DELETE \\  \n  https://service.com/apps/1f9b/domains/0fd4\n\nHTTP/1.1 200 OK\nContent-Type: application/json;charset=utf-8\n...\n{\n  \"created_at\": \"2012-01-01T12:00:00Z\",\n  \"hostname\": \"subdomain.example.com\",\n  \"id\": \"01234567-89ab-cdef-0123-456789abcdef\",\n  \"updated_at\": \"2012-01-01T12:00:00Z\"\n}\n```\n\n当请求状态码为202时，不返回所有可用资源，例如：\n\n```\n$ curl -X DELETE \\  \n  https://service.com/apps/1f9b/dynos/05bd\n\nHTTP/1.1 202 Accepted\nContent-Type: application/json;charset=utf-8\n...\n{}\n```\n\n#### 提供资源的(UU)ID\n\n在默认情况给每一个资源一个`id`属性。除非有更好的理由，否则请使用UUID。不要使用那种在服务器上或是资源中不是全局唯一的标识，尤其是自动增长的id。\n\n生成小写的UUID格式 `8-4-4-4-12`，例如：\n\n```json\n\"id\": \"01234567-89ab-cdef-0123-456789abcdef\"\n```\n\n#### 提供标准的时间戳\n\n为资源提供默认的创建时间 `created_at` 和更新时间 `updated_at`，例如:\n\n```json\n{\n  ...\n  \"created_at\": \"2012-01-01T12:00:00Z\",\n  \"updated_at\": \"2012-01-01T13:00:00Z\",\n  ...\n}\n```\n\n有些资源不需要使用时间戳那么就忽略这两个字段。\n\n#### 使用UTC（世界标准时间）时间，用ISO8601进行格式化\n\n仅接受和返回UTC格式的时间。ISO8601格式的数据，例如:\n\n```json\n\"finished_at\": \"2012-01-01T12:00:00Z\"\n```\n\n#### 嵌套外键关系\n\n使用嵌套对象序列化外键关联，例如:\n\n```json\n{\n  \"name\": \"service-production\",\n  \"owner\": {\n    \"id\": \"5d8201b0...\"\n  },\n  // ...\n}\n```\n\n而不是像这样:\n\n```json\n{\n  \"name\": \"service-production\",\n  \"owner_id\": \"5d8201b0...\",\n  ...\n}\n```\n\n这种方式尽可能的把相关联的资源信息内联在一起，而不用改变资源的结构，或者引入更多的顶层字段，例如:\n\n```json\n{\n  \"name\": \"service-production\",\n  \"owner\": {\n    \"id\": \"5d8201b0...\",\n    \"name\": \"Alice\",\n    \"email\": \"alice@heroku.com\"\n  },\n  ...\n}\n```\n\n#### 生成结构化的错误\n\n响应错误的时，生成统一的、结构化的错误信息。包含一个机器可读的错误 `id`，一个人类可读的错误信息（`message`），根据情况可以添加一个`url`来告诉客户端关于这个错误的更多信息以及如何去解决它，例如:\n\n```\nHTTP/1.1 429 Too Many Requests\n```\n\n```json\n{\n  \"id\":      \"rate_limit\",\n  \"message\": \"Account reached its API rate limit.\",\n  \"url\":     \"https://docs.service.com/rate-limits\"\n}\n```\n\n文档化错误信息格式，以及客户端可能遇到的错误信息`id`。\n\n#### 显示频率限制状态\n\n客户端的访问速度限制可以维护服务器的良好状态，保证为其他客户端请求提供高性的服务。你可以使用[token bucket algorithm](http://en.wikipedia.org/wiki/Token_bucket)技术量化请求限制。\n\n为每一个带有`RateLimit-Remaining`响应头的请求，返回预留的请求tokens。\n\n#### 保证响应JSON最小化\n\n请求中多余的空格会增加响应大小，而且现在很多的HTTP客户端都会自己输出可读格式（\"prettify\"）的JSON。所以最好保证响应JSON最小化，例如：\n\n```json\n{\"beta\":false,\"email\":\"alice@heroku.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\"}\n```\n\n而不是这样：\n\n```json\n{\n  \"beta\": false,\n  \"email\": \"alice@heroku.com\",\n  \"id\": \"01234567-89ab-cdef-0123-456789abcdef\",\n  \"last_login\": \"2012-01-01T12:00:00Z\",\n  \"created_at\": \"2012-01-01T12:00:00Z\",\n  \"updated_at\": \"2012-01-01T12:00:00Z\"\n}\n```\n\n你可以提供可选的方式为客户端提供更详细可读的响应，使用查询参数（例如：`?pretty=true`）或者通过`Accept`头信息参数（例如：`Accept: application/vnd.heroku+json; version=3; indent=4;`）。\n\n### 工件（Artifacts）\n\n\n#### 提供机器可读的JSON模式\n\n提供一个机器可读的模式来恰当的表现你的API。使用\n[prmd](https://github.com/interagent/prmd)管理你的模式，并且确保用`prmd verify`验证是有效的。\n\n#### 提供人类可读的文档\n\n提供人类可读的文档让客户端开发人员可以理解你的API。\n\n如果你用prmd创建了一个概要并且按上述要求描述，你可以为所有节点很容易的使用`prmd doc`生成Markdown文档。\n\n除了节点信息，提供一个API概述信息:\n\n* 验证授权，包含如何取得和如何使用token。\n* API稳定及版本管理，包含如何选择所需要的版本。\n* 一般情况下的请求和响应的头信息。\n* 错误的序列化格式。\n* 不同编程语言客户端使用API的例子。\n\n#### 提供可执行的例子\n\n提供可执行的示例让用户可以直接在终端里面看到API的调用情况，最大程度的让这些示例可以简单的使用，以减少用户尝试使用API的工作量。例如:\n\n```\n$ export TOKEN=... # acquire from dashboard\n$ curl -is https://$TOKEN@service.com/users\n```\n\n如果你使用[prmd](https://github.com/interagent/prmd)生成Markdown文档，每个节点都会自动获取一些示例。\n\n#### 描述稳定性\n\n描述您的API的稳定性或是它在各种各样节点环境中的完备性和稳定性，例如：加上 原型版（prototype）/开发版（development）/产品版（production）等标记。\n\n更多关于可能的稳定性和改变管理的方式，查看 [Heroku API compatibility policy](https://devcenter.heroku.com/articles/api-compatibility-policy)\n\n一旦你的API宣布产品正式版本及稳定版本时，不要在当前API版本中做一些不兼容的改变。如果你需要，请创建一个新的版本的API。\n\n\n----------\n\n好久没同步更新了，这么多朋友关注，最近有时间重启这个项目\n\n进微信交流群加我好友：\n\n![image](https://user-images.githubusercontent.com/2317407/75836820-07134080-5dfe-11ea-8cc6-d755f32f486d.png)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FZhangBohan%2Fhttp-api-design-ZH_CN","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FZhangBohan%2Fhttp-api-design-ZH_CN","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FZhangBohan%2Fhttp-api-design-ZH_CN/lists"}