假设 HTTP 中的 DELETE 谓词是幂等的,当我发出以下请求时,第二个(或第三个,或第四个,等等)应该发生什么。.)时间到了吗?
DELETE /person/123
第一次,资源被删除,我返回一个204(成功,没有内容)。我应该在随后的呼叫中返回一个204还是一个404(未找到) ?
RESTful Web 服务食谱是一个很好的资源。它的谷歌预览偶然显示了关于 DELETE 的页面(第11页) :
DELETE 方法是幂等的 意味着服务器必须返回 响应代码200(OK) ,即使 服务器删除了 但实际上, 作为幂等元实现 DELETE 操作要求服务器保持 跟踪所有已删除的资源。 否则,它可以返回一个404(不 发现)。
由于无状态系统中的 HTTP 请求应该是独立的,因此一个请求的结果不应该依赖于以前的请求。考虑一下,如果两个用户同时对同一资源执行 DELETE,会发生什么情况。第二个请求得到404是有道理的。如果一个用户发出两个请求,也应该如此。
我猜,让 DELETE 返回两个不同的响应对您来说不会感到无能为力。我发现将幂等请求看作是使系统处于相同的状态,而不一定具有相同的响应是有用的。因此,无论您是 DELETE 现有资源,还是尝试 DELETE 不存在的资源,服务器资源状态都是相同的。
首先删除 : 200或204。
其后的 DELETE : 200或204。
基本原理: DELETE 应该是幂等的。如果在第二次删除时返回404,则响应将从 成功准则更改为 错误代码。基于 DELETE 失败的假设,客户端程序可能采取不正确的操作。
例子 :
为了说明这种方法的使用,PayPal 的 HTTP API 样式指南有以下准则:
DELETE: 这个方法应该返回状态码204,因为在大多数情况下不需要返回任何内容,因为请求是要删除一个资源,并且它已经被成功删除。 因为 DELETE 方法也必须是幂等的,所以它仍然应该返回204,即使资源已经被删除。通常,API 使用者不关心资源是作为此操作的一部分删除的,还是在此操作之前删除的。这也是为什么应该返回204而不是404的原因。
DELETE: 这个方法应该返回状态码204,因为在大多数情况下不需要返回任何内容,因为请求是要删除一个资源,并且它已经被成功删除。
因为 DELETE 方法也必须是幂等的,所以它仍然应该返回204,即使资源已经被删除。通常,API 使用者不关心资源是作为此操作的一部分删除的,还是在此操作之前删除的。这也是为什么应该返回204而不是404的原因。
我同意当前选择的答案所说的,即 第二(和第三,第四,...)删除应得到一个404。我注意到这个答案有143个赞成票,但也有一个相反的评论,有54个赞成票,所以社区被分成2个阵营,大约3:1的比例。这里有更多的信息来解决这个长期的争论。
RFC 7231,章节4.3.5 DELETE 碰巧只提到一个成功的响应应该是2xx,但是它并没有说明随后的 DELETE 会得到什么。我们再深入调查一下。
RFC 7231章节6.5.4404 Not Found 说404响应表示资源不存在。由于没有特定的 http 方法(特别是 DELETE)被调用来进行其他处理,我们可以直观地得到一个印象(理所当然地) ,即我的请求 DELETE /some/resource/which/does/not/exist应该导致404。那么,DELETE /some/resource/which/happened/to/be/removed/by/someone/else/five/days/ago不妨也返回一个404。那么,为什么 DELETE /some/resource/i/deleted/five/seconds/ago会有什么不同呢? “那么等幂呢? !”,我能听到你在尖叫。等等,我们马上就要进入这个话题了。
DELETE /some/resource/which/does/not/exist
DELETE /some/resource/which/happened/to/be/removed/by/someone/else/five/days/ago
DELETE /some/resource/i/deleted/five/seconds/ago
从历史上看,1999年发布的 RFC 2616是最常被引用的 HTTP 1.1规范。不幸的是,它对幂等性的描述是模糊的为所有这些辩论留下了空间。但是这个规格已经被 RFC 7231取代了。引自 RFC 7231,第4.2.2节,幂等方法,强调我的:
如果预期的 EFFECT ON,请求方法被认为是“幂等的” 使用该方法的多个相同请求的服务器是 与单个此类请求的效果相同 由本规范、 PUT、 删除和安全请求方法定义 是幂等的。
所以,它是在规范中写的,幂等性是关于对服务器的影响。第一个 DELETE 返回204,然后随后的 DELETE 返回404,这种不同的状态代码不会使 DELETE 非幂等。使用这个参数来证明随后的204返回是正确的,这根本无关紧要。
所以这不是关于幂等性。但是接下来的问题可能是,如果我们仍然选择在后续的 DELETE 中使用204会怎么样?可以吗?
问得好。其动机是可以理解的: 允许客户端仍然达到其预期的结果,而不用担心错误处理。我想说,在后续的 DELETE 中返回204,在很大程度上是一个无害的服务器端“善意的谎言”,客户端不会立即区分。这就是为什么有大约25% 的人在野外这样做,而且似乎仍然有效。请记住,这样的谎言在语义上可能被认为是奇怪的,因为 GET /non-exist返回404,而 DELETE /non-exist返回204,这时客户端会发现你的服务不完全符合 第6.5.4404节没有找到。
GET /non-exist
DELETE /non-exist
但是我想指出的是,RFC 7231所暗示的预期方式,即在后续的 DELETE 中返回404,从一开始就不应该是一个问题。3x 更多的开发人员选择这样做,你有没有听说过一个重大事件或抱怨造成的客户不能处理404?大概没有,这是因为,任何实现 HTTP DELETE (或任何 HTTP 方法)的客户端都不会盲目地认为结果总是成功的2xx。然后,一旦开发人员开始考虑错误处理,404Notfound 将是首先想到的错误之一。在这一点上,他/她可能会得出这样的结论: 对于 HTTP DELETE 操作来说,忽略404错误在语义上是安全的。他们这么做了。
问题解决了。