├── .DS_Store ├── http-api-设计指南.pdf ├── LICENSE ├── README.md └── http-api-设计指南.html /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cocoajin/http-api-design-ZH_CN/HEAD/.DS_Store -------------------------------------------------------------------------------- /http-api-设计指南.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cocoajin/http-api-design-ZH_CN/HEAD/http-api-设计指南.pdf -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 cocoajin 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # HTTP API 设计指南 2 | > 翻译自 `HTTP API Design Guide` [https://github.com/interagent/http-api-design](https://github.com/interagent/http-api-design) 3 | 4 | ## 前言 5 | 6 | 这篇指南介绍了大量的 http + json 的api设计风格,最初摘录自heroku平台的api设计指引 [Heroku 平台 API 指引](https://devcenter.heroku.com/articles/platform-api-reference). 7 | 8 | 这篇指南除了当前那些API,同时也适用于heroku平台新集成的api,我们希望那些在heroku之外的api设计者也感兴趣! 9 | 10 | 我们的目标是一致性,专注业务逻辑同时避免设计上的空想,我们一直在寻找一种良好的,统一的,显而易见的API设计方式,未必只有一种方式。 11 | 12 | 我们假设你熟悉基本的 http+json api 设计方式,但是,不一定包含在此篇指南里面的所有内容。 13 | 14 | ## 内容 15 | 16 | * [返回合适的状态码](#返回合适的状态码) 17 | * [提供全部可用的资源](#提供全部可用的资源) 18 | * [在请求的body体使用JSON数据](#在请求的body体使用JSON数据) 19 | * [提供资源的唯一标识](#提供资源的唯一标识) 20 | * [提供标准的时间戳](#提供标准的时间戳) 21 | * [使用ISO8601的国际化时间格式](#使用ISO8601的国际化时间格式) 22 | * [使用统一的资源路径](#使用统一的资源路径) 23 | * [路径和属性要用小写字母](#路径和属性要用小写字母) 24 | * [嵌套外键关系](#嵌套外键关系) 25 | * [支持方便的无id间接引用](#支持方便的无id间接引用) 26 | * [构建错误信息](#构建错误信息) 27 | * [支持Etags缓存](#支持Etags缓存) 28 | * [用id来跟踪每次的请求](#用id来跟踪每次的请求) 29 | * [按范围分页](#按范围分页) 30 | * [显示速度限制状态](#显示速度限制状态) 31 | * [指定可接受头信息的版本](#指定可接受头信息的版本) 32 | * [提供机器可读的JSON概要](#提供机器可读的JSON概要) 33 | * [提供人类可读的文档](#提供人类可读的文档) 34 | * [提供可执行的示例](#提供可执行的示例) 35 | * [描述稳定性](#描述稳定性) 36 | * [要求传输通道安全](#要求传输通道安全) 37 | * [使用友好的JSON输出](#使用友好的JSON输出) 38 | 39 | ### 返回合适的状态码 40 | 41 | 为每一次的响应返回合适的HTTP状态码. 成功的HTTP响应应该使用如下的状态码: 42 | 43 | * `200`: `GET`请求成功, 以及`DELETE`或 44 | `PATCH` 同步请求完成 45 | * `201`: `POST` 同步请求完成 46 | * `202`: `POST`, `DELETE`, 或 `PATCH` 异步请求将要完成 47 | * `206`: `GET` 请求成功, 这里只是一部分状态码: 更多 48 | 49 | 对于用户请求的错误情况,及服务器的异常错误情况,请查阅完整的HTTP状态码[HTTP response code spec](http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html)。 50 | 51 | ### 提供全部可用的资源 52 | 53 | 提供全部可显现的资源 (例如. 这个对象的所有属性) 不用考虑全部可能响应的状态码,总是在响应码为200或是201时返回所有可用资源, 包含 `PUT`/`PATCH` 和 `DELETE` 54 | 请求, 例如: 55 | 56 | ``` 57 | $ curl -X DELETE \ 58 | https://service.com/apps/1f9b/domains/0fd4 59 | 60 | HTTP/1.1 200 OK 61 | Content-Type: application/json;charset=utf-8 62 | ... 63 | { 64 | "created_at": "2012-01-01T12:00:00Z", 65 | "hostname": "subdomain.example.com", 66 | "id": "01234567-89ab-cdef-0123-456789abcdef", 67 | "updated_at": "2012-01-01T12:00:00Z" 68 | } 69 | ``` 70 | 71 | 当请求状态码为202时,不返回所有可用资源, 72 | e.g.: 73 | 74 | ``` 75 | $ curl -X DELETE \ 76 | https://service.com/apps/1f9b/dynos/05bd 77 | 78 | HTTP/1.1 202 Accepted 79 | Content-Type: application/json;charset=utf-8 80 | ... 81 | {} 82 | ``` 83 | 84 | ### 在请求的body体使用JSON数据 85 | 86 | 在 `PUT`/`PATCH`/`POST` 请求的body体使用JSON格式数据, 而不是使用 form 表单形式的数据. 这里我们使用JSON格式的body请求创建对称的格式数据, 例如.: 87 | 88 | ``` 89 | $ curl -X POST https://service.com/apps \ 90 | -H "Content-Type: application/json" \ 91 | -d '{"name": "demoapp"}' 92 | 93 | { 94 | "id": "01234567-89ab-cdef-0123-456789abcdef", 95 | "name": "demoapp", 96 | "owner": { 97 | "email": "username@example.com", 98 | "id": "01234567-89ab-cdef-0123-456789abcdef" 99 | }, 100 | ... 101 | } 102 | ``` 103 | 104 | ### 提供资源的唯一标识 105 | 106 | 在默认情况给每一个资源一个`id`属性. 用此作为唯一标识除非你有更好的理由不用.不要使用那种在服务器上或是资源中不是全局唯一的标识,比如自动增长的id标识。 107 | 108 | 返回的唯一标识要用小写字母并加个分割线格式 `8-4-4-4-12`, 例如.: 109 | 110 | ``` 111 | "id": "01234567-89ab-cdef-0123-456789abcdef" 112 | ``` 113 | 114 | ### 提供标准的时间戳 115 | 116 | 提供默认的资源创建时间,更新时间 `created_at` and `updated_at` , 117 | e例如: 118 | 119 | ```json 120 | { 121 | ... 122 | "created_at": "2012-01-01T12:00:00Z", 123 | "updated_at": "2012-01-01T13:00:00Z", 124 | ... 125 | } 126 | ``` 127 | 128 | 这些时间戳可能不适用于某些资源,这种情况下可以忽略省去。 129 | 130 | ### 使用ISO8601的国际化时间格式 131 | 132 | 在接收的返回时间数据时只使用UTC格式. 查阅ISO8601时间格式, 133 | 例如: 134 | 135 | ``` 136 | "finished_at": "2012-01-01T12:00:00Z" 137 | ``` 138 | 139 | ### 使用统一的资源路径 140 | 141 | #### 资源命名 142 | 143 | 使用复数形式为资源命名,而不是在系统中有争议的一个单个资源 (例如,在大多数系统中,给定的用户帐户只有一个). 这种方式保持了特定资源的统一性. 144 | 145 | #### 形为 146 | 147 | 好的末尾展现形式不许要指定特殊的资源形为,在某些情况下,指定特殊的资源的形为是必须的,用一个标准的`actions`前缀去替代他, 清楚的描述他: 148 | 149 | ``` 150 | /resources/:resource/actions/:action 151 | ``` 152 | 153 | 例如. 154 | 155 | ``` 156 | /runs/{run_id}/actions/stop 157 | ``` 158 | 159 | ### 路径和属性要用小写字母 160 | 161 | 使用小写字母并用`-`短线分割路径名字,并且紧跟着主机域名 e.g: 162 | 163 | ``` 164 | service-api.com/users 165 | service-api.com/app-setups 166 | ``` 167 | 168 | 同样属性也要用小写字母, 但是属性名字要用下划线`_`分割,以至于这样在javaScript语言中不用输入引号。 例如.: 169 | 170 | ``` 171 | service_class: "first" 172 | ``` 173 | 174 | ### 嵌套外键关系 175 | 176 | 序列化的外键关系通常建立在一个有嵌套关系的对象之上, 例如.: 177 | 178 | ```json 179 | { 180 | "name": "service-production", 181 | "owner": { 182 | "id": "5d8201b0..." 183 | }, 184 | ... 185 | } 186 | ``` 187 | 188 | 而不是这样 例如: 189 | 190 | ```json 191 | { 192 | "name": "service-production", 193 | "owner_id": "5d8201b0...", 194 | ... 195 | } 196 | ``` 197 | 198 | 这种方式尽可能的把相关联的资源信息内联在一起,而不用改变响应资源的结构,或者展示更高一级的响应区域, 例如: 199 | 200 | ```json 201 | { 202 | "name": "service-production", 203 | "owner": { 204 | "id": "5d8201b0...", 205 | "name": "Alice", 206 | "email": "alice@heroku.com" 207 | }, 208 | ... 209 | } 210 | ``` 211 | 212 | ### 支持方便的无id间接引用 213 | 214 | 在某些情况下,为了方便用户使用接口,在末尾提供用id标识资源,例如,一个用户想到了他在heroku平台app的名字,但是这个app的唯一标识是id,这种情况下,你想让接口通过名字和id都能访问,例如: 215 | 216 | ``` 217 | $ curl https://service.com/apps/{app_id_or_name} 218 | $ curl https://service.com/apps/97addcf0-c182 219 | $ curl https://service.com/apps/www-prod 220 | ``` 221 | 不要只接受使用名字而剔除了使用id。 222 | 223 | ### 构建错误信息 224 | 225 | 在网络请求响应错误的时候,返回统一的,结构化的错误信息。要包含一个机器可读的错误 `id`,一个人类能识别的错误信息 `message`, 根据情况可以添加一个`url` ,告诉客户端关于这个错误的更多信息以及如何去解决它。 226 | 例如: 227 | 228 | ``` 229 | HTTP/1.1 429 Too Many Requests 230 | ``` 231 | 232 | ```json 233 | { 234 | "id": "rate_limit", 235 | "message": "Account reached its API rate limit.", 236 | "url": "https://docs.service.com/rate-limits" 237 | } 238 | ``` 239 | 240 | 把你的错误信息格式文档化,以及这些可能的错误信息`id`s 让客户端能获取到. 241 | 242 | ### 支持Etags缓存 243 | 244 | 在所有请求响应中包含一个`ETag`头,比如,标识出返回资源的指定版本. 用户能够根据他们提供的头信息`If-None-Match`,在随后的请求中检查出那些无效的。 245 | 246 | 247 | ### 用id来跟踪每次的请求 248 | 249 | 在每一个API响应中要包含一个`Request-Id`头信息, 通常用唯一标识UUID. 如果服务器和客户端都打印出他们的`Request-Id`, 这对我们的网络请求调试和跟踪非常有帮助. 250 | 251 | ### 按范围分页 252 | 253 | 对于服务器响应的大量数据我们应该为此分页。 254 | 使用`Content-Range` 头传递分页请求的数据.这里有个例子详细的说明了请求和响应头、状态码,限制条件、排序以及分页处理:[Heroku Platform API on Ranges](https://devcenter.heroku.com/articles/platform-api-reference#ranges). 255 | 256 | ### 显示速度限制状态 257 | 258 | 客户端的访问速度限制可以维护服务器的良好状态,进而为其他客户端请求提供高性的服务.你可以使用[token bucket algorithm](http://en.wikipedia.org/wiki/Token_bucket)技术量化请求限制. 259 | 260 | 为每一个带有`RateLimit-Remaining`响应头的请求,返回预留的请求tokens。 261 | 262 | ### 指定可接受头信息的版本 263 | 264 | 在开始的时候指定API版本,使用`Accepts`头传递版本信息,也可以是一个自定义的内容, 例如: 265 | 266 | ``` 267 | Accept: application/vnd.heroku+json; version=3 268 | ``` 269 | 270 | 最好不要给出一个默认的版本, 而是要求客户端明确指明他们要使用特定的版本. 271 | 272 | ### 减少路径嵌套 273 | 274 | 在一些有父路径/子路径嵌套关系的资源数据模块中, 路径可能有非常深的嵌套关系, 例如: 275 | 276 | ``` 277 | /orgs/{org_id}/apps/{app_id}/dynos/{dyno_id} 278 | ``` 279 | 280 | 推荐在根(root)路径下指定资源来限制路径的嵌套深度。使用嵌套指定范围的资源,例如在下面的情况下,dyno属性app范围下,app属性org范围下: 281 | 282 | ``` 283 | /orgs/{org_id} 284 | /orgs/{org_id}/apps 285 | /apps/{app_id} 286 | /apps/{app_id}/dynos 287 | /dynos/{dyno_id} 288 | ``` 289 | 290 | ### 提供机器可读的JSON概要 291 | 292 | 提供一个机器可读的概要恰当的表现你的API.使用 293 | [prmd](https://github.com/interagent/prmd)管理你的概要, 并且确保用`prmd verify`验证是有效的。 294 | 295 | ### 提供人类可读的文档 296 | 297 | 提供人类可读的文档让客户端开发人员可以理解你的API。 298 | 299 | 如果你用prmd创建了一个概要并且按上述要求描述,你可以很容易的生成所有结节使用`prmd doc`的Markdown文件。 300 | 301 | 除此之在详细信息的结尾,提供一个关于如下信息的API摘要: 302 | 303 | * 验证授权,包含获取及使用验证tokens. 304 | * API 稳定性及版本控制, 包含如何选择所需要的版本. 305 | * 一般的请求和响应头信息. 306 | * 错误信息序列格式. 307 | * 不同语言客户端使用API的例子. 308 | 309 | ### 提供可执行的示例 310 | 311 | 提供可执行的示例让用户可以直接在终端里面看到API的调用情况,最大程度的让这些示例可以逐字的使用,以减少用户尝试使用API的工作量。例如: 312 | 313 | ``` 314 | $ export TOKEN=... # acquire from dashboard 315 | $ curl -is https://$TOKEN@service.com/users 316 | ``` 317 | 318 | 如果你使用[prmd](https://github.com/interagent/prmd)生成Markdown文档, 你会自动获取一些示例在结点处。 319 | 320 | ### 描述稳定性 321 | 322 | 描述您的API的稳定性或是它在各种各样节点环境中的完备性和稳定性 323 | 例如. 带有 原型/开发版/产品 324 | 等标签. 325 | 326 | 更多关于可能的稳定性和改变管理的方式,查看 [Heroku API compatibility policy](https://devcenter.heroku.com/articles/api-compatibility-policy) 327 | 328 | 一旦你的API宣布产品正式版本及稳定版本时, 不要在当前API版本回退做一些不兼容的改变。如果你需要回退做一些不兼容的改变,请创建一个新的版本的API。 329 | 330 | ### 要求传输通道安全 331 | 332 | 要求在传输通道安全的情况下访问API,这点没什么可解释的了. 因为这不值得去争辩在什么时候使用传输通道安全访问API是好的,什么时候是不好的,只需要记住在访问API时,使用安全传输通道就行了。 333 | 334 | ### 使用友好的JSON输出 335 | 336 | 用户在第一次看到你的API使用情况,很可能是在命令行下使用`curl`进行的。友好的输出会让他们非常容易的理解你的API,为好开发者们的方便,打印友好的JSON输出, 例如: 337 | 338 | ```json 339 | { 340 | "beta": false, 341 | "email": "alice@heroku.com", 342 | "id": "01234567-89ab-cdef-0123-456789abcdef", 343 | "last_login": "2012-01-01T12:00:00Z", 344 | "created_at": "2012-01-01T12:00:00Z", 345 | "updated_at": "2012-01-01T12:00:00Z" 346 | } 347 | ``` 348 | 349 | 而不是这样 例如: 350 | 351 | ```json 352 | {"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"} 353 | ``` 354 | 355 | 记住要在每行尾部包含一个换行,这样那些使用终端测试API的输出不会被遮挡住。 356 | 357 | 对于大多数的API友好的响应数据输出总会有更好的表现,你可能受到过不友好打印数据API的影响(例如:非常高的流量占用) 或者是在一些客户端上不能工作 (例如:一个随意编写的程序). 358 | 359 | ### 译者注 360 | - 更新时间:`2014-06-11` 361 | - 好久没更新了... 362 | -------------------------------------------------------------------------------- /http-api-设计指南.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 305 | HTTP API 设计指南 306 | 307 | 308 | 309 |

