上下文:假设我们要定期检索给定用户的加星标存储库的完整列表(每天、每小时或几分钟)。
至少有两种方法可以做到这一点:
执行 GET 到 https://api.github.com/users/evereq/starred 并在“Link”响应标头中使用带有 rel='next' 的 URL 来获取下一页 URL(我们应该这样做,直到我们得到没有“下一页”响应,意味着我们到达了结尾)。似乎这是推荐的方法(由 GitHub 提供)。
使用 GET 迭代“page”参数(从 1 到无限)到 https://api.github.com/users/evereq/starred?page=XXX,直到获得 0 个响应结果。如果你得到 0 个结果,你就完成了(不推荐,因为例如 GitHub 可以移动到“哈希”值而不是页码。GitHub 已经对某些 API 操作做到了这一点。)。
现在,假设我们要确保使用条件请求(请参阅https://docs.github.com/en/rest/overview/resources-in-the-rest-api#conditional-requests)来保存我们的 API 使用限制(以及世界上的流量、树木等)。
因此,我们将“If-None-Match”添加到请求标头中,并检查响应状态是否为 304(未修改)。如果是这样,则意味着我们上次的请求没有发生任何变化。这样就可以了。
然而,我们在上面 1. 和 2. 中遇到的问题,与我们如何检测何时停止的方式有关,当您使用条件请求时,它不再起作用!
即使用方法 1.,当您使用条件请求时,您根本不会获得链接响应标头。 因此,您需要再执行一个请求,其页面大于您已拥有 ETag 的页面,并看到它返回 0 结果,然后您就知道您已经完成了。这样一来,您基本上就“浪费”了对 GitHub API 的一个请求(因为它错过了条件请求标头)。
与方法 2 相同,基本上每个状态为 304 的请求都有 0 个响应...因此,要知道您已完成,您需要至少发出一个额外的请求,该请求确实返回 0 个结果。
所以问题是:当我们执行条件请求时,GitHub API 不会发回链接响应标头(至少使用 ETag 进行查询,结果为 Status 304),我们如何知道何时停止分页?这是 GitHub API 实现中的错误还是我错过了什么?
我们不知道最大页数,因此要了解何时停止,我们应该再执行一个“浪费”请求并检查是否返回 0 个结果!
我也找不到如何在 GitHub 上查询加星标的存储库的总数(这样我就可以计算出我应该在建议中迭代多少页),就像响应中不包含“X-Total-Count”之类的内容一样,所以我知道何时停止使用简单的数学计算页数。
有什么想法如何保存那个(“结束”)请求并仍然使用条件请求吗?
如果你每天做一个请求,接受这样的浪费是可以的,但是如果你每分钟做一个这样的请求怎么办?您将很快用完所有 API 使用限制!
好吧,经过几次测试,我现在看到以下“规则”(但是在文档中的任何地方都找不到它,所以请注意确定它的规则还是只是假设):如果用户星标新内容,则每个请求的页面都会产生结果与之前相比包含不同的 ETag 值,并且不再有状态 304!这意味着仅请求首页并检查状态就足够了。如果是 304(未修改),我们不需要检查下一页,即我们已经完成,因为任何页面中都没有任何更改。这是正确的做法还是只是巧合?
当内容发生更改时,我们确实在
Link
响应标头中返回分页关系 1。由于我们不支持该调用的 since
参数,因此您需要按最新结果进行排序,并为最后一个已知 ID 或时间戳(基于您的排序标准)维护客户端游标,并在以下情况下停止分页:它显示在您的分页结果中。有条件请求只会让您知道第 1 页是否已更改。
我们还没有确定返回列表方法计数的方法,但一个技术含量很低的解决方案是将页面大小设置为 1,获取
rel=last
链接关系并检查其 page
参数值。
希望有帮助。