使用http DELETE删除资源

Cra*_*son 109 rest http http-delete

因此,假设Http中的DELETE谓词是幂等的,当我发出以下请求时,第二个(或第三个,或第四个,等等)会发生什么?

DELETE /person/123
Run Code Online (Sandbox Code Playgroud)

第一次,资源被删除,我返回204(成功,没有内容).我应该在后续电话或404(未找到)上返回204吗?

Dar*_*ler 136

作为一个无状态的系统的HTTP请求应该是独立的,一个请求的结果不应该依赖于先前的请求.考虑如果两个用户同时在同一资源上执行DELETE会发生什么.获取404的第二个请求是有意义的.如果一个用户发出两个请求,则同样应该如此.

我猜测让DELETE返回两个不同的响应对你来说并不是幂等的.我认为将幂等请求视为离开系统处于相同状态,而不一定具有相同的响应是有用的.因此,无论您是删除现有资源,还是尝试删除不存在的资源,服务器资源状态都是相同的.

  • 如果你删除了一些不存在的东西,你应该只返回一个204(即使资源从未存在过).客户希望资源消失,它就消失了.返回404正在暴露对客户端不重要的内部处理,并将导致不必要的错误情况. (51认同)
  • @DarrelMiller我想这里的关键概念是你不应该使用DELETE来检查资源是否存在,你首先要使用GET.然后,如果响应是200,则执行DELETE; 否则甚至懒得这样做.所以我认为总是在DELETE上返回204是有意义的. (8认同)
  • @Brian RFC说它应该表现得像`rm`.`rm`如果不存在则返回错误.https://tools.ietf.org/html/rfc7231#section-4.3.5 (7认同)
  • 谢谢.这非常有意义.我确实认为幂等因为回归同样的反应. (4认同)
  • @Craig小心!在Cookbook中,Subbu与我刚才所说的完全矛盾.他说幂等性意味着它应该返回相同的反应.幸运的是,Subbu将会参加RESTFest,所以,我将在那里与他澄清. (4认同)
  • @Brian 这是一种有趣的方法。就我个人而言,我想要某种确认我确实使用了正确的 Uri。用 204 换。我不知道服务器是否做了我想要的一切。 (2认同)
  • @布莱恩。你说返回 204,即使资源从未存在过。如果资源从未存在过,我想我想让客户端知道它只是试图删除从未存在过的东西。不管怎样,正如 Julian 在他的回答中提到的,HTTP 并不关心,做对你有用的事情。 (2认同)
  • @manei_cc如果你想检查资源是否存在,HEAD请求可能是更便宜的方式. (2认同)
  • @DarrelMiller,您在2011年问过Subbu吗?:) (2认同)
  • @DaxFohl 从技术上讲,它说“这种方法类似于 rm 命令”,我将其解释为类比,而不是行为建议。 (2认同)
  • 我编写了很多依赖于服务器端乐观并发的客户端代码。当服务器用成功代码响应冗余 DELETE 时,此类代码(其中条件(If-Match 等)GET、PATCH 和 DELETE 为规范)肯定会更简单。替代方案有些模糊,因为冗余 DELETE 上的 404 错误可能是客户端错误(错误的 URL)以及预期的“已经消失”。虽然可以处理 404,但这样做可能会掩盖其他“真实”错误情况。 (2认同)

Ray*_*Luo 42

我同意当前选择的答案所说的,即第二个(以及第三个、第四个……) DELETE 应该得到 404。而且,我注意到答案有 143 票赞成,但也有相反的评论,有 54 票赞成,因此社区以大约 3:1 的比例分为 2 个阵营。这里有更多信息来解决这场长期的争论。

  1. 首先,让我们不要从“我”的想法、“你”的想法或另一本书作者的想法开始。让我们从 HTTP 规范开始,即 RFC 7231。

    • RFC 7231 的第 4.3.5 节 DELETE碰巧只提到成功响应应该是 2xx,但它没有说明后续 DELETE 会得到什么。所以让我们深入挖掘。
    • RFC 7231,第 6.5.4 节 404 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, section 4.2.2 Idempotent Methods,强调我的:

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

      所以,它写在规范中,幂等性是关于对服务器的影响。第一个 DELETE 返回 204,然后随后的 DELETE 返回 404,这种不同的状态代码不会使 DELETE 非幂等。使用这个论点来证明随后的 204 返回是完全不相关的。

  2. 好的,所以这与幂等性无关。但是接下来的一个问题可能是,如果我们在后续的DELETE中仍然选择使用204呢?可以吗?

    好问题。动机是可以理解的:允许客户端仍然达到预期的结果,而不必担心错误处理。我会说,在随后的 DELETE 中返回 204,在很大程度上是无害的服务器端“善意的谎言”,客户端不会立即分辨出区别。这就是为什么有大约 25% 的人在野外这样做并且它似乎仍然有效。请记住,这种谎言在语义上可以被认为是奇怪的,因为GET /non-exist返回 404 但DELETE /non-exist给出 204,此时客户端会发现您的服务不完全符合第 6.5.4 节 404 Not Found

    但我想指出,RFC 7231 暗示的预期方式,即在随后的 DELETE 中返回 404,首先不应该成为问题。3 倍以上的开发人员选择这样做,您是否听说过由于客户端无法处理 404 导致的重大事件或抱怨?大概,不,那是因为,任何实现 HTTP DELETE(或任何 HTTP 方法,就此而言)的体面的客户端都不会盲目地假设结果总是成功 2xx。然后,一旦开发人员开始考虑错误处理,404 Not Found 将是第一个想到的错误之一。那时,他/她可能会得出结论,HTTP DELETE 操作忽略 404 错误在语义上是安全的。他们这样做了。