HTTP API 设计指南

310 | 311 |

翻译自 HTTP API Design Guide https://github.com/interagent/http-api-design

312 | 313 |

前言

314 | 315 |

这篇指南介绍了大量的 http + json 的api设计风格,最初摘录自heroku平台的api设计指引 Heroku 平台 API 指引.

316 | 317 |

这篇指南除了当前那些API,同时也适用于heroku平台新集成的api,我们希望那些在heroku之外的api设计者也感兴趣!

318 | 319 |

我们的目标是一致性,专注业务逻辑同时避免设计上的空想,我们一直在寻找一种良好的,统一的,显而易见的API设计方式,未必只有一种方式。

320 | 321 |

我们假设你熟悉基本的 http+json api 设计方式,但是,不一定包含在此篇指南里面的所有内容。

322 | 323 |

内容

324 | 325 | 349 | 350 | 351 |

返回合适的状态码

352 | 353 |

为每一次的响应返回合适的HTTP状态码. 成功的HTTP响应应该使用如下的状态码:

354 | 355 | 362 | 363 | 364 |

对于用户请求的错误情况,及服务器的异常错误情况,请查阅完整的HTTP状态码HTTP response code spec

365 | 366 |

提供全部可用的资源

367 | 368 |

提供全部可显现的资源 (例如. 这个对象的所有属性) 不用考虑全部可能响应的状态码,总是在响应码为200或是201时返回所有可用资源, 包含 PUT/PATCHDELETE 369 | 请求, 例如:

