- 标头版本控制
不是追加版本号作为查询字符串参数,而是可以实现指示资源的版本的自定义标头。 此方法需要客户端应用程序将相应标头添加到所有请求,虽然如果省略了版本标头,处理客户端请求的代码可以使用默认值(版本 1)。 下面的示例使用了名为 Custom-Header 的自定义标头**。 此标头的值指示 Web API 的版本。
GET https://adventure-works.com/customers/3 HTTP/1.1 Custom-Header: api-version=1
- 无版本控制:在更改RESTful API时,请以兼容的方式进行更改,并避免生成其他API版本。
说明:多个版本会使理解、测试、维护、发展、操作和发布我们的系统变得非常复杂。
在更改RESTful api时,请以兼容的方式进行更改,并避免生成其他API版本。多个版本可能会显著地复杂化查看、测试、维护、发展、运营和发布系统(补充阅读)。如果无法以兼容的方式更改API,请使用这三种方式:
- 在旧资源变体的基础上创建新资源(变量)
- 创建一个新的服务端点-即一个具有新API的新应用程序(使用新域名)
- 在微服务中创建一个新的API版本,该版本支持与旧API同时支持
Filtering
在参数过滤时通常会为参数值定义数据格式。为了在所有 API 中提供一致的开发者体验并减少学习曲线,API 设计人员必须使用以下扩展巴科斯范式(Extended Backus-Naur Form,简写为“EBNF”)语法的变体来定义这样的语法:
Production = name "=" [ Expression ] ";" ; Expression = Alternative { "|" Alternative } ; Alternative = Term { Term } ; Term = name | TOKEN | Group | Option | Repetition ; Group = "(" Expression ")" ; Option = "[" Expression "]" ; Repetition = "{" Expression "}" ;
注意:
TOKEN
表示在语法之外定义的终端符号。
Example
GET /zoos?id=1001,1002,1003
Long running
有时,POST、PUT、PATCH 或 DELETE 操作可能需要一段时间才能完成。如果需要等待该操作完成后才能向客户端发送响应,可能会造成不可接受的延迟。在这种情况下,请考虑将该操作设置为异步操作。返回 HTTP 状态代码 202(已接受),指示该请求已接受进行处理,但尚未完成。
应公开一个可返回异步请求状态的终结点,使客户端能够通过轮询状态终结点来监视状态。在 202 响应的 Location 标头中包含状态终结点的 URI。例如:
HTTP/1.1 202 Accepted Location: /api/status/12345
如果客户端向此终结点发送 GET 请求,响应中应包含该请求的当前状态。(可选)响应中还可以包含预计完成时间,或者用于取消操作的链接
HTTP/1.1 200 OK Content-Type: application/json { "status":"In progress", "link": { "rel":"cancel", "method":"delete", "href":"/api/status/12345" } }
如果异步操作创建了新资源,则该操作完成后,状态终结点应返回状态代码 303(查看其他)。在 303 响应中,包含一个 Location 标头用于提供新资源的 URI:
HTTP/1.1 303 See Other Location: /api/orders/12345
有关详细信息,请参阅异步请求-回复模式。
Sub-collection
有时,API 需要让客户跨子集执行 List/Search
操作。例如,“API 图书馆”有一组书架,每个书架都有一系列书籍,而客户希望在所有书架上搜索某一本书。在这种情况下,建议在子集合上使用标准 List
,并为父集合指定通配符集合 ID "-"
。对于“API 图书馆”示例,我们可以使用以下 REST API 请求:
GET https://library.googleapis.com/v1/shelves/-/books/{id}
注意:选择
"-"
而不是"*"
的原因是为了避免需要进行 URL 转义。
Action
常用的HTTP动词有下面五个(括号里是对应的SQL命令)。
- GET(SELECT):从服务器取出资源(一项或多项)。
- POST(CREATE):在服务器新建一个资源。
- PUT(UPDATE):在服务器更新资源(客户端提供改变的属性)
- DELETE(DELETE):从服务器删除资源。
对于非标准的操作,以上动词无法无法满足需求,可以在资源上使用“操作”子集合。 动作基本上类似于RPC的消息,用于对资源执行特定操作。 “动作”子集合可以看作是一个命令队列,可以将新的动作发布到该命令队列中,然后由API执行。定义标准动词如下:
- batch:批量操作
- search:搜索操作
GET /zoos:列出所有动物园 POST /zoos:新建一个动物园 GET /zoos/ID:获取某个指定动物园的信息 PUT /zoos/ID:更新某个指定动物园的信息(提供该动物园的全部信息) PATCH /zoos/ID:更新某个指定动物园的信息(提供该动物园的部分信息) DELETE /zoos/ID:删除某个动物园 GET /zoos/ID/animals:列出某个指定动物园的所有动物 DELETE /zoos/ID/animals/ID:删除某个指定动物园的指定动物 GET /zoos/-/action/batch 批量查询 POST /zoos/-/action/batch 批量更新 POST /zoos/-/action/search 搜索
其他
- 对
null
和不存在的属性使用相同的语义
required | nullable | {} | {“example”:null} |
true |
true |
✗ No | ✔ Yes |
false |
true |
✔ Yes | ✔ Yes |
true |
false |
✗ No | ✗ No |
false |
false |
✔ Yes | ✗ No |
- 路径使用 中划线
-
代替 下划线_
;
在搜索引擎中,把中划线当做空格处理,而下划线是被忽略的。使用中划线是对搜索引擎友好的写法
- Example:
/shipment-orders/{shipment-order-id}
- 范围
表示范围的字段应该使用半开区间和命名惯例[start_xxx, end_xxx)
,例如[start_key, end_key)
或[start_time, end_time)
。通常 C ++ STL 库和 Java 标准库会使用半开区间语义。API 应该避免使用其他表示范围的方式,例如(index, count)
或[first, last]
。
总结
完成以上这些,也仅仅是达到REST Level 2,由于Level 3 对于API风格影响不大,暂不涉及。对 HATEOAS 感兴趣,可以参考 Github v3 版本的API。
参考链接
- 架构风格与基于网络应用软件的架构设计
- Google Cloud API guide
- Microsoft API design best practices
- Zalando RESTful API and Event Scheme Guidelines
- OpenAPI-Specification
- Consumer-Centric API Design v0.4.0.pdf
- s3 rest api and post method
- what is hypermedia hypermedia controls hypermedia formats
- Enterprise Integration Using REST
- Thoughts on RESTful API Design
本文作者 : cyningsun
本文地址 : https://www.cyningsun.com/06-29-2020/how-to-write-restful-api.html
版权声明 :本博客所有文章除特别声明外,均采用 CC BY-NC-ND 3.0 CN 许可协议。转载请注明出处!