第二次使用 HTTPDELETE 删除资源时的状态代码

假设 HTTP 中的 DELETE 谓词是幂等的,当我发出以下请求时,第二个(或第三个,或第四个,等等)应该发生什么。.)时间到了吗?

DELETE /person/123

第一次,资源被删除,我返回一个204(成功,没有内容)。我应该在随后的呼叫中返回一个204还是一个404(未找到) ?

109880 次浏览

RESTful Web 服务食谱是一个很好的资源。它的谷歌预览偶然显示了关于 DELETE 的页面(第11页) :

DELETE 方法是幂等的 意味着服务器必须返回 响应代码200(OK) ,即使 服务器删除了 但实际上, 作为幂等元实现 DELETE 操作要求服务器保持 跟踪所有已删除的资源。 否则,它可以返回一个404(不 发现)。

由于无状态系统中的 HTTP 请求应该是独立的,因此一个请求的结果不应该依赖于以前的请求。考虑一下,如果两个用户同时对同一资源执行 DELETE,会发生什么情况。第二个请求得到404是有道理的。如果一个用户发出两个请求,也应该如此。

我猜,让 DELETE 返回两个不同的响应对您来说不会感到无能为力。我发现将幂等请求看作是使系统处于相同的状态,而不一定具有相同的响应是有用的。因此,无论您是 DELETE 现有资源,还是尝试 DELETE 不存在的资源,服务器资源状态都是相同的。

首先删除 : 200或204。

其后的 DELETE : 200或204。

基本原理: DELETE 应该是幂等的。如果在第二次删除时返回404,则响应将从 成功准则更改为 错误代码。基于 DELETE 失败的假设,客户端程序可能采取不正确的操作。

例子 :

  • 假设您的 DELETE 操作是客户端程序执行的多步操作(或“ saga”)的一部分。
  • 例如,客户端程序可以是执行银行交易的移动应用程序。
  • 假设客户机程序对 DELETE 操作有一个自动重试(这是有意义的,因为 DELETE 应该是幂等的)。
  • 假设第一个 DELETE 成功执行,但是200响应在传递到客户机程序的过程中丢失了。
  • 客户端程序将重试 DELETE。
  • 如果第二次尝试返回404,客户端程序可能会因为此错误代码而取消整个操作。
  • 但是因为第一个 DELETE 在服务器上成功执行,所以 系统可能处于不一致的状态
  • 如果第二次尝试返回200或204,客户端程序将按预期进行。

为了说明这种方法的使用,PayPal 的 HTTP API 样式指南有以下准则:

DELETE: 这个方法应该返回状态码204,因为在大多数情况下不需要返回任何内容,因为请求是要删除一个资源,并且它已经被成功删除。

因为 DELETE 方法也必须是幂等的,所以它仍然应该返回204,即使资源已经被删除。通常,API 使用者不关心资源是作为此操作的一部分删除的,还是在此操作之前删除的。这也是为什么应该返回204而不是404的原因。

我同意当前选择的答案所说的,即 第二(和第三,第四,...)删除应得到一个404。我注意到这个答案有143个赞成票,但也有一个相反的评论,有54个赞成票,所以社区被分成2个阵营,大约3:1的比例。这里有更多的信息来解决这个长期的争论。

  1. 首先,让我们不要从“我”怎么想,“你”怎么想,或者其他书作者怎么想开始。让我们从 HTTP 规范(即 RFC7231)开始。
  • 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会有什么不同呢? “那么等幂呢? !”,我能听到你在尖叫。等等,我们马上就要进入这个话题了。

  • 从历史上看,1999年发布的 RFC 2616是最常被引用的 HTTP 1.1规范。不幸的是,它对幂等性的描述是模糊的为所有这些辩论留下了空间。但是这个规格已经被 RFC 7231取代了。引自 RFC 7231,第4.2.2节,幂等方法,强调我的:

    如果预期的 EFFECT ON,请求方法被认为是“幂等的” 使用该方法的多个相同请求的服务器是 与单个此类请求的效果相同 由本规范、 PUT、 删除和安全请求方法定义 是幂等的。

    所以,它是在规范中写的,幂等性是关于对服务器的影响。第一个 DELETE 返回204,然后随后的 DELETE 返回404,这种不同的状态代码不会使 DELETE 非幂等。使用这个参数来证明随后的204返回是正确的,这根本无关紧要。

  1. 所以这不是关于幂等性。但是接下来的问题可能是,如果我们仍然选择在后续的 DELETE 中使用204会怎么样?可以吗?

    问得好。其动机是可以理解的: 允许客户端仍然达到其预期的结果,而不用担心错误处理。我想说,在后续的 DELETE 中返回204,在很大程度上是一个无害的服务器端“善意的谎言”,客户端不会立即区分。这就是为什么有大约25% 的人在野外这样做,而且似乎仍然有效。请记住,这样的谎言在语义上可能被认为是奇怪的,因为 GET /non-exist返回404,而 DELETE /non-exist返回204,这时客户端会发现你的服务不完全符合 第6.5.4404节没有找到

    但是我想指出的是,RFC 7231所暗示的预期方式,即在后续的 DELETE 中返回404,从一开始就不应该是一个问题。3x 更多的开发人员选择这样做,你有没有听说过一个重大事件或抱怨造成的客户不能处理404?大概没有,这是因为,任何实现 HTTP DELETE (或任何 HTTP 方法)的客户端都不会盲目地认为结果总是成功的2xx。然后,一旦开发人员开始考虑错误处理,404Notfound 将是首先想到的错误之一。在这一点上,他/她可能会得出这样的结论: 对于 HTTP DELETE 操作来说,忽略404错误在语义上是安全的。他们这么做了。

问题解决了。