370 | 371 |
$ curl -X DELETE \  
372 |   https://service.com/apps/1f9b/domains/0fd4
373 | 
374 | HTTP/1.1 200 OK
375 | Content-Type: application/json;charset=utf-8
376 | ...
377 | {
378 |   "created_at": "2012-01-01T12:00:00Z",
379 |   "hostname": "subdomain.example.com",
380 |   "id": "01234567-89ab-cdef-0123-456789abcdef",
381 |   "updated_at": "2012-01-01T12:00:00Z"
382 | }
383 | 
384 | 385 |

当请求状态码为202时,不返回所有可用资源, 386 | e.g.:

387 | 388 |
$ curl -X DELETE \  
389 |   https://service.com/apps/1f9b/dynos/05bd
390 | 
391 | HTTP/1.1 202 Accepted
392 | Content-Type: application/json;charset=utf-8
393 | ...
394 | {}
395 | 
396 | 397 |

在请求的body体使用JSON数据

398 | 399 |

PUT/PATCH/POST 请求的body体使用JSON格式数据, 而不是使用 form 表单形式的数据. 这里我们使用JSON格式的body请求创建对称的格式数据, 例如.:

400 | 401 |
$ curl -X POST https://service.com/apps \
402 |     -H "Content-Type: application/json" \
403 |     -d '{"name": "demoapp"}'
404 | 
405 | {
406 |   "id": "01234567-89ab-cdef-0123-456789abcdef",
407 |   "name": "demoapp",
408 |   "owner": {
409 |     "email": "username@example.com",
410 |     "id": "01234567-89ab-cdef-0123-456789abcdef"
411 |   },
412 |   ...
413 | }
414 | 
415 | 416 |

