https://stackoverflow.blog/2020/03/02/best-practices-for-rest-api-design/
REST API 是最常见的 Web 服务类型之一。浏览器、应用程序等各种客户端 都可以通过 REST API与服务器通信。
正确设计 REST API 非常重要, 我们要考虑 REST API 的安全性、性能和易用性。
REST API 是一种应用程序编程接口, 它符合特定的体系结构约束,如无状态通信和可缓存数据。它不是协议或标准。
虽然 REST API 可以通过多种通信协议进行访问,但最常见的是通过 HTTPS 。
以下准则适用于将通过 Internet 调用的 REST API 端点。
注意:对于通过互联网调用的 REST API,您需要遵循 REST API 身份验证的最佳实践。
REST API 应以 JSON 作为数据传输标准:
JSON 是传输数据的标准,无论是客户端还是服务器端,使用JSON都很方便。
表单比较适合发送文件。但对于文本和数字,我们可以直接在客户端从中获取JSON传输。这样最直接。
在返回JSON时,应该设置响应标头,Content-Type: application/json
。不过很多库会自动替我们设置这个标头。
我们不应该在端点路径中使用动词。相反,应该使用相关实体的名词,作为路径名。
这是因为我们的 HTTP 请求方法已经具有动词。在我们的 API 终结点路径中使用动词是没有用的。它不传达任何新信息,只是显得冗长,而且,所选动词可能因开发人员的心血来潮而异。例如,有人用“get”,有人用“retrieve”。
所以最好让HTTP GET动词告诉我们和端点的作用。
最常用的方法包括 GET
、POST
、PUT
和 DELETE
。
GET
检索资源。
POST
将新数据提交到服务器。
PUT
会更新现有数据。
DELETE
删除数据。
动词映射到 CRUD 操作。比如:
在实际中,一个资源可能包含其它资源,比如一篇文章可能包含多个评论。我们要设计合理的路径来表示这种嵌套。
注意:REST API 路径中的资源嵌套最好不要照搬数据库的表结构,以免后台数据结构的泄露。
比如,GET /articles/:articleId/comments 得到某篇文章的所有评论。
然而,这种嵌套可能有很多层,尤其在二三层之后,这种结构就会变得很笨拙。这时,可以通过返回对象的URL 来终止这种嵌套。
比如,你想得到某篇文章的某个评论的作者,与其返回某个 articleId 中大而全的结构,不如在 GET /articles/:articleId/comments/:commentId/author
中直接返回 URI {"author": "/users/:userId"}
这个,客户端在拿到地址之后,可以再根据接口,拉取更详细的信息。避免一次查询过于臃肿。
API 出错可能有多种情况,但我们可以把出错分为两大类:
在实际中,我们应该既返回 HTTP 状态码,也同时返回应用逻辑状态码。
HTTP 返回码通常是标准的,而应用逻辑状态码需要我们自己约定。
常见的 HTTP 状态码包括:
200 OK
- HTTP 请求正常400 BAD REQUEST
- 请求的参数格式错误401 UNAUTHORIZED
- 认证未通过(比如用户名密码错,导致不能通过认证)403 FORBBIDEN
- 没有授权404 NOT FOUND
- 找不到资源。注意,有的电信运营商很讨厌,他们劫持 HTTP 404——反正你也找不到,不如我来插播一条广告…500 INTERNAL SERVER ERROR
- 通用的服务器内部错误502 BAD GATEWAY
- 上游服务出错503 SERVICE UNAVAILABLE
- 服务不可用除了返回 HTTP 状态码外,我们还应在返回内容中增加 err 部分,更细致地返回/出错状态信息。
比如,数据库连接失败:
{
"status": 502,
"err": {
"code": 502001,
"msg": "后台数据库连接失败"
},
"data": {
}
}
如果正常:
{
"status": 200,
"err": {
"code": 0,
"msg": "",
},
"data": {
正常的返回数据
}
REST API 背后的数据可能非常大,我们需要提效分页和筛选功能,以提高效率。
比如:/employees?lastName=Smith&age=30&page=2
或者:/aritcles?sort=+author, -datepublished
加号、减号代表排序顺序
使用缓存有助于提高性能,因为不用每次都查询数据库了。当然,缓存有可能过时,导致调试了生产时的一些问题。使用时要特别小心。
缓存的解决方案有 Redis, Memcache 等。
注意应在标头中使用 Cache-Control 来为使用者提供更详细的指引。
API 接口改动可能会引起客户端的更改,为了提供更好的兼容性,我们应该提供版本控制。
常见的做法是在 API 路径开头提供 /v1 /v2 这样的前缀来表示API的版本。