我最近一直在对这个问题和其他与 REST 分页相关的问题进行广泛的研究,并认为在这里添加我的一些发现是有建设性的。我将问题扩大了一点,以包括对分页的想法以及它们密切相关的计数。
标题
分页元数据以响应标头的形式包含在响应中。这种方法的最大好处是响应负载本身就是请求者请求的实际数据。使对寻呼信息不感兴趣的客户更容易处理响应。
有一堆(标准和自定义)标头用于返回分页相关信息,包括总数。
X-总计数
X-Total-Count: 234
这个用在someAPIs我在野外发现的。还有NPM packages 用于添加对此标头的支持,例如环回。一些articles 建议也设置此标头。
它经常与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 header 向使用rel=next、rel=previous 等的客户端提供分页链接。问题在于它缺少总共有多少条记录的信息,这就是为什么许多 API 将其与 X-Total-Count 标头结合在一起的原因。
或者,一些 API 和例如JsonApi 标准,使用Link 格式,但将信息添加到响应信封而不是标题中。这简化了对元数据的访问(并创建了一个添加总计数信息的位置),但代价是增加了访问实际数据本身的复杂性(通过添加信封)。
内容范围
Content-Range: items 0-49/234
由名为Range header, I choose you (for pagination)! 的博客文章推广。作者为使用Range 和Content-Range 标头进行分页提供了强有力的案例。当我们仔细阅读这些标头上的 the RFC 时,我们发现将它们的含义扩展到字节范围之外实际上是 RFC 预期的,并且是明确允许的。当在items 而不是bytes 的上下文中使用时,Range 标头实际上为我们提供了一种方法来请求特定范围的项目并指示响应项目涉及的总结果的范围。此标题还提供了一种显示总数的好方法。它是一个真正的标准,主要将一对一映射到分页。也是used in the wild。
信封
包括the one from our favorite Q&A website 在内的许多API 都使用信封,这是一种数据包装器,用于添加有关数据的元信息。此外,OData 和 JsonApi 标准都使用响应信封。
这样做的最大缺点(恕我直言)是处理响应数据变得更加复杂,因为必须在信封中的某处找到实际数据。该信封还有许多不同的格式,您必须使用正确的格式。很明显,来自 OData 和 JsonApi 的响应信封大相径庭,OData 在响应中的多个点混合在元数据中。
单独的端点
我认为其他答案已经对此进行了足够的介绍。我没有进行太多调查,因为我同意 cmets 的观点,因为您现在有多种类型的端点,因此这很令人困惑。我认为最好每个端点都代表一个(集合)资源。
进一步的想法
我们不仅要传达与响应相关的分页元信息,还允许客户端请求特定的页面/范围。有趣的是,还关注这方面以最终得出一个连贯的解决方案。在这里我们也可以使用标头(Range 标头似乎非常合适),或其他机制,例如查询参数。有些人主张将结果页面视为单独的资源,这在某些用例中可能是有意义的(例如/books/231/pages/52。我最终选择了一系列经常使用的请求参数,例如pagesize、page[size] 和limit除了支持 Range 标头(以及作为请求参数)之外,等等。