提供资源的唯一标识

417 | 418 |

在默认情况给每一个资源一个id属性. 用此作为唯一标识除非你有更好的理由不用.不要使用那种在服务器上或是资源中不是全局唯一的标识,比如自动增长的id标识。

419 | 420 |

返回的唯一标识要用小写字母并加个分割线格式 8-4-4-4-12, 例如.:

421 | 422 |
"id": "01234567-89ab-cdef-0123-456789abcdef"
423 | 
424 | 425 |

提供标准的时间戳

426 | 427 |

提供默认的资源创建时间,更新时间 created_at and updated_at , 428 | e例如:

429 | 430 |

json 431 | { 432 | ... 433 | "created_at": "2012-01-01T12:00:00Z", 434 | "updated_at": "2012-01-01T13:00:00Z", 435 | ... 436 | } 437 |

438 | 439 |

这些时间戳可能不适用于某些资源,这种情况下可以忽略省去。

440 | 441 |

使用ISO8601的国际化时间格式

442 | 443 |

在接收的返回时间数据时只使用UTC格式. 查阅ISO8601时间格式, 444 | 例如:

445 | 446 |
"finished_at": "2012-01-01T12:00:00Z"
447 | 
448 | 449 |

使用统一的资源路径

450 | 451 |

资源命名

