最近我一直在对这个问题和其他与 REST 分页相关的问题进行广泛的研究,并认为在这里添加我的一些发现是有建设性的。我将这个问题扩大了一点,以包括关于分页的想法以及它们密切相关的计数。
标头
分页元数据以响应标头的形式包含在响应中。这种方法的最大好处是响应负载本身就是请求者请求的实际数据。使对寻呼信息不感兴趣的客户端更容易处理响应。
有一堆(标准和自定义)标头用于返回与分页相关的信息,包括总数。
X-总计数
X-Total-Count: 234
这用于我在野外发现的一些 API 。还有一些NPM 包用于添加对该标头的支持,例如 Loopback。有些文章也建议设置此标头。
它经常与Link
header结合使用,这是一个非常好的分页解决方案,但缺少总计数信息。
关联
Link: </TheBook/chapter2>;
rel="previous"; title*=UTF-8'de'letztes%20Kapitel,
</TheBook/chapter4>;
rel="next"; title*=UTF-8'de'n%c3%a4chstes%20Kapitel
我觉得,通过阅读很多关于这个主题的内容,普遍的共识是使用Link
标题rel=next
为使用等的客户端提供分页链接rel=previous
。这样做的问题是它缺少总记录数的信息,即为什么许多 API 将其与X-Total-Count
标头结合在一起。
或者,某些 API (例如JsonApi标准)使用该Link
格式,但将信息添加到响应信封而不是标头中。这以增加访问实际数据本身的复杂性(通过添加信封)为代价简化了对元数据的访问(并创建了一个添加总计数信息的位置)。
内容范围
Content-Range: items 0-49/234
由一篇名为Range header 的博客文章推广,我选择你(用于分页)!. 作者为使用Range
和Content-Range
标头进行分页提供了强有力的理由。当我们仔细阅读有关这些标头的 RFC时,我们发现将它们的含义扩展到字节范围之外实际上是 RFC 预期的,并且是明确允许的。当用于items
代替的上下文中时bytes
, Range 标头实际上为我们提供了一种方法来请求特定范围的项目并指示响应项目涉及的总结果范围。此标题还提供了一种显示总数的好方法。它是一个真正的标准,主要将一对一映射到分页。它也用于野外。
信封
许多 API,包括我们最喜欢的问答网站中的API,都使用信封,即数据的包装器,用于添加有关数据的元信息。此外,OData和JsonApi标准都使用响应信封。
这样做的最大缺点(恕我直言)是处理响应数据变得更加复杂,因为必须在信封中的某处找到实际数据。该信封还有许多不同的格式,您必须使用正确的格式。很明显,来自 OData 和 JsonApi 的响应信封完全不同,OData 在响应的多个点混合在元数据中。
单独的端点
我认为这已经在其他答案中得到了足够的覆盖。我没有进行太多调查,因为我同意这令人困惑的评论,因为您现在有多种类型的端点。我认为最好每个端点都代表一个(集合)资源。
进一步的想法
我们不仅要传达与响应相关的分页元信息,还允许客户端请求特定的页面/范围。有趣的是,还关注这方面以最终得出一个连贯的解决方案。这里我们也可以使用 headers(Range
header 似乎很合适),或者其他机制,例如查询参数。有些人主张将结果页面视为单独的资源,这在某些用例中可能是有意义的(例如/books/231/pages/52
。除了支持标头pagesize
(page[size]
以及作为请求参数以及)。limit
Range