REST API设计最佳实践

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 是一种应用程序编程接口, 它符合特定的体系结构约束,如无状态通信和可缓存数据。它不是协议或标准。

虽然 REST API 可以通过多种通信协议进行访问,但最常见的是通过 HTTPS 。

以下准则适用于将通过 Internet 调用的 REST API 端点。

注意:对于通过互联网调用的 REST API,您需要遵循 REST API 身份验证的最佳实践。

使用 JSON 作为输入和响应

REST API 应以 JSON 作为数据传输标准:

  • 接受 JSON 作为请求负载
  • 通过 JSON 发送响应。

JSON 是传输数据的标准,无论是客户端还是服务器端,使用JSON都很方便。

表单比较适合发送文件。但对于文本和数字,我们可以直接在客户端从中获取JSON传输。这样最直接。

在返回JSON时,应该设置响应标头,Content-Type: application/json。不过很多库会自动替我们设置这个标头。

在路径中使用名词而不是动词

我们不应该在端点路径中使用动词。相反,应该使用相关实体的名词,作为路径名。

这是因为我们的 HTTP 请求方法已经具有动词。在我们的 API 终结点路径中使用动词是没有用的。它不传达任何新信息,只是显得冗长,而且,所选动词可能因开发人员的心血来潮而异。例如,有人用“get”,有人用“retrieve”。

所以最好让HTTP GET动词告诉我们和端点的作用。

最常用的方法包括 GETPOSTPUTDELETE

GET 检索资源。
POST 将新数据提交到服务器。
PUT 会更新现有数据。
DELETE 删除数据。
动词映射到 CRUD 操作。比如:

  • GET /articles 获得取文章列表
  • GET /articles/:id 获得某篇文章
  • POST /articles 创建新文章
  • PUT /articles/:id 修改某篇文章
  • DELETE /articles/:id 删除某篇文章

在路径中使用资源嵌套

在实际中,一个资源可能包含其它资源,比如一篇文章可能包含多个评论。我们要设计合理的路径来表示这种嵌套。

注意:REST API 路径中的资源嵌套最好不要照搬数据库的表结构,以免后台数据结构的泄露。

比如,GET /articles/:articleId/comments 得到某篇文章的所有评论。

然而,这种嵌套可能有很多层,尤其在二三层之后,这种结构就会变得很笨拙。这时,可以通过返回对象的URL 来终止这种嵌套。

比如,你想得到某篇文章的某个评论的作者,与其返回某个 articleId 中大而全的结构,不如在 GET /articles/:articleId/comments/:commentId/author 中直接返回 URI {"author": "/users/:userId"}

这个,客户端在拿到地址之后,可以再根据接口,拉取更详细的信息。避免一次查询过于臃肿。

优雅地处理错误 - 返回有效的信息

API 出错可能有多种情况,但我们可以把出错分为两大类:

  • HTTP 协议级出错
  • 上层应用逻辑出错

在实际中,我们应该既返回 HTTP 状态码,也同时返回应用逻辑状态码。

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 加号、减号代表排序顺序

加强安全

  • 使用 TLS/SSL
  • 贯彻最小特权原则 - 普通用户应该无法访问其他用户的信息,不能访问管理员的数据。不同角色的权限要有明确的控制。

使用缓存提高性能

使用缓存有助于提高性能,因为不用每次都查询数据库了。当然,缓存有可能过时,导致调试了生产时的一些问题。使用时要特别小心。

缓存的解决方案有 Redis, Memcache 等。

注意应在标头中使用 Cache-Control 来为使用者提供更详细的指引。

API 版本控制

API 接口改动可能会引起客户端的更改,为了提供更好的兼容性,我们应该提供版本控制。

常见的做法是在 API 路径开头提供 /v1 /v2 这样的前缀来表示API的版本。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值