452 | 453 |

使用复制形式为资源命名,而不是在系统中有争议的一个单个资源 (例如,在大多数系统中,给定的用户帐户只有一个). 这种方式保持了特定资源的统一性.

454 | 455 |

形为

456 | 457 |

好的末尾展现形式不许要指定特殊的资源形为,在某些情况下,指定特殊的资源的形为是必须的,用一个标准的actions前缀去替代他, 清楚的描述他:

458 | 459 |
/resources/:resource/actions/:action
460 | 
461 | 462 |

例如.

463 | 464 |
/runs/{run_id}/actions/stop
465 | 
466 | 467 |

路径和属性要用小写字母

468 | 469 |

使用小写字母并用-短线分割路径名字,并且紧跟着主机域名 e.g:

470 | 471 |
service-api.com/users
472 | service-api.com/app-setups
473 | 
474 | 475 |

同样属性也要用小写字母, 但是属性名字要用下划线_分割,以至于这样在javaScript语言中不用输入引号。 例如.:

476 | 477 |
service_class: "first"
478 | 
479 | 480 |

嵌套外键关系

481 | 482 |

序列化的外键关系通常建立在一个有嵌套关系的对象之上, 例如.:

483 | 484 |

json 485 | { 486 | "name": "service-production", 487 | "owner": { 488 | "id": "5d8201b0..." 489 | }, 490 | ... 491 | } 492 |

