优秀的 REST API 设计指南

2020-07-29 06:14:50 +08:00
 KalaSearch

这是一篇会长期更新的文章

什么样的 API 设计能被称为优秀当然是一个非常主观的标准,但是还是有一些客观可考量 API 质量的数据,比如

  1. 接了你设计的 API 的前端给好评的比例是多少,还是边接边骂
  2. 如果你的 API 本身就是你的产品的话(比如 Stripe,Algolia 或者 Github 等等),你的用户会对你的 API 好评吗
  3. API 是不是一读即可以清晰地知道,对应接口是做什么的。换句话说,接入 API 时需要的交流时间成本有多高

不管是前端程序员还是后端程序员,都少不了跟 API 打交道。后端需要把 API 设计和实现出来,而前端程序员需要把界面逻辑和 API 接起来,因此对于 REST 的设计规则有一些基本了解,不管你是前端还是后端,都会有很大帮助。

之前在厂里设计了一些还算被广泛使用的 API, 因此我写了这篇文章,结合之前的经验总结了一些要点。希望作为一个参考,可以帮助大家

文章请戳 => 优秀的 REST API 设计指南

当然我想要说明的是,设计 API 在一定范围内是有规律可循的,但是太过抠细节则会陷入无穷无尽地“宗教版”争论中,所以请大家理论讨论。

你们设计 API 的时候有些什么原则?有哪些好的规范和经验可以介绍和分享给大家?欢迎告诉我,我会加到文章中

25733 次点击
所在节点    程序员
98 条回复
Amit
2020-07-30 10:52:53 +08:00
@xuanbg
密码一般都是要做 hash 的,且不能暴露给前端,所以需要对这个字段单独修改,而不能放到完整信息中修改并返回,修改密码是在登录状态下,所以我会设计为 PUT /v1/users/{id}/password (管理员修改用户密码)或 PUT /v1/users/self/password (修改自己的密码),重置密码我理解为非登录状态下修改密码(不确定用户身份),所以我会设计为 PUT /v1/users/password,然后再 body 中提供用户名、验证码等信息。

软删除也是删除,对应用来说如果删除了就是不存在的,应用中不应该能看到,软删除和物理删除同时存在是不合理的,这种情况应该设计一个状态字段区分,而不是使用逻辑删除。
xuanbg
2020-07-30 12:01:16 +08:00
@Amit
修改密码和重置密码我也是一样的处理。在复数形式的资源后面,有时候不但要加动词,还得加属性,以定位到更细一层的资源才行。

我说的软删其实是禁用,只是为了理解方便。业务前端看不到了,也就没得用了。但元数据管理后端应该能看到,毕竟禁用后说不得还会启用。。。硬删当然就是数据灰灰,再也无法恢复的。如果软删用 PUT:/v1/users,那就和修改姓名冲突了。我是这样规划的,修改普通属性 PUT:/v1/users,禁用 PUT:/v1/users/status,删除 DELETE:PUT:/v1/users 。
jorneyr
2020-07-30 16:09:28 +08:00
RESTful 在 URL 里是禁止使用动词的,但是很多时候有的 URL 中用动词来表达很自然,强制使用 RESTful 的风格的话会很难受
imhxc
2020-07-30 18:19:45 +08:00
我一直有个问题,请教下。
在实际业务中,各种需求都有,很难严格遵守 RESTful API,拿文章中的示例来说:

GET /owners/1/pets/ 获取 id 为 1 的主人的所有宠物
1. 如果区分角色怎么办,比如管理员获取 id 为 1 的主人的所有宠物,结果中包含所有状态的宠物;
2. 其他人需要查看 id 为 1 的主人所有宠物,结果中只返回状态为「可公开」的宠物;

这种怎么设计?
codingbody
2020-07-30 18:22:52 +08:00
我有个问题问大家,为什么安全扫描的时候,不准我使用除了 GET 、POST 之外的请求,我认为请求的方式和安全没啥关系吧
DeWhite
2020-07-30 18:59:43 +08:00
那个就一句话,吃屎啦。就是没有主语的,国内的很明显主语省略的句子还有很多。
xcstream
2020-07-30 20:21:36 +08:00
这标题隐含意思就是不 rest 就不优秀(狗头)
KalaSearch
2020-07-31 01:29:46 +08:00
@imhxc 用 ACL 来控制,REST endpoint 没办法控制的
KalaSearch
2020-07-31 01:30:24 +08:00
@DeWhite 你说的是祈使句,祈使句当然可以没有主语(省略了第二人称主语)
forgaoqiang
2020-07-31 12:16:24 +08:00
看了下 Discuz Q,真的几斤,完全的 RESTFUL 风格,patch delete 各种方法都用
grzhan
2020-07-31 13:46:45 +08:00
@lovedebug 我个人觉得关于复杂查询不管是用 $filter 还是直接 POST 自定义方法(如 "_search" )都是可以的,具体看自己场景。
事实上我们项目实际实践中,这种情况还是自定义 POST 方法用的比较多
GavinZZ
2020-07-31 13:52:12 +08:00
??
GavinZZ
2020-07-31 13:52:38 +08:00
还有个叫车满满的。。。工资给开的还算可以 13K+ 14 薪,但是不推荐去,企业文化很奇葩
lovedebug
2020-07-31 14:13:54 +08:00
@grzhan 嗯。$filter 需要写 parser 专门处理,否则会重复造轮子
grzhan
2020-07-31 14:16:34 +08:00
@lovedebug 如果查询场景需求确实很复杂的业务的话,我们会考虑上 GraphQL 的
lovedebug
2020-07-31 14:20:31 +08:00
@grzhan 主要是 GraphQL 对已有产品的 RESTful API 破坏性过大,ROI 也不够高,另外也考虑在微服务和 k8s 中 GraphQL 中心化并不是一个很完美的方案。其实主要的阻力是项目进度和同事。哈哈哈哈
dongxiaoxian
2020-07-31 15:09:26 +08:00
好复杂
ChanKc
2020-07-31 18:57:19 +08:00
@codingbody 没有,但是历史上发生过一些 HTTP server 对 PUT,DELETE 等请求实现不当,导致远程代码执行等漏洞。一些公司就会觉得索性禁了这些请求更好
yixinlove
2020-08-02 19:29:08 +08:00
@KallyDev 好东西
wangxiaoaer
2020-08-03 09:23:35 +08:00
这个帖子很有启发啊,顺便问一下,针对楼上一些老哥们提到的复杂的组合条件查询,如果是基于 spring boot + jpa 的应用,如何优雅的实现呢?

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/693907

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX