归类到“瞎扯淡”话题,实际上是想吐槽一些比较纠结的地方。
我在公司负责后端 API 开发,按照标准的 RESTful 规范封装好接口,然后发现了一些跟前端(Android、iOS)矛盾的地方。比如:
/api/v1/users/{id}/stories
,把参数放在 URI 中,我个人认为这比单独在 URI 之后拼接参数?id=xx
要好的多,不仅仅是因为符合 RESTful 规范,也更方组织关系层级更为复杂的 URL。然而前端会有人吐槽,为何不用参数传,为何讲 id 写在 URL 里,这样不方便写请求 URL(balabala...)。尤其对于第一种情况,我私下问过一些朋友,在他们的团队中也有不同程度的体现。
所以我想了解一下,做 API 一定要按照 RESTful 规范来做么?这样的规范对于前端开发究竟是否方便、合理呢?大家是怎么解决这种矛盾的呢?
当然不一定啦,但如果你使用 RESTful,就建议尽量按照 RESTful 的规范进行设计,如果你设计是规范的,前端并不会麻烦的,有时候就是前端偷懒,P.S. 如果可以建议也尝试一下客户端或者前端的开发,这有帮助于设计 API 并且可以在技术层面反驳前端或者客户端提出的不合理要求~
#8 楼 @pengedy 推荐使用 Swagger 来写 API 文档,我自己一个项目的文档可以参考一下:http://mock-api.daza.io/docs/
前阵子我也写了一阵子 API,能按照 RESTful 规范来的场景,还是尽量按照规范执行。但我觉得完全按照 RESTful 的规范来执行,也是很难的。
例如你说的场景 1,如果完全按照 RESTful 拆分出来,原本前端同学发一个 HTTP 请求就可以完成了,那变成要发多个 HTTP 请求。HTTP 请求又比较耗时,会拖慢页面加载时间。
再比如批量插入场景,RESTful 并没有批量插入的规范,如果严格按照 RESTful 来,只提供插入单条数据的接口,那无疑很耗时。
这个没有绝对,如果能推行 RESTful 最好. 不用 RESTful 也有示例。比如 Discourse ,完全的前后端分离论坛系统,每个页面一个接口,比如关于页接口,不但返回页面数据,也返回相关的管理员数据。https://meta.discourse.org/about.json 这样就不像 RESTful 风格的接口,有可能一个页面要调用 4~5 接口。
能遵照 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 这样的场景,筛选条件是不定的。