493 | 494 |

而不是这样 例如:

495 | 496 |

json 497 | { 498 | "name": "service-production", 499 | "owner_id": "5d8201b0...", 500 | ... 501 | } 502 |

503 | 504 |

这种方式尽可能的把相关联的资源信息内联在一起,而不用改变响应资源的结构,或者展示更高一级的响应区域, 例如:

505 | 506 |

json 507 | { 508 | "name": "service-production", 509 | "owner": { 510 | "id": "5d8201b0...", 511 | "name": "Alice", 512 | "email": "alice@heroku.com" 513 | }, 514 | ... 515 | } 516 |

517 | 518 |

支持方便的无id间接引用

519 | 520 |

在某些情况下,为了方便用户使用接口,在末尾提供用id标识资源,例如,一个用户想到了他在heroku平台app的名字,但是这个app的唯一标识是id,这种情况下,你想让接口通过名字和id都能访问,例如:

521 | 522 |
$ curl https://service.com/apps/{app_id_or_name}
523 | $ curl https://service.com/apps/97addcf0-c182
524 | $ curl https://service.com/apps/www-prod
525 | 
526 | 527 |

不要只接受使用名字而剔除了使用id。

528 | 529 |

构建错误信息

530 | 531 |

在网络请求响应错误的时候,返回统一的,结构化的错误信息。要包含一个机器可读的错误 id,一个人类能识别的错误信息 message, 根据情况可以添加一个url ,告诉客户端关于这个错误的更多信息以及如何去解决它。 532 | 例如:

533 | 534 |
HTTP/1.1 429 Too Many Requests
535 | 
536 | 537 |

json 538 | { 539 | "id": "rate_limit", 540 | "message": "Account reached its API rate limit.", 541 | "url": "https://docs.service.com/rate-limits" 542 | } 543 |

544 | 545 |

把你的错误信息格式文档化,以及这些可能的错误信息ids 让客户端能获取到.

546 | 547 |

支持Etags缓存

548 | 549 |

在所有请求响应中包含一个ETag头,比如,标识出返回资源的指定版本. 用户能够根据他们提供的头信息If-None-Match,在随后的请求中检查出那些无效的。

550 | 551 |

用id来跟踪每次的请求

552 | 553 |

在每一个API响应中要包含一个Request-Id头信息, 通常用唯一标识UUID. 如果服务器和客户端都打印出他们的Request-Id, 这对我们的网络请求调试和跟踪非常有帮助.

554 | 555 |

按范围分页

556 | 557 |

对于服务器响应的大量数据我们应该为此分页。 558 | 使用Content-Range 头传递分页请求的数据.这里有个例子详细的说明了请求和响应头、状态码,限制条件、排序以及分页处理:Heroku Platform API on Ranges.

559 | 560 |

显示速度限制状态

561 | 562 |

客户端的访问速度限制可以维护服务器的良好状态,进而为其他客户端请求提供高性的服务.你可以使用token bucket algorithm技术量化请求限制.

563 | 564 |

为每一个带有RateLimit-Remaining响应头的请求,返回预留的请求tokens。

