Rest 集合中的分页

2024-01-08

我有兴趣向 JSON 文档集合公开一个直接的 REST 接口(想想CouchDB http://couchdb.apache.org/ or 坚持不懈 http://persvr.org/)。我遇到的问题是如何处理GET如果集合很大,则对集合根进行操作。

举个例子,假设我正在公开 StackOverflow 的Questions表中的每一行都作为一个文档公开(不一定存在这样的表,只是一个相当大的“文档”集合的具体示例)。该系列将在以下网址提供:/db/questions使用通常的 CRUD apiGET /db/questions/XXX, PUT /db/questions/XXX, POST /db/questions正在播放。获取整个集合的标准方法是GET /db/questions但是,如果将每一行天真地转储为 JSON 对象,您将获得相当大的下载量,并且服务器会承担大量工作。

解决方案当然是分页。 Dojo 已经解决了这个问题JsonRestStore http://docs.dojocampus.org/dojox/data/JsonRestStore#id7通过巧妙的 RFC2616 兼容扩展使用Range带有自定义范围单位的标题items。结果是206 Partial Content仅返回请求的范围。与查询参数相比,这种方法的优点是它将查询字符串留给...查询(例如GET /db/questions/?score>200或者类似的东西,是的,会被编码%3E).

这种方法完全涵盖了我想要的行为。问题是RFC 2616 https://www.rfc-editor.org/rfc/rfc2616指定在 206 响应中(强调我的):

The request必须包含 Range 标头字段(第 14.35 条 https://www.rfc-editor.org/rfc/rfc2616#section-14.35) 指示所需的范围,并且可以包含 If-Range 标头字段(第 14.27 条 https://www.rfc-editor.org/rfc/rfc2616#section-14.27) 使请求成为有条件的。

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

我已经详细阅读了 RFC 寻找解决方案,但对我的解决方案不满意,并且对 SO 对这个问题的看法感兴趣。

我曾经有过的想法:

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

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

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


我不太同意你们中有些人的观点。我已经为我的 REST 服务开发此功能数周了。我最终做的事情非常简单。我的解决方案只对 REST 人们所说的集合有意义。

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

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

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

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

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Rest 集合中的分页 的相关文章

随机推荐

  • 当鼠标一段时间没有移动时,用jQuery隐藏div元素?

    我有一个广播视频网站 带有一个菜单 当鼠标一段时间 假设 10 秒 不移动时 应该隐藏该菜单 同样 随着鼠标移动 它应该会重新出现 使用 css 和 jQuery 执行此操作的最佳方法是什么 先感谢您 看看mousemove http ap
  • 隐藏直方图

    所以我想绘制正态分布 我已经看到一种方法是使用以下代码 import numpy as np import matplotlib pyplot as plt mu 5 sigma 1 s np random normal mu sigma
  • 如何创建 C 工厂函数?

    我有一个带有函数指针的结构 如下所示 typedef int node transition func wint t typedef struct lex dfa arc t node transition func func int ex
  • C中的按位移位[重复]

    这个问题在这里已经有答案了 我得到了一些令我困惑的 C 代码 int a 1 int b 32 printf d n d n a lt
  • 在Python中强制函数参数类型?

    我在 Python 类中有一个函数 可以将接口添加到列表中 def RegisterAsListener self inListener self TransitListeners append inListener 这很好 因为一个类只需
  • 在类函数中定义类函数:Python

    我有一个代码 我想在类函数中定义一个类函数 这是我想做的一个简单的例子 该程序的目标是打印 4 gt gt gt class bluh def haha self print 3 def init self def haha self pr
  • Xrm.Page.data 为空

    我在机会实体上添加了一个自定义表单 并附加了一些 javascript 我使用 window open 和 url 中的 formId 来调用表单来打开表单 并且仅用于创建机会实体 在 javascript 中 我只是尝试填充一些字段 但
  • 使用 PHP 和 HTML 时的最佳实践是什么?

    我设计网站已经有一段时间了 但在使用 PHP 和 HTML 时 有一点我一直不太确定 整个文档用 PHP 编写是不是更好 echoHTML 像这样 或者有一个像这样的 HTML 文件 然后添加到 PHP 中 div Content div
  • 人们使用类加载做什么?

    因此 每本 Java 教科书都会谈论 Java 的灵活性 因为它可以在运行时加载类 只需拼凑一根绳子并将其交给Class forName 并抓住ClassNotFoundException并处理它 理论就讲这么多 您能否举例说明如何使用 J
  • 在鼠标悬停时动态添加和删除类 - Vue.js

    我可以使用 Vue 成功地在鼠标悬停时添加一个类 但我想在鼠标离开元素时删除该类 在 Vue 中处理这个问题的惯用方法是什么
  • MongoDB $或查询

    我在 mongo shell 中运行以下查询 db Profiles find or name gary name rob 它只是按预期返回任何内容 JSON Use in 对于问题中的查询 使用更合适 in http docs mongo
  • Websocket 跨页面 JavaScript

    我用 JS 实现了一个基本的 websockets 客户端 function connectToNotifServer var conn new WebSocket ws localhost 8080 conn onopen functio
  • 管道、dup2 和 exec()

    我必须编写一个可以运行管道的外壳 例如像这样的命令ls l wc l 我已经成功解析了用户给出的命令 如下所示 ls 第一个cmd l frsarg wc scmd l secarg 现在我必须使用两个叉子 因为命令是两个和一个管道 我编写
  • XML 中真正允许的字符

    由于在解析某些 据说是 XML 数据时出现一些解析器错误 我查看了XML标准 http www w3 org TR REC xml d 找出真正允许的内容 我目前的疑虑是关于标签内容中允许包含哪些内容
  • 添加更多代码后,Google Apps 脚本会随机生成错误消息“发生意外错误”

    我编写了一个 Google Apps Script UiApp 应用程序 其中包含近 1000 行代码以及相当数量的处理程序和回调 该应用程序运行良好 但随着代码的增长 应用程序突然收到很多 发生意外错误 消息 错误消息在应用程序加载时出现
  • 您如何根据风格选择元素?

    使用 jQuery 您如何找到具有特定样式的元素 例如 float left 无论它是内联样式还是 CSS 文件中定义的样式 使用过滤功能 http docs jquery com Traversing filter filter func
  • 带有嵌套资源轨的嵌套表单 4

    我正在尝试在 Rails 4 0 3 上创建一个带有嵌套资源的嵌套 form for 但是我遇到了一些问题并且花了很多时间 问题是当我尝试提交表单时 这些值没有保存在我的数据库中 它将直接重定向到labs index 我已经定义了嵌套资源和
  • 为什么带宽以每秒位数来衡量?

    根据带宽的定义 它是频率的宽度 光谱 因此带宽应以 Hz 为单位进行测量 但 bps Mbps kbps 几乎到处都被用作带宽的度量 我需要知道的是 为什么使用 bps kbps 等数据传输速率测量来测量信号的带宽 由于对香农 哈特利定律的
  • 是的:将字段本身与另一个字段进行比较

    I had StartIntensity yup number EndIntensity yup number when StartIntensity StartIntensity number schema any gt return S
  • Rest 集合中的分页

    我有兴趣向 JSON 文档集合公开一个直接的 REST 接口 想想CouchDB http couchdb apache org or 坚持不懈 http persvr org 我遇到的问题是如何处理GET如果集合很大 则对集合根进行操作