当前位置: 首页 > 知识库问答 >
问题:

为什么HTTP PUT不允许在REST API中进行部分更新?

晋越彬
2023-03-14

谁说可信赖的 API 必须通过 HTTP 补丁单独支持部分更新?

它似乎没有任何好处。它增加了在服务器端实现的更多工作,以及在客户端实现的更多逻辑,以决定请求哪种更新。

我是在使用HTTP创建一个RESTAPI的上下文中问这个问题的,这个RESTAPI提供了对已知数据模型的抽象。要求PATCH进行部分更新,而不是要求PUT进行全部或部分更新,这似乎没有任何好处,但我可以被说服。

相关的

http://restcookbook.com/HTTP方法/幂等性/-这意味着您无法控制可能缓存请求的服务器软件。

禁止部分PUT的理由是什么没有给出明确的答案,只参考了HTTP对PUt和PATCH的定义。

http://groups.yahoo.com/neo/groups/rest-discuss/conversations/topics/17415-显示了对此的看法分歧。

共有3个答案

桂德义
2023-03-14

PUT允许部分更新(根据RFC 7231https://www.rfc-editor.org/rfc/rfc7231#section-4.3.4)。

",...PUT请求被定义为替换目标资源的状态。-替换物体的一部分基本上改变了它的状态。

"通过定位与较大资源的一部分重叠的单独标识的资源,可以进行部分内容更新,…"

根据RFC,下一个请求是有效的:PUT/resource/123 { name:' new name ' }它将只更改指定资源的名称。在请求有效负载中指定id是不正确的(因为不允许对未指定的资源进行部分更新)。

PS:下面是补丁有用时的示例。

有一个内部有数组的对象。使用PUT,您不能更新特定的值。您只能将整个列表替换为新列表。使用PATCH,您可以将一个值替换为另一个值。使用地图和更复杂的对象,好处会更大。

符畅
2023-03-14

为了扩展现有的答案,< code>PUT应该执行资源状态的完整更新(覆盖),因为HTTP以这种方式定义了该方法。关于HTTP/1.1的原始RFC 2616对此不是很明确,RFC 7231增加了语义说明:

4.3.4输出

PUT方法请求创建目标资源的状态或用请求消息有效负载中包含的表示定义的状态替换。给定表示的成功PUT将表明同一目标资源上的后续GET将导致在200(OK)响应中发送等效表示。

如另一个答案所述,遵守此约定简化了API的理解和使用,并且无需显式记录PUT方法的行为。

但是,由于幂等性,不允许进行部分更新。我发现强调这一点很重要,因为这些概念经常被混淆,即使在许多StackOverflow答案上也是如此(例如在这里)。

幂等仅表示应用请求一次或多次会在服务器上产生相同的效果。再次引用 RFC 7231:

4.2.2幂等方法

如果使用该方法的多个相同请求对服务器的预期效果与单个此类请求的效果相同,则该请求方法被视为“幂等”。

只要部分更新仅包含资源状态的新值并且不依赖于以前的值(即这些值被覆盖),就可以满足幂等性的要求。无论应用此类部分更新的次数如何,服务器的状态将始终保留请求中指定的值。

来自另一个客户端的中间请求是否可以改变资源的不同部分并不相关,因为幂等性指的是操作(即PUT方法),而不是状态本身。并且关于部分覆盖更新的操作,其应用程序在应用一次或多次后产生相同的效果。

相反,不是幂等的操作依赖于当前的服务器状态,因此根据它被执行的次数,它会导致不同的结果。最简单的例子是递增一个数(非等幂)与将其设置为绝对值(等幂)。

对于非幂等更改,HTTP预见到方法POSTPATCH,而PATCH被明确设计为对现有资源进行修改,而POST可以更自由地解释请求URI、正文内容和服务器上的副作用的关系。

这在实践中意味着什么?REST是在HTTP协议上实现API的一个范例——许多人认为这是一个合理的约定,因此很可能被采纳或理解。尽管如此,关于什么是RESTful,什么不是,仍然存在争议,但即使撇开这些,REST并不是构建HTTP API的唯一正确或有意义的方法。

HTTP协议本身对您可以做什么和不能做什么施加了限制,其中许多都具有实际的实际影响。例如,忽略幂等性可能会导致缓存服务器更改客户端实际发出的请求数,并随后中断应用程序预期的逻辑。因此,在偏离标准时意识到其影响至关重要。

严格遵守REST,对于部分更新没有完全令人满意的解决方案(有些人甚至说这种需求本身就不利于REST)。问题是PATCH,最初似乎只是为了这个目的而制作的,不是幂等的。因此,通过使用PATCH进行幂等部分更新,您失去了幂等的优势(任意数量的自动重试、更简单的逻辑、客户端、服务器和网络优化的潜力)。因此,您可能会问自己,使用PUT是否真的是最糟糕的主意,只要行为被明确记录并且不会因为用户(和中间网络节点)依赖于某些行为而中断……?

鲍俊杰
2023-03-14

谁说的?发明REST的人说:

@mnot Oy,是的,PATCH是我为最初的HTTP/1.1提案创建的,因为部分PUT永远不会RESTful。;-)