565 | 566 |

指定可接受头信息的版本

567 | 568 |

在开始的时候指定API版本,使用Accepts头传递版本信息,也可以是一个自定义的内容, 例如:

569 | 570 |
Accept: application/vnd.heroku+json; version=3
571 | 
572 | 573 |

最好不要给出一个默认的版本, 而是要求客户端明确指明他们要使用特定的版本.

574 | 575 |

减少路径嵌套

576 | 577 |

在一些有父路径/子路径嵌套关系的资源数据模块中, 路径可能有非常深的嵌套关系, 例如:

578 | 579 |
/orgs/{org_id}/apps/{app_id}/dynos/{dyno_id}
580 | 
581 | 582 |

推荐在根(root)路径下指定资源来限制路径的嵌套深度。使用嵌套指定范围的资源,例如在下面的情况下,dyno属性app范围下,app属性org范围下:

583 | 584 |
/orgs/{org_id}
585 | /orgs/{org_id}/apps
586 | /apps/{app_id}
587 | /apps/{app_id}/dynos
588 | /dynos/{dyno_id}
589 | 
590 | 591 |

提供机器可读的JSON概要

592 | 593 |

提供一个机器可读的概要恰当的表现你的API.使用 594 | prmd管理你的概要, 并且确保用prmd verify验证是有效的。

595 | 596 |

提供人类可读的文档

597 | 598 |

提供人类可读的文档让客户端开发人员可以理解你的API。

599 | 600 |

如果你用prmd创建了一个概要并且按上述要求描述,你可以很容易的生成所有结节使用prmd doc的Markdown文件。

601 | 602 |

除此之在详细信息的结尾,提供一个关于如下信息的API摘要:

603 | 604 | 611 | 612 | 613 |

提供可执行的示例

614 | 615 |

提供可执行的示例让用户可以直接在终端里面看到API的调用情况,最大程度的让这些示例可以逐字的使用,以减少用户尝试使用API的工作量。例如:

616 | 617 |
$ export TOKEN=... # acquire from dashboard
618 | $ curl -is https://$TOKEN@service.com/users
619 | 
620 | 621 |

如果你使用prmd生成Markdown文档, 你会自动获取一些示例在结点处。

622 | 623 |

描述稳定性

624 | 625 |

描述您的API的稳定性或是它在各种各样节点环境中的完备性和稳定性 626 | 例如. 带有 原型/开发版/产品 627 | 等标签.

628 | 629 |

更多关于可能的稳定性和改变管理的方式,查看 Heroku API compatibility policy

630 | 631 |

一旦你的API宣布产品正式版本及稳定版本时, 不要在当前API版本回退做一些不兼容的改变。如果你需要回退做一些不兼容的改变,请创建一个新的版本的API。

632 | 633 |

要求传输通道安全

634 | 635 |

要求在传输通道安全的情况下访问API,这点没什么可解释的了. 因为这不值得去争辩在什么时候使用传输通道安全访问API是好的,什么时候是不好的,只需要记住在访问API时,使用安全传输通道就行了。

636 | 637 |

使用友好的JSON输出

638 | 639 |

用户在第一次看到你的API使用情况,很可能是在命令行下使用curl进行的。友好的输出会让他们非常容易的理解你的API,为好开发者们的方便,打印友好的JSON输出, 例如:

640 | 641 |

json 642 | { 643 | "beta": false, 644 | "email": "alice@heroku.com", 645 | "id": "01234567-89ab-cdef-0123-456789abcdef", 646 | "last_login": "2012-01-01T12:00:00Z", 647 | "created_at": "2012-01-01T12:00:00Z", 648 | "updated_at": "2012-01-01T12:00:00Z" 649 | } 650 |

651 | 652 |

而不是这样 例如:

653 | 654 |

json 655 | {"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"} 656 |

657 | 658 |

记住要在每行尾部包含一个换行,这样那些使用终端测试API的输出不会被遮挡住。

659 | 660 |

对于大多数的API友好的响应数据输出总会有更好的表现,你可能受到过不友好打印数据API的影响(例如:非常高的流量占用) 或者是在一些客户端上不能工作 (例如:一个随意编写的程序).

661 | 662 |

译者注

663 | 664 | 669 | 670 | 671 | --------------------------------------------------------------------------------