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

HTTP PATCH is idempotent or non idempotent?

我看过很多地方都说 HTTP 补丁是非幂等的。有人能解释一下为什么它是非幂等的吗? 因为根据定义 - 幂等方法可能会或可能不会更改资源状态,但重复请求在第一次请求后应该没有进一步的副作用。 重复的 PATCH 请求如何改变资源状态?

对此有些困惑。 PATCH 方法不需要 是幂等的,这就是重点。客户不能假设他们的 PATCH 请求是幂等的,就像他们可以使用 PUT 和 GET 一样。

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

我有一个 PATCH 不会幂等的场景:

假设两个不同的客户端正在发送 HTTP 请求。
客户 X
客户 Y

客户 X
(1) 补丁 {"age":"10"}
response1-> {"age":"10", "sex":"f","name":"a"}

客户 Y
(2) 补丁 {"name":"b"}
response2-> {"age":"10", "sex":"f","name":"b"}

客户 X
(3) 补丁 {"age":"10"}
response3-> {"age":"10", "sex":"f","name":"b"}

你可以看到即使请求(1)和(3)相同,响应也不同。第 3 个响应中的 "name""b".

如果这是一个有效的场景,则可以证明即使请求相同,PATCH 方法也可以使用不同的响应进行响应。 PUT 方法永远不会发生这种情况,它应该发送包含所有字段 {age,sex,name} 的整个对象。

是的,有很多关于 PUT 和 PATCH 不同的讨论和困惑。明确的是:

放置

  • 请求必须包含给定资源的完整表示
  • 是幂等的(客户端可以100%确定)

补丁

  • 请求仅包含 子集(仅我们要更新的属性)
  • 不需要幂等(很多时候是幂等的,但不是规则,所以客户不能100%确定)

从这些规则中,我们可以推导出一些我们需要在后端实现的规则,例如:

一)

  • 获取:users/1;响应正文 {username: 'john', email: 'old@email.com'}
  • 放置:users/1;请求正文 {username: 'john'}

要么从 API(缺少 email)服务器发送验证错误,要么电子邮件将被删除。

真希望API应该return验证错误。所以要删除一些值,客户端应该调用(在请求中明确提到email: null):

  • 放置:users/1;请求正文 {username: 'john', email: null}

b)

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

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

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

以上两个例子都是幂等的。

在另一个讨论中,如果 patch 在后端执行类似“添加”到集合的操作,则 PATCH 是非幂等的示例:

PATCH 不一定是幂等的,尽管它可以。将此与 PUT 进行对比;这总是幂等的。 “幂等”一词意味着任意数量的重复、相同的请求将使资源保持相同的状态。例如,如果自动递增计数器字段是资源的组成部分,那么 PUT 自然会覆盖它(因为它会覆盖所有内容),但 PATCH 不一定如此。