DELETE 应该是幂等的。
如果我 DELETE http://example.com/account/123,它将删除该账户。
如果我再次执行,是否期望得到一个404错误,因为该账户已不存在?如果尝试删除从未存在过的账户会怎么样呢?
DELETE 应该是幂等的。
如果我 DELETE http://example.com/account/123,它将删除该账户。
如果我再次执行,是否期望得到一个404错误,因为该账户已不存在?如果尝试删除从未存在过的账户会怎么样呢?
除了错误问题(见下文)外,在所有情况下,该账户都不再存在。
来自这里
“方法还可以具有‘幂等性’属性,也就是说(除了 错误或过期问题),N > 0个相同请求的副作用与单个请求的副作用相同。GET、HEAD、PUT和DELETE方法共享此属性。另外,OPTIONS和TRACE方法不应具有副作用,因此本质上是幂等的。”
关键点在于“N > 0个相同请求的副作用与单个请求的副作用相同。”
你可以期望状态码会有所不同,但这并不影响幂等性的核心概念 - 您可以发送多个请求而无需对服务器状态进行额外更改。
幂等(Idempotent)是指请求的效果,而不是您收到的响应代码。
http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.1.2中提到:
除错误或过期问题外,“幂等”方法的副作用与单个请求相同。
虽然您可能会获得不同的响应代码,但发送N+1个DELETE请求到相同资源的效果可以被认为是相同的。
摘自我在另一个问题的回答:
历史上,发布于1999年的RFC 2616是HTTP 1.1规范中被引用最多的。不幸的是, 其对幂等性的描述非常模糊,这留给了所有这些争论的空间。但是该规范已被RFC 7231取代。摘自RFC 7231,4.2.2节幂等方法,重点加粗:
如果使用相同方法进行多个相同请求,对服务器的预期影响与单个请求的影响相同,请求方法被认为是“幂等的”。 在本说明书中定义的请求方法中,PUT、DELETE和安全请求方法是幂等的。
因此,规范中写明,幂等性完全是关于对服务器的影响。第一个DELETE返回204,然后随后的DELETE返回404,这些不同的状态码并不会使DELETE非幂等。使用这个论点来为随后的204返回辩护是不相关的。
好吧,那么问题就不在于幂等性了。但接下来的一个问题可能是,如果我们仍然选择在随后的DELETE中使用204,这样可以吗?
好问题。这种做法是可以理解的:为了让客户端能够实现其预期的结果,而不必担心错误处理。我认为,在后续的DELETE操作中返回204是一种相对无害的服务器端“善意谎言”,客户端不会立即察觉到其中的差别。所以,有人在实践中这样做,并且仍然运行良好。只需记住这种谎言可能被认为是语义上奇怪的,因为“GET /不存在”的返回值是404,但“DELETE /不存在”则返回204,在这种情况下,客户端将发现你的服务不完全符合 RFC 7231的第6.5.4节404 Not Found规范。
但是,RFC 7231暗示的期望方式,即在后续的DELETE操作中返回404,应该本来就不应该成为问题。更多的开发者选择这样做。那很可能是因为任何实现HTTP DELETE(或任何HTTP方法)的客户端都不会盲目地假设结果总是成功的2xx。一旦开发者开始考虑错误处理,404 Not Found可能会是首先想到的错误之一。此时,他/她希望得出结论:忽略404错误对于HTTP DELETE操作来说是语义上安全的。问题得到解决。
DELETE http://example.com/account/123
,那么其效果就是从服务器中删除帐户123,这是唯一的效果,对服务器状态的唯一更改。现在假设您再次执行相同的DELETE http://example.com/account/123
请求,服务器将以不同的方式响应,但其状态仍然相同。是的。无论响应代码如何。
根据HTTP 1.1最新RFC(我强调),幂等方法因为在客户端能够读取服务器响应之前发生通讯故障时可以自动重复请求而与众不同。例如,如果客户端发送一个PUT请求并且底层连接在接收任何响应之前关闭,那么客户端可以建立一个新的连接并重试幂等请求。它知道重复请求将有相同的预期效果,即使原始请求成功了,但响应可能会有所不同。
它明确指出,响应可能会有所不同。更重要的是,它指出了概念的原因:如果一个操作是幂等的,则客户端在遇到任何错误时都可以重复该操作,并知道这样做不会破坏任何东西。否则,客户端将不得不进行其他查询(可能是GET
),以查看之前的查询是否有效,才能安全地重复该操作。只要服务器能够提供这样的保证,该操作就是幂等的。引用自另一条评论:
计算幂等性是关于系统的强度。由于事情可能会失效(例如,网络故障),当检测到故障时,您如何恢复?最简单的恢复方法就是重新执行它,但这仅在重新执行是幂等的情况下才有效。例如,
discard(x)
是幂等的,但pop()
不是。这都是关于错误恢复的问题。
假设我们需要管理由id
、name
和city
表示的足球队伍。
{
id: "1",
name: "manchester united",
city : "manchester "
}
说DELETE
是幂等的意思是,如果您多次调用DELETE /team/1
,系统的状态保持不变(实际上第一次调用DELETE /team/1
会删除团队)。换句话说,因为重复调用DELETE
不会更改系统状态,所以DELETE
是幂等的。
同样地,我们也可以说PUT
是幂等的。
想象一下,您执行了多个PUT
:
PUT /team/1
{
id: "1",
name: "liverpool",
city : "liverpool"
}
重复调用这样的PUT
请求总是有相同的效果(团队1将是利物浦)。
显然,GET
请求也是幂等的。
我认为也是这样,404 - 账户不存在。
你可以说400 - 错误的请求。但从REST的角度来看,您请求执行操作的对象不存在。这就转化为404。