瞎扯淡 到底如何做 HTTP API?

pengedy · 2016年08月30日 · 最后由 luax 回复于 2016年08月31日 · 4166 次阅读

归类到“瞎扯淡”话题,实际上是想吐槽一些比较纠结的地方。

我在公司负责后端 API 开发,按照标准的 RESTful 规范封装好接口,然后发现了一些跟前端(Android、iOS)矛盾的地方。比如:

  1. 如果考虑前端开发的方便,每个页面访问多个资源,这些资源应该被整合在同一个 API 中(高耦合);但按照 RESTful 的规范,每个资源都是相互独立的(低耦合)。
  2. 关于 URL,比如/api/v1/users/{id}/stories,把参数放在 URI 中,我个人认为这比单独在 URI 之后拼接参数?id=xx要好的多,不仅仅是因为符合 RESTful 规范,也更方组织关系层级更为复杂的 URL。然而前端会有人吐槽,为何不用参数传,为何讲 id 写在 URL 里,这样不方便写请求 URL(balabala...)。

尤其对于第一种情况,我私下问过一些朋友,在他们的团队中也有不同程度的体现。

所以我想了解一下,做 API 一定要按照 RESTful 规范来做么?这样的规范对于前端开发究竟是否方便、合理呢?大家是怎么解决这种矛盾的呢?

其实就是前端懒,不想学 restful,不想多写两行代码做个 url 生成器。对于这种人,我的建议是,迁就他,顺着他,把他培养成一个大傻逼。

2 楼 已删除

#2 楼 @pengedy 那就多教育咯,不过这很难。

#2 楼 @111 我脾气差... 不过还是先耐心点吧

#3 楼 @pengedy 很快这点耐心就会用完的。

#5 楼 @111 到时候再说了。。

当然不一定啦,但如果你使用 RESTful,就建议尽量按照 RESTful 的规范进行设计,如果你设计是规范的,前端并不会麻烦的,有时候就是前端偷懒,P.S. 如果可以建议也尝试一下客户端或者前端的开发,这有帮助于设计 API 并且可以在技术层面反驳前端或者客户端提出的不合理要求~

#7 楼 @lijy91 正打算这么做

#8 楼 @pengedy 推荐使用 Swagger 来写 API 文档,我自己一个项目的文档可以参考一下:http://mock-api.daza.io/docs/

#8 楼 @lijy91 我是新来这家公司的,最近在赶上线,上线之后整这些。

前阵子我也写了一阵子 API,能按照 RESTful 规范来的场景,还是尽量按照规范执行。但我觉得完全按照 RESTful 的规范来执行,也是很难的。

例如你说的场景 1,如果完全按照 RESTful 拆分出来,原本前端同学发一个 HTTP 请求就可以完成了,那变成要发多个 HTTP 请求。HTTP 请求又比较耗时,会拖慢页面加载时间。

再比如批量插入场景,RESTful 并没有批量插入的规范,如果严格按照 RESTful 来,只提供插入单条数据的接口,那无疑很耗时。

这个没有绝对,如果能推行 RESTful 最好. 不用 RESTful 也有示例。比如 Discourse ,完全的前后端分离论坛系统,每个页面一个接口,比如关于页接口,不但返回页面数据,也返回相关的管理员数据。https://meta.discourse.org/about.json 这样就不像 RESTful 风格的接口,有可能一个页面要调用 4~5 接口。

#12 楼 @cxh116 嗯这个道理跟我举的例子是一样的,感谢。

@lijy91 API 设计阶段,RAML 比 Swagger 要好

#14 楼 @vkill 我看了一下,是好东西,感谢!

16 楼 已删除

是不是没有提供可视化文档?restful 最好理解了,配合好的文档,不应该有这样的问题才是。

能遵照 RESTful 就尽量遵照,但不要偏执于一切都 RESTful。API 设计主要是保持 resource 的细粒度。方便前端组合重用。那种一个 API 请求满足一个页面需求的看起来对前端简单,其实是最坑的方案,很容易变成同一个 resource 根据不同页面要写多个 API 的情况。所以一开始就不要这么做。

另外很多人忽略的一点是 relationship,这点是 RESTful 并没有仔细考虑的问题,很多是做成返回 xxx_id 或者直接嵌套的结构。在 relationship 比较复杂的情况下也很容易坑。如果业务场景确实复杂,可以考虑 JSON API 规范,至少可以借鉴一部分,比如它的状态码设定,可以省很多琐碎的决策。API 开发的很多部分都是体力活。

最后说一个例子,我最近的项目是用的 JSON API 的 response 结构(只用了 response,其他保持 RESTful),一是需要有一个标准化和扁平化的 response 方便配合 Redux。这样一套 deserialize 的代码就可以处理多种 resource 的数据转换逻辑,不用针对每个 API 或 resource 写特殊的转换逻辑(尤其是有 relationship 的情况)。二是可以用 compound document 加载额外的数据,类似 ActiveRecord 的 include/preload,增加 API 的灵活性。

第一个问题:个人观点,不一定符合 restfull 规范,resource 定义可以更灵活一点,同样的 resource,可以增加定语来适应不同的场景。而批量的场景,可以在 post 或 put 中兼容. 不建议 API 按页面来定义,有时候一个页面需要请求 2-3 个接口,有极小的性能损失,但是跟语义清晰,扩展性这些优点比起来,可以接受. 第二个问题:有 restful 规范是好的,好处是,这个规范不用培训.url 的构建,实在不是问题。

不过我们做的时候没太遵循 restful 规范,为了简单,也没有用/api/v1/users/{id}/stories 这样的方式,所以也没遇到什么障碍。对于 url 的方式,我们也是更倾向于使用?id=xxx&name=xxx 这样的方式。这样的方式好处非常明显,使用 key value 的方式,可读性比较好 (不需要查文档),扩展性也比较好,比如 search 这样的场景,筛选条件是不定的。

需要 登录 后方可回复, 如果你还没有账号请 注册新账号