HTTP PATCH 是幂等的还是非幂等的?

4
我读过很多地方说HTTP Patch是不幂等的。有人能解释一下为什么它是不幂等的吗? 因为根据定义,幂等方法可能会或可能不会改变资源状态,但重复请求在第一次请求后不应产生进一步的副作用。 如何通过重复PATCH请求更改资源状态?
3个回答

6

关于这个问题有些混淆。PATCH方法不需要是幂等的,这就是重点。客户端不能像使用PUT和GET一样假设他们的PATCH请求是幂等的。

特定实现是否幂等通常取决于正在使用的修补算法(如果有)。例如,一个不使用验证当前值的差异格式的糟糕实现将不会是幂等的。


抱歉,即使使用类似于JSON Patch的差异格式,您仍然可以进行非幂等性 PATCH 请求。例如,通过将项目附加到数组中:{"op": "add", "path": "/-", "value": "foo"}[] 转换为 ["foo"] 第一次,然后转换为 ["foo", "foo"] 第二次,然后转换为 ["foo", "foo", "foo"] 第三次,以此类推。 - Géry Ogam
@Maggyero "不使用验证当前值的差异格式" - Pedro Werneck
我不明白验证与幂等性有什么关系。无论是否经过验证,向数组追加元素都永远不会是幂等的。 - Géry Ogam
追加数组是不是一个PATCH操作?这个问题非常模糊不清。我们要修补的元素是一个键还是一个键值对?有没有唯一性的标准?只要我们讨论的是更新非数组值,就应该将修补操作视为幂等的。如果我们将数组字段视为独立的对象,那么这个操作可以是PUT、POST或PATCH。 - undefined
你能用类似diff的操作来做吗?如果可以的话,可以使用PATCH方法。如果不能,那可能就是POST方法了。PUT方法是用来替换整个文档的。 - undefined
显示剩余3条评论

2
是的,人们对PUT和PATCH之间的区别进行了很多讨论和混淆。清晰的区别如下:
PUT
- 请求必须包含给定资源的全部表示 - 是幂等的(客户端可以确信为100%)
PATCH
- 请求仅包含子集(我们想要更新的属性) - 不需要是幂等的(通常是幂等的,但这不是规则,因此客户端不能100%确定)
从这些规则中,我们可以推断出我们需要在后端实现的一些规则,例如:
a)
- GET:users/1;响应体 {username: 'john', email: 'old@email.com'} - PUT:users/1;请求体 {username: 'john'}
服务器将从API发送验证错误(缺少电子邮件)或删除电子邮件。
我真的希望API能够返回验证错误。因此,要删除某个值,客户端应该调用以下内容(在请求中明确指定email:null):
  • PUT:users/1;请求正文{username:'john',email:null}

b)

  • PATCH:users/1;请求正文{username:'john'}

服务器上没有变化。要删除值,客户端应发送:

  • PATCH:users/1;请求正文{email:null}

以上两个示例均为幂等。

在另一次讨论中,如果补丁对后端集合执行“添加”之类的操作,则PATCH是不幂等的:在REST API实际场景中使用PUT和PATCH方法


0
PATCH不一定是幂等的,尽管它可以是。与PUT相比,PUT始终是幂等的。 "幂等"一词意味着任何数量的重复、相同的请求都将使资源保持在相同的状态。例如,如果自动递增计数器字段是资源的一个组成部分,那么PUT将自然地覆盖它(因为它覆盖了所有内容),但对于PATCH来说则不一定如此。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接