不允许部分PUT背后的理由是什么?

时间:2010-03-02 15:11:12

标签: http rest

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

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

即:

通过阻止部分PUT获得了什么?

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

4 个答案:

答案 0 :(得分:15)

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

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

如果要进行部分更新,请使用PATCH或在子资源上使用POST,然后返回303参见“其他”资源,例如


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(被定义为幂等)不能用于部分更新。

答案 1 :(得分:-2)

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

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

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

答案 2 :(得分:-2)

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

答案很长:

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

因为每次执行POST时,语义都是在服务器上创建一个新的实体实例,POST构成一个ACID操作。但是,如果服务器的存储空间不足以存储需要创建的新实例,那么在主体中使用相同的实体重复相同的POST两次仍然可能导致不同的结果 - 因此,POST不是幂等的。

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

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

答案 3 :(得分:-2)

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

如果已知某种方法永远不会是部分内容更新,并且某人提供的API仅支持该方法,那么使用API​​的人必须做的事情就是更改文档以获得给定一组有效的内容。