优秀的 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 的时候有些什么原则?有哪些好的规范和经验可以介绍和分享给大家?欢迎告诉我,我会加到文章中

26861 次点击
所在节点    程序员
98 条回复
cbasil
2020-08-03 09:31:29 +08:00
设计 API 的目的是为了前端好评? api 接口安全和效率都不需要考虑了吗?你去看看阿里,腾讯等大公司的接口文档,有几个是完全按照 REST API 来设计的。
lovedebug
2020-08-03 09:53:26 +08:00
@cbasil 一是对内为了公司内部统一,减少沟通成本。而是针对 public api 与主流统一,减少用户的集成成本。
nig001
2020-08-03 14:43:53 +08:00
不错的
fy
2020-08-04 01:38:35 +08:00
@lovedebug #32

这个我做了,默认 and 操作,请求类似这样:

/api/topic/list/1?time.ge=1577808000&order=time.desc&select=id,title

前端反馈一般,说是不好理解。语言是 python

https://github.com/fy0/slim


问题主要是几处:

1. http header 有限,有的查询条件放不下,其实同时支持提交 body 查询更好些( get 提交 body 是规范允许的,只是很多 http server 选择不解析)

2. 对查询的掌控力度不够。前端提交上来一个请求,说某种情况下希望将某个条件变成 or 查询,这时候做不到。当然这和 orm 还有底层实现有关,这是一个整体设计上的问题。

3. 连表查询比较复杂。

4. 全栈开发会觉得好用,有的纯前端就觉得这是后端偷懒。

所以可能不光是规范问题,还是框架问题,甚至要连同 orm 、表单验证、权限之类做通盘考虑。

@imhxc #44

角色权限 + ACL
sunzhenyucn
2020-08-04 04:42:12 +08:00
请让我默默地 mark 一下
lovedebug
2020-08-04 09:35:07 +08:00
@fy 感谢回复,是的,get 带参数会有这些问题。
一般对于 simple collection items 的 list(GET 方法)操作,我建议用 order,filter, 这样语义清晰,主要实现集合过滤功能。可以尝试在 filter= X OR Y 这样的形式实现 or 操作
我的理解是对于复杂集合(如 logs 等)或通用操作的模糊搜索还是用 POST + custom method,例如 /v1/items/search,除非可以细化复杂集合为若干简单的集合。
主要这个度不好把握。
当然,从实现简单程度来看,所有的 order,filter,projection 都可以定义为用 post 实现。
thtznet
2020-08-04 11:15:03 +08:00
看到 API 和表对应,我就知道不用看下去了,太水了。
jy28520
2020-08-04 11:22:55 +08:00
@KalaSearch 想问下我们现在的业务需要验证用户提交的 SKU 和优惠券是否匹配 请问 URL 应该怎么设计那?
我们会有几条 SKU 和几条优惠券的信息
b0644170fc
2020-08-04 11:36:51 +08:00
根本不需要 rest, get / post 走天下
imhxc
2020-08-04 14:24:18 +08:00
@fy 嗯嗯,ACL 是可以解决刚才提的问题。
但是总感觉 REST API 规范有局限性,自己曾经做过 ERP,会经常出现较为复杂的接口,感觉很难严格遵守 REST API 风格。

比如有一些无法区分上下级关系、获取同一个数据,有的需要用 iD 查,有的需要用 MD5 查,总之,实际业务中各种千奇百怪的需求。

我以前自己写接口用 REST API 写着写着就要精神分裂了。。。😓

也可能是我没理解 REST API 的精髓😅
no1xsyzy
2020-08-05 11:00:25 +08:00
@imhxc #70 除非你能直接塞图灵完备的代码进数据库,不然什么都有局限性
就是 SQL 有时不得不分成两个查询( SELECT ),虽然完全就是数据库里的内容,之后可优化为一次数据库交互包含两个查询(避免传输),但一个(对人脑来说)本来看上去非常简单的东西,不通过逻辑检验竟然无法简化。

实际上 RESTful 不是有局限性,而是它就是局限性本身:通过强加某种限制,将(一次) API 请求类比为对(一项)资源的操作,形成某种直觉映射,来理清思路。要 “改” 到 RESTful,并不是改动 API 就行的,而是整个建模得修改。
有人[谁?](忘了谁)认为其实是启发自 Unix 的文件操作。(所以 WebDAV 是 RESTful 最恰当的应用场景)
imhxc
2020-08-05 11:47:20 +08:00
@no1xsyzy 感谢,涨知识了。
lolizeppelin
2020-08-05 13:13:45 +08:00
这个论坛早就有人说过了

RESTful 是对 sql 的劣质模仿,没法表达的情况多去了
no1xsyzy
2020-08-05 14:54:39 +08:00
@lolizeppelin #73 谁?在哪儿说的?
RESTful sql 劣质模仿 site:v2ex.com 只搜出来你说的话……

从来从来,RESTful 就是个和 SQL 完全相悖的路线
SQL 一直在做得越来越图灵完备,添加各种诡异的、我承认确实像是有那么回事儿的、但其实没有也没关系的功能进去。
RESTful 一直都是那么平铺直叙。谓宾仍然是谓宾,最多用点 HTTP 语义。
“C 是个对 Lisp 的劣质模仿”
lolizeppelin
2020-08-05 15:12:12 +08:00
@no1xsyzy
est 说的 嘿嘿
no1xsyzy
2020-08-05 15:16:09 +08:00
@lolizeppelin #75 @est 在哪说的?
楞是没搜到……
lolizeppelin
2020-08-05 15:17:08 +08:00
@no1xsyzy
当然个别字有出入呗,你找他 233333
est
2020-08-05 16:12:31 +08:00
@lolizeppelin
@no1xsyzy

我也不记得在哪里说的了,但是中心思想是,RESTful 本来是对文件读写的一个 增删改查 的封装,最适合拿来做 WebDAV 之类的工具。然而其他的业务的「动作」很可能无法用这 4 个指令覆盖。就多出来了很多奇葩的指令比如 OPTIONS TRACE PATCH 。。。与其这样,还不如直接根据具体业务在 url 里指定动作名称。比如

POST /api/user/login
POST /api/order/cancel



然后我是明确反对把 URL 里直接嵌入 resource id 作为路径一部分的。比如 GET /myitem/12345/ 这种,RESTful 一时爽,nginx 日志分析火葬场。
no1xsyzy
2020-08-05 18:38:56 +08:00
@est #78 本来指令就随便添加,过分绑定到固定四个指令有点先辈的罪或者思维定势。
我觉得 POST .../login 没什么问题,我的某个工具里面 Login 是类名,将 Login 视为名词形式。
同时我觉得 POST .../order/cancellation 也没什么问题,是订单状态改变。DELETE order 和它是根本上不同的两种行为。如同 rm 一样,DELETE 谓词的使用应当慎之又慎。
一般这类框架会有自己的日志的,不用 nginx 分析日志。而且如果不分 /api/* 的 URL 出来的话,也就是 /static/* 让 nginx 处理,其他都归框架管了。而且看到某 PHP 应用的官方部署教程是关掉 /static/* 的日志的…… 基本上 nginx 日志存在有意义的信息就已经是系统层面的大问题了(比如 uwsgi 挂了)
putaozhenhaochi
2020-08-11 20:28:03 +08:00
老哥这么拼

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

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

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

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

© 2021 V2EX