https://twitter.com/fielding/status/275471320685367296

首先,REST是一种架构风格,其原则之一是利用其底层协议的标准化行为,因此如果您想在HTTP上实现RESTful API,您必须严格遵循HTTP,使其成为RESTful。如果你认为这不足以满足你的需求,你可以不这样做,没有人会因此而诅咒你,但是你没有Rest。您必须记录您在哪里以及如何偏离标准,在客户端和服务器实现之间创建强耦合,使用REST的全部目的就是避免这种情况,并专注于您的媒体类型。

因此,根据RFC 7231,PUT应该仅用于幂等运算中表示的完全替换。PATCH应该用于不需要幂等的部分更新,但最好在应用diff之前通过先决条件或验证当前状态使其幂等。如果需要执行非幂等更新,无论是否是部分更新,请使用POST。易于理解的每个使用你的API并且知道PUT和PATCH是如何工作的人都希望它们能那样工作,你不需要记录或解释这些方法应该对给定的资源做什么。你可以自由地让PUT以你认为合适的任何其他方式运行,但是你必须为你的客户记录这一点,你必须为API找到另一个流行词,因为那不是RESTful。

请记住,REST 是一种专注于 API 长期演变的架构风格。正确地做到这一点现在会增加更多的工作,但将使以后的改变更容易,创伤更小。这并不意味着REST对一切和每个人都是足够的。如果您的重点是易于实现和短期使用,只需根据需要使用这些方法即可。如果您不想打扰客户选择正确的方法,则可以通过POST执行所有操作。

 类似资料:
  • 问题内容: 我从编译器收到的错误是“分配的左侧必须是变量”。我的用例是深度复制,但并没有实际意义。 在C ++中,可以分配给。 问题不在于如何规避对的分配。这很简单,但是决定不进行变量的背后是什么原理。 原因是技术上的还是概念上的? 到目前为止,我的猜测-用随机方法重建对象的可能性容易出错(概念上),但在技术上是可行的。 编辑 请避免使用“因为Java规范这么说”的变体。我想知道 这个决定 的 原

  • 问题内容: 我读了这个问题,并认为如果可以写的话,很容易解决(不是没有它就不能解决): 我不确定在很多情况下它是否有用,但是我想知道为什么它没有用,以及其他语言中是否存在类似的东西。 你们有什么感想? 编辑: 澄清一下:是的,我知道,这在Java中是不可能的,我也不是很想念它。这不是我期望的工作,并且惊讶于出现编译器错误。我只是有这个主意,喜欢讨论它。 问题答案: 它违反了封装。你不应该能够绕过父

  • 问题内容: 我试图获取我的Layout 以适合我要移植到Java的程序的外观,在此之前,我已经使用了多个LayoutManager并获得了巨大的成功,但是由于某些原因,我似乎无法获得此布局都在工作。我的目标是有权利(东)侧的包含一个“查找下一个”和自上而下的命令“取消”按钮,然后在下面的任何额外的空间,从而使两个按钮总是在的顶部,但由于某种原因,它会不断忽略更改a宽度的任何尝试(这是我迷失的地方)

  • 在学习和使用spring-boot之后,我了解了spring-boot ConditionalOnClass的用法和逻辑,我的问题是: < li >为什么“因为这个注释是通过加载类字节码来解析的,所以在这里指定最终可能不在类路径上的类是安全的”。 < li >与此相关的JVM规范在哪里? https://github.com/spring-projects/spring-boot/blob/mas

  • 问题内容: W3指定表列(带有元素)仅允许使用四个CSS规则- 边框,背景,宽度和可见性。 有人知道这个决定的原因吗?如果可以使用边框和背景,为什么不使用字体和颜色呢? 问题答案: IanHixie在这里详细解释:为什么只有四个属性应用于表列的奥秘。相关报价: 文本的颜色取决于其元素的“颜色”属性。除非指定,否则“ color”属性(基本上)默认为“ inherit”,这意味着“采用父元素的值”。

  • 其中map类型为,但我的测试在编译时失败: 为什么JUnit(或Hamcrest)不能确定使用哪个匹配器?