重构 REST 风格接口中一对多 (Embedding Foreign Entities) 参数设计的疑问

vincenting · 2016年02月20日 · 最后由 vkill 回复于 2016年03月02日 · 8124 次阅读

最近正在进行我自己项目使用的 REST 风格的规范/实现指导,很大部分的参考了参考了 PostgREST 的接口风格。但是遇到了 Embedding Foreign Entities 查询参数的设计问题,示例情景如下:

在用户自己买书的情景下,用户和书籍为一对多关系,现在需要在一个接口中获得满足一定条件的用户列表、同时获得每个用户最近刚买的三本书的需求。

在一些实现里面,是通过 Hypermedia(超媒体)作为其解决方案,在查询 GET: https://api.example.com/v1/readers?order=created_at.desc&status=eq.online 这样的接口时,会返回如下内容:

[
  {
    "meta": {
      "href": "https://api.vincenting.com/v1/readers/a0f0e-ds012e-aff00f"
    },
    "id": "a0f0e-ds012e-aff00f",
    "name": "vincent",
    "created_at": "2015-11-01T17:02:23.212Z",
    "books": {
       "meta": {
         "href": "https://api.vincenting.com/v1/readers/a0f0e-ds012e-aff00f/books"
       }
    }
  }
]

这样使用起来问题不大,但是当 HTTP2 未普及的今天,带来的问题就是多次请求带来的时间问题,以及服务器需要多次进行解析、权限控制等等操作的性能损耗。

于是在 PostgREST 后面的版本里面加入了:Embedding Foreign Entities 的内容,支持这样的情况下的内容返回。基本思路是对 select 参数进行拓展,显示的申明我需要返回例如 books 里面的所有字段,于是请求的地址变成了 https://api.example.com/v1/readers?order=created_at.desc&status=eq.online&select=*,books{*},从而服务器会将整个满足条件的内容返回。

于是,可能是 PostgREST 目前不支持或者目前对 PostgREST 的理解有限,对于这种列表(虽然是内嵌的列表),至少需要满足:

  1. 条件查询(设计的不好的话很难区分到底是给哪个资源的返回列表进行约束);
  2. 分页支持(目前分页支持是尽可能的遵循 RFC 7233 - Hypertext Transfer Protocol (HTTP/1.1): Range Requests。但是该规范规定客户端 不能发起多个资源的 Range 请求,使得很难在 Range 请求头中规定多个资源的分页需求;
  3. 排序需求(目前是在 url 的 查询参数中以关键字 order 来设计的,问题同一)。

最终目前的疑惑是:

  1. 是否有需要考虑这种情况下的查询参数的设计,或者上文中的观点部分内容自身就是错误的
  2. 是否有比较好的相关设计范例指的借鉴

注:目前参考的其他文献:

  1. Design Beautiful REST + JSON APIs
  2. Best Practices for Designing a Pragmatic RESTful API
需要 登录 后方可回复, 如果你还没有账号请 注册新账号