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 不一定如此。
我看过很多地方都说 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 不一定如此。