【问题标题】:What's the justification behind disallowing partial PUT?不允许部分 PUT 背后的理由是什么?
【发布时间】:2010-03-02 15:11:11
【问题描述】:

为什么 HTTP PUT 请求必须包含“整体”状态的表示,而不能只是部分状态?

我知道这是 PUT 的现有定义 - 这个问题是关于为什么会这样定义的原因。

即:

防止部分 PUT 有什么好处?

为什么阻止幂等部分更新被认为是可接受的损失?

【问题讨论】:

  • 查看此处以了解有关同一问题的另一次讨论:tech.groups.yahoo.com/group/rest-discuss/message/17415 - 我已经阅读了所有内容,并认为没有令人信服的理由将 PUT 的定义仅用于完整更新。
  • @lkraider 我同意。除了做一些事情之外,我没有看到任何好处,因为 HTTP 规范区分了 PUT 和 PATCH(这不是很实用)。

标签: http rest


【解决方案1】:

PUT 表示 HTTP 规范定义的含义。客户端和服务器无法改变这个含义。如果客户端或服务器以与其定义相矛盾的方式使用 PUT,至少可能会发生以下情况:

Put 根据定义是幂等的。这意味着客户端(或中介!)可以重复 PUT 任意次数,并确保效果相同。假设中介收到来自客户端的 PUT 请求。当它将请求转发到服务器时,出现了网络问题。中介根据定义知道它可以重试 PUT 直到成功。如果服务器以非幂等方式使用 PUT,这些潜在的多次调用将产生不良影响。

如果您想进行部分更新,请在子资源上使用 PATCH 或 POST 并将 303 See Other 返回到“主”资源,例如


POST /account/445/owner/address
Content-Type: application/x-www-form-urlencoded

street=MyWay&zip=22222&city=Manchaster


303 See Other
Location: /account/445

编辑:关于为什么部分更新不能是幂​​等的一般问题:

一般来说,部分更新不能是幂​​等的,因为幂等性取决于媒体类型语义。 IOW,您也许可以指定允许幂等补丁的格式,但不能保证 PATCH 对于每种情况都是幂等的。由于方法的语义不能是媒体类型的函数(出于正交性原因),因此需要将 PATCH 定义为非幂等的。并且 PUT(被定义为幂等)不能用于部分更新。

【讨论】:

  • 嗨 Jan,正如我已经说过的; “我知道这是 PUT 的现有定义——这个问题是关于为什么会这样定义的原因”。您在第 2 段中的示例暗示部分更新是非幂等的 - 显然这就是 PATCH 的用途。我对 幂等 部分更新感兴趣 - 即部分 PUT。
  • PATCH 正在重新添加。还; Jan - 幂等性不需要依赖于任何特定的媒体类型集,就其在协议中的定义而言,方法的语义是它作为统一接口的一部分的定义的函数。我仍在努力通过将 PUT 的定义更改为简单的“状态的幂等变化”(即不阻止部分)来计算实际丢失的内容。
  • 我看不出部分 PUT 是如何破坏幂等性的。当然,实现可以打破这一点,就像它可以为 GET 一样。此外,RFC 并没有严格提到 PUT 不能是部分的。
  • HTTP1.1bis 现在明确表示 PUT 不适用于部分更新:tools.ietf.org/html/…(倒数第二段)
  • FWIW 在讨论的后期,有几个例子说明为什么部分更新仅与所涉及的媒体类型相关:日志文件的补丁(例如,实时聊天板保留最后 1000 行)部分更新该文件,但重新提交会多次添加相同的条目,表现为对集合的 POST。然后你就有了类似使用 PATCH 来更新一个人的名字的东西,如果重新提交(幂等),每次都会导致同样的事情。伙计们,HTTP 规范的存在是有原因的。 PUT 具有既定的预期行为。
【解决方案2】:

因为,我猜,当多个并发客户端访问该状态时,这会转化为不一致的“视图”。据我所知,REST 中没有“部分文档”语义,而且在并发上下文中处理该语义的复杂性中添加它的好处可能并不值得。

如果文档很大,没有什么可以阻止您构建多个独立文档并拥有一个将它们联系在一起的总体文档。此外,一旦收集了所有的点点滴滴,我想可以在服务器上整理一个新的文档。

所以,考虑到可以“解决”这个“限制”,我可以理解为什么这个功能没有成功。

【讨论】:

  • 道歉 - 我不明白部分幂等更新产生的不一致视图与“完全”幂等更新的行为不同的观点。从协议定义的角度来看,我也不确定建议的复杂性增加。
【解决方案3】:

简答: PUT 操作的酸度和更新实体的状态。

长答案:

RFC 2616:第 2.5 段,“POST 方法请求所附实体被接受为所请求 URL 的新下级”。第 2.6 段,“PUT 方法请求将封闭的实体存储在指定的 URL”。

由于每次执行POST,语义都是在服务器上创建一个新的实体实例,POST构成一个ACID操作。但是,在正文中使用相同的实体重复相同的 POST 两次仍然可能导致不同的结果,例如,如果服务器已用完存储来存储需要创建的新实例 - 因此,POST 不是幂等的。

另一方面,PUT 具有更新现有实体的语义。不能保证即使部分更新是幂等的,它也是 ACID 并导致一致且有效的实体状态。因此,为了确保 ACIDity,PUT 语义要求发送完整的实体。即使这不是 HTTP 协议作者的目标,PUT 请求的幂等性也会作为尝试执行 ACID 的副作用而发生。

当然,如果 HTTP 服务器对实体的语义非常了解,它可以允许部分 PUT,因为它可以通过服务器端逻辑确保实体的一致性。然而,这需要数据和服务器之间的紧密耦合。

【讨论】:

  • “不能保证即使部分更新是幂等的,它也是原子的” - 嗯,我不明白。幂等更新怎么可能是非原子的?
  • 当我说原子性时,我暗示了酸性。换句话说,如果实体处于有效且一致的状态,我认为操作是“原子的”。应该明确使用 ACID 而不是 atomic。
【解决方案4】:

通过完整的文档更新,很明显,在不了解特定 API 的任何细节或它对文档结构的限制是什么的情况下,更新后生成的文档将是什么。

如果已知某个方法永远不会是部分内容更新,并且某人提供的 API 仅支持该方法,那么使用该 API 的人必须做什么才能更改文档以具有给定的内容总是很清楚的一组有效内容。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-08-05
    • 1970-01-01
    • 2011-08-17
    • 2013-06-16
    • 2012-01-17
    • 2015-02-20
    • 1970-01-01
    • 2014-06-24
    相关资源
    最近更新 更多