http - 在 Rest 集合中分页

标签 http rest http-headers pagination

我有兴趣将直接 REST 接口(interface)暴露给 JSON 文档集合(想想 CouchDBPersevere )。我遇到的问题是如果集合很大,如何处理集合根上的 GET 操作。

举个例子,假设我正在公开 StackOverflow 的 Questions 表,其中每一行都作为一个文档公开(并不是说一定有这样一个表,只是一个相当大的“文档”集合的具体示例').该集合将在 /db/questions 中可用,使用通常的 CRUD api GET/db/questions/XXX, PUT/db/questions/XXXPOST/db/questions 正在运行。获取整个集合的标准方法是 GET/db/questions 但如果天真地将每一行转储为 JSON 对象,您将获得相当大的下载量和大量工作服务器。

解决方案当然是分页。 Dojo 在其 JsonRestStore 中解决了这个问题通过将 Range header 与自定义范围单元 items 一起使用的符合 RFC2616 的巧妙扩展。结果是 206 Partial Content,它只返回请求的范围。这种方法相对于查询参数的优势在于它为...查询保留查询字符串(例如 GET/db/questions/?score>200 或类似的,是的,它会被编码%3E)。

这种方法完全涵盖了我想要的行为。问题是 RFC 2616指定在 206 响应(强调我的):

The request MUST have included a Range header field (section 14.35) indicating the desired range, and MAY have included an If-Range header field (section 14.27) to make the request conditional.

这在 header 的标准用法的上下文中是有意义的,但这是一个问题,因为我希望 206 响应成为默认响应以处理天真的客户/随机探索的人。

我已详细阅读 RFC 以寻找解决方案,但对我的解决方案不满意,并且对 SO 对问题的处理很感兴趣。

我的想法:

  • 返回带有 Content-Range header 的 200! - 我不认为这是错误的,但我更愿意一个更明显的指示器,表明响应只是部分内容。
  • Return 400 Range Required - 对于所需的 header 没有特殊的 400 响应代码,因此必须使用默认错误并手动读取。这也使得通过网络浏览器(或 Resty 等其他客户端)进行探索变得更加困难。
  • 使用查询参数 - 标准方法,但我希望允许查询像 la Persevere 一样切入查询命名空间。
  • 只需返回 206! - 我认为大多数客户不会 panic ,但我不想违背 RFC 中的 MUST
  • 扩展规范!返回 266 部分内容 - 行为与 206 完全相同,但响应的请求不得包含 Range header 。我认为 266 足够高,我不应该遇到碰撞问题,这对我来说很有意义,但我不清楚这是否被视为禁忌。

我认为这是一个相当普遍的问题,我希望看到它以一种事实上的方式完成,这样我或其他人就不会重新发明轮子。

当集合很大时,通过 HTTP 公开完整集合的最佳方式是什么?

最佳答案

我真的不同意你们中的一些人。为了我的 REST 服务,我已经为这个特性工作了数周。我最终做的事情真的很简单。我的解决方案只对 REST 人们所说的集合有意义。

客户端必须包含一个“Range” header 以指示他需要集合的哪一部分,或者当请求的集合太大而无法在单次往返中检索时准备好处理 413 REQUESTED ENTITY TOO LARGE 错误.

服务器发送一个 206 PARTIAL CONTENT 响应,其中 Content-Range header 指定已发送资源的哪一部分,以及一个 ETag header 以标识集合的当前版本。我通常使用类似 Facebook 的 ETag {last_modification_timestamp}-{resource_id},我认为集合的 ETag 是它包含的最近修改资源的 ETag。

要请求集合的特定部分,客户端必须使用“Range” header ,并使用从先前执行的请求中获取的集合的 ETag 填充“If-Match” header ,以获取同一集合的其他部分.因此,服务器可以在发送请求的部分之前验证集合是否未更改。如果存在更新的版本,则返回 412 PRECONDITION FAILED 响应以邀请客户端从头开始检索集合。这是必要的,因为这可能意味着在当前请求的部分之前或之后可能已经添加或删除了一些资源。

我将 ETag/If-Match 与 Last-Modified/If-Unmodified-Since 结合使用来优化缓存。浏览器和代理可能依赖其中之一或两者来实现它们的缓存算法。

我认为 URL 应该是干净的,除非它包含搜索/过滤查询。如果您考虑一下,搜索只不过是集合的部分 View 。我们应该看到更多 cars?manufacturer=BMW,而不是 cars/search?q=BMW 类型的 URL。

关于http - 在 Rest 集合中分页,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/924472/

相关文章:

HTTP GET 请求在查询字符串中包含许多项目

java - Spring RestTemplate 不使用完整的 URL

c# - HttpClient/.NET Core 不支持的媒体类型

java - 阻塞非 CRUD REST 动词

javascript - "No ' Access-Control-Allow-Origin ' header is present on the requested resource."发出 "GET"请求时

php - 不使用表单将文件上传到服务器?

java - 从网页响应读取字节时出现问题 (amf)

http - 当客户端尝试更新客户端陈旧的数据实体时,什么 HTTP 状态代码是合适的?

angular - 响应主体为空,状态为 200

javascript - Rest 控制台测试 REST API 需要 INT 列表作为参数