问题解决了。

  • +1“幂等性取决于对服务器的影响”。认真地回答了。做得好!我是后续 DELETE 请求的 404 信徒。 (7认同)
  • -1 _“所以,它是在规范中写的,幂等性是关于对服务器的影响。”_我以不同的方式准备了规范。它不是**对服务器的影响**(如服务器上发生的情况),而是**对服务器的预期影响**(调用者意图在服务器上发生的情况)。 (3认同)
  • @RémyvanDuijkeren,我们随时欢迎您的建设性讨论。关于您的评论,我不认为您对“打算”一词的强调会在这里产生什么影响。这句话“如果对服务器的预期效果......则请求方法被认为是*幂等*”正在谈论*幂等性*,而不是状态代码。虽然我们都同意 HTTP DELETE 是幂等的,但我的观点是状态代码无关紧要。您对 HTTP PUT 的其他引用也是无关紧要的,因为它是在不同的上下文中讨论客户端和服务器之间的 PUT 表示差异。 (3认同)
  • 你让我在 _`GET /non-exist` 返回 404 但 `DELETE /non-exist` 给出 204_ (2认同)

yve*_*lem 29

RESTful Web服务手册是一个很好的资源.偶然的机会,它的谷歌预览显示关于DELETE的页面(第11页):

DELETE方法是幂等的.这意味着即使服务器在先前的请求中删除了资源,服务器也必须返回响应代码200(OK).但实际上,将DELETE实现为幂等操作需要服务器跟踪所有已删除的资源.否则,它可以返回404(未找到).

  • 好吧,这本书错了.幂等性并不意味着状态代码将是相同的.与服务器的最终状态相关的是什么. (17认同)
  • @Craig阅读Cookbook,它说即使你已经删除它也应该返回200 OK.但是,在实践中需要服务器跟踪所有已删除的资源,因此,您可以使用404.它继续说安全问题可能要求您始终返回404. (6认同)
  • 续...这取决于您的情况。PayPal 返回相同的代码。像我这样的其他人想知道是否发现它并删除它。我对客户端进行了编程,我将按照我需要的方式处理它。在某些情况下我确实想知道。在其他情况下,只要不再存在,返回什么并不重要。有些例子说这样做,另一些则说相反。这取决于你和你的情况。如果您从不需要关心它是否删除了某些内容...返回相同的代码,只要适合您的项目,就使您的客户端代码更简单:) (2认同)

Pau*_*son 12

首先删除:200或204.

随后的DELETE:200或204.

理由:DELETE应该是幂等的.如果您在第二个DELETE上返回404,则您的响应将从成功代码更改为错误代码.客户端程序可能会根据DELETE失败的假设采取不正确的操作.

示例:

  • 假设您的DELETE操作是客户端程序执行的多步操作(或"saga")的一部分.
  • 例如,客户端程序可以是执行银行交易的移动应用程序.
  • 比方说,客户端程序有一个DELETE操作的自动重试(这是有道理的,因为DELETE应该是幂等).
  • 假设第一个DELETE已成功执行,但200个响应在前往客户端程序的过程中丢失了.
  • 客户端程序将重试DELETE.
  • 如果第二次尝试返回404,则客户端程序可以取消整个操作,因为该错误代码.
  • 但是因为第一个DELETE在服务器上成功执行,系统可能会处于不一致状态.
  • 如果第二次尝试返回200或204,则客户端程序将按预期继续.

  • 正如其他人提到的,幂等性不是您的响应代码,而是您的服务器状态。 (2认同)