I have been doing some extensive research into this and other REST paging related questions lately and thought it constructive to add some of my findings here. I'm expanding the question a bit to include thoughts on paging as well as the count as they are intimitely related.
Headers
寻呼元数据以响应标头的形式包含在响应中。这种方法的一大好处是响应负载本身就是请求者所要求的实际数据。使对寻呼信息不感兴趣的客户端更容易处理响应。
有一堆(标准和自定义)标头用于返回分页相关信息,包括总计数。
X 总计数
X-Total-Count: 234
这用于some http://support.mashery.com/docs/read/mashery_api/30/Pagination APIs http://liquid-docs.readthedocs.io/en/latest/restapi.html#header-response我在野外发现的。还有NPM 包 https://www.npmjs.com/package/loopback-xtotalcount用于添加对此标头的支持,例如环回。一些articles https://blog.mwaysolutions.com/2014/06/05/10-best-practices-for-better-restful-api/建议也设置此标头。
它经常与Link
header,这是一个非常好的分页解决方案,但缺少总计数信息。
Link
Link: </TheBook/chapter2>;
rel="previous"; title*=UTF-8'de'letztes%20Kapitel,
</TheBook/chapter4>;
rel="next"; title*=UTF-8'de'n%c3%a4chstes%20Kapitel
通过阅读有关该主题的大量内容,我觉得普遍的共识是使用Link header https://www.rfc-editor.org/rfc/rfc5988为客户提供分页链接rel=next
, rel=previous
问题在于它缺少总记录数的信息,这就是为什么许多 API 将其与X-Total-Count
header.
或者,一些 API 和例如这JsonApi http://jsonapi.org/format/#document-links标准,使用Link
格式,但将信息添加到响应信封中而不是标头中。这简化了对元数据的访问(并创建了添加总计数信息的位置),但代价是增加了访问实际数据本身的复杂性(通过添加信封)。
内容范围
Content-Range: items 0-49/234
由一篇名为的博客文章推广范围标题,我选择你(用于分页)! http://otac0n.com/blog/2012/11/21/range-header-i-choose-you.html。作者提出了强有力的理由来使用Range
and Content-Range
用于分页的标题。当我们仔细阅读the https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.16 RFC https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35在这些标头中,我们发现将其含义扩展到字节范围之外实际上是 RFC 预期的并且是明确允许的。当在上下文中使用时items
代替bytes
, Range 标头实际上为我们提供了一种方法,既可以请求特定范围的项目,又可以指示响应项目与总结果的范围相关。此标题还提供了显示总数的好方法。这是一个真正的标准,主要一对一地映射到分页。也是在野外使用 https://github.com/glpi-project/glpi.
Envelope
许多 API,包括来自我们最喜欢的问答网站的一个 https://api.stackexchange.com/docs/wrapper use an envelope,数据的包装器,用于添加有关数据的元信息。还,OData http://www.odata.org and JsonApi http://jsonapi.org/format/#fetching-pagination标准都使用响应信封。
这样做的一大缺点(恕我直言)是处理响应数据变得更加复杂,因为必须在信封中的某个地方找到实际数据。此外,该信封有多种不同的格式,您必须使用正确的一种。很明显,OData 和 JsonApi 的响应信封截然不同,OData 在响应中的多个点混合了元数据。
单独的端点
我认为其他答案已经充分讨论了这一点。我没有调查这么多,因为我同意这样的评论,即这很令人困惑,因为你现在有多种类型的端点。我认为如果每个端点都代表一个资源(集合),那就最好了。
进一步的想法
我们不仅必须传达与响应相关的分页元信息,而且还允许客户端请求特定的页面/范围。有趣的是,也考虑这个方面,最终得到一个连贯的解决方案。在这里我们也可以使用标头(Range
header 看起来很合适),或者其他机制,例如查询参数。有些人主张将结果页面视为单独的资源,这在某些用例中可能有意义(例如/books/231/pages/52
。我最终选择了一系列常用的请求参数,例如pagesize
, page[size]
and limit
等除了支持Range
标头(也作为请求参数)。