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

发布于 2024-11-16 18:29:50 字数 176 浏览 8 评论 0原文

鉴于 HTTP 中的 DELETE 动词是幂等的,当我发出以下请求时,第二次(或第三次、第四次等...)发出请求时会发生什么?

DELETE /person/123

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

Given that the DELETE verb in HTTP is idempotent, when I issue the following request, what should happen the second (or third, or fourth, etc...) time I make it?

DELETE /person/123

The first time, the resource is deleted and I return a 204 (successful, no content). Should I return a 204 on subsequent calls or a 404 (not found)?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

烂柯人 2024-11-23 18:29:51

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

  1. 首先,我们不要从“我”的想法、“你”的想法或另一本书作者的想法开始。让我们从 HTTP 规范开始,即 RFC 7231。
  • RFC 7231,部分4.3.5 DELETE 碰巧只提到成功的响应应该是 2xx,但没有指出后续 DELETE 会得到什么。那么让我们深入挖掘一下。

  • RFC 7231,第 6.5.4 404 节未找到说 404 响应是资源不存在。由于没有调用特定的 http 方法(特别是不是 DELETE)来进行其他处理,因此我们可以直观地得到一个印象(这是正确的),即我的请求 DELETE /some/resource/which/does/not/存在应该导致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 幂等方法,强调我的:

    <块引用>

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

    所以,规范中是这么写的,幂等性就是对服务器的影响。第一个 DELETE 返回 204,随后的 DELETE 返回 404,这种不同的状态代码不会使 DELETE 非幂等。使用此参数来证明后续 204 返回的合理性是完全无关的。

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

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

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

问题解决了。

I agree with what the current chosen answer has said, that the 2nd (and 3rd, 4th, ...) DELETE should get a 404. And, I noticed that answer has 143 up votes but also has an opposite comment which has 54 up votes, so the community is divided into 2 camps in roughly 3:1 ratio. Here comes more information to settle this long time debate.

  1. First of all, let's NOT start with what "I" think, what "you" think, or what yet another book author thinks. Let's start with the HTTP specs i.e. RFC 7231.
  • RFC 7231, section 4.3.5 DELETE happened to only mention a successful response should be 2xx, but it did not call out what a subsequent DELETE would get. So let's dig deeper.

  • RFC 7231, section 6.5.4 404 Not Found says 404 response is for a resource does not exist. Since no specific http method (in particular, not DELETE) being called out to be treated otherwise, we can intuitively get an impression (and rightfully so), that my request DELETE /some/resource/which/does/not/exist should result in a 404. Then, DELETE /some/resource/which/happened/to/be/removed/by/someone/else/five/days/ago might as well also return a 404. Then, why should DELETE /some/resource/i/deleted/five/seconds/ago be any different?
    "But how about idempotency?!", I can hear you are screaming that. Hang on, we are about to get into that.

  • Historically, RFC 2616, published at 1999, was the most-referenced HTTP 1.1 specs. Unfortunately its description on idempotency was vague, that leaves room for all these debates. But that specs has been superseded by RFC 7231. Quoted from RFC 7231, section 4.2.2 Idempotent Methods, emphasis mine:

    A request method is considered "idempotent" if the intended EFFECT ON
    THE SERVER of multiple identical requests with that method is the
    same as the effect for a single such request.
    Of the request methods
    defined by this specification, PUT, DELETE, and safe request methods
    are idempotent.

    So, it is written in the specs, idempotency is all about the effect on the server. The first DELETE returning a 204 and then subsequent DELETE returning 404, such different status code does NOT make the DELETE non-idempotent. Using this argument to justify a subsequent 204 return, is simply irrelevant.

  1. OK so it is not about idempotency. But then a follow-up question may be, what if we still choose to use 204 in subsequent DELETE? Is it OK?

    Good question. The motivation is understandable: to allow the client to still reach its intended outcome, without worrying about error handling. I would say, returning 204 in subsequent DELETE, is a largely harmless server-side "white lie", which the client-side won't immediately tell a difference. That's why there are ~25% people doing that in the wild and it seemingly still works. Just keep in mind that, such lie can be considered semantically weird, because GET /non-exist returns 404 but DELETE /non-exist gives 204, at that point the client would figure out your service does not fully comply with section 6.5.4 404 Not Found.

    But I want to point out that, the intended way hinted by RFC 7231, i.e. returning 404 on subsequent DELETE, shouldn't be an issue in the first place. 3x more developers chose to do that, and did you ever hear a major incident or complain caused by a client not being able to handle 404? Presumably, nope, and that is because, any decent client which implements HTTP DELETE (or any HTTP method, for that matter), would not blindly assume the result would always be successful 2xx. And then, once the developer starts to consider the error handling, 404 Not Found would be one of the first errors that comes into mind. At that point, he/she would probably draw a conclusion that, it is semantically safe for an HTTP DELETE operation to ignore a 404 error. And they did so.

Problem solved.

你在看孤独的风景 2024-11-23 18:29:51

RESTful Web 服务食谱是这方面的一个很好的资源。偶然间,其 Google 预览 显示有关的页面删除(第 11 页):

DELETE 方法是幂等的。这
意味着服务器必须返回
响应代码 200(正常),即使
服务器删除了 a 中的资源
之前的请求。但在实践中,
将 DELETE 实现为幂等
操作需要服务器保存
跟踪所有已删除的资源。
否则,它可能会返回 404(不是
找到)。

The RESTful web services cookbook is a great resource for this. By chance, its google preview show the page about DELETE (page 11):

The DELETE method is idempotent. This
implies that the server must return
response code 200 (OK) even if the
server deleted the resource in a
previous request. But in practice,
implementing DELETE as an idempotent
operation requires the server to keep
track of all deleted resources.
Otherwise, it can return a 404 (Not
Found).

秋叶绚丽 2024-11-23 18:29:51

首次删除:200 或 204。

后续删除:200 或 204。

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

示例

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

只是为了说明此方法的使用, HTTP PayPal API 风格指南 具有以下准则:

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

由于 DELETE 方法也必须是幂等的,因此即使资源已被删除,它仍应返回 204。通常,API 使用者并不关心资源是否在此操作期间或之前被删除。这也是为什么应该返回204而不是404的原因。

First DELETE: 200 or 204.

Subsequent DELETEs: 200 or 204.

Rationale: DELETE should be idempotent. If you return 404 on a second DELETE, your response is changing from a success code to an error code. The client program may take incorrect actions based on the assumption the DELETE failed.

Example:

  • Suppose your DELETE operation is part of a multi-step operation (or a "saga") executed by the client program.
  • The client program may be a mobile app performing a bank transaction, for example.
  • Let's say the client program has an automatic retry for a DELETE operation (it makes sense, because DELETE is supposed to be idempotent).
  • Let's say the first DELETE was executed successfully, but the 200 response got lost on its way to the client program.
  • The client program will retry the DELETE.
  • If the second attempt returns 404, the client program may cancel the overall operation because of this error code.
  • But because the first DELETE executed successfully on the server, the system may be left at an inconsistent state.
  • If the second attempt returns 200 or 204, the client program will proceed as expected.

Just to illustrate the use of this approach, the HTTP API style guide for PayPal has the following guideline:

DELETE: This method SHOULD return status code 204 as there is no need to return any content in most cases as the request is to delete a resource and it was successfully deleted.

As the DELETE method MUST be idempotent as well, it SHOULD still return 204, even if the resource was already deleted. Usually the API consumer does not care if the resource was deleted as part of this operation, or before. This is also the reason why 204 instead of 404 should be returned.

沙沙粒小 2024-11-23 18:29:51

我将把 410 Gone 加入其中。 RFC 7231,第 6.5.4 410 节已消失

410(Gone)状态码表示访问目标
源服务器上的资源不再可用,并且此
这种情况可能是永久性的。

因此,204 表示第一个 DELETE410 表示后续的 DELETE。它也很好而且一致,因为 GETPUT 等也会返回 410

但是,这需要服务器跟踪已删除的内容,并且规范确实继续说道

如果源服务器不知道,或者没有能力确定,
无论该情况是否是永久性的,状态代码 404(不是
发现)应该改用。

因此,如果跟踪已删除的资源很有价值(例如,如果您需要防止重新创建它们),请使用 410,否则, 404 如本答案中建议的,或者换句话说"it取决于”

I'm going to throw 410 Gone into the mix. RFC 7231, section 6.5.4 410 Gone says

The 410 (Gone) status code indicates that access to the target
resource is no longer available at the origin server and that this
condition is likely to be permanent.

So 204 for the first DELETE and 410 for the subsequent DELETEs. It's nice and consistent too, as a GET, PUT, etc will also return 410.

However, it would require the server to keep track of what has been deleted and the spec does go on to say

If the origin server does not know, or has no facility to determine,
whether or not the condition is permanent, the status code 404 (Not
Found) ought to be used instead.

So, if it's valuable to keep track of deleted resources (e.g. if you need to prevent them from being re-created), 410, otherwise, 404 as recommended in this answer, or in other words "it depends".

浅沫记忆 2024-11-23 18:29:51

据我观察,大多数开发人员倾向于使用 200 作为 DELETE 请求的响应代码,无论资源是否存在。然而,正确的做法是,只有删除现有记录后操作成功才返回 200,如果没有找到所请求的资源,则返回 404。 404 状态代码专门针对未找到资源,而不仅仅是针对未找到页面错误。

https://developer.mozilla.org/en-US/ docs/Web/HTTP/Status/404

因此,我建议使用 200 来成功操作,使用 404 来表示缺少资源。它还可以帮助管理测试用例以确保正确实施。

As far as I've observed, most developers tend to use 200 as the response code for DELETE requests, regardless of whether the resource exists or not. However, the correct approach would be to return 200 only if the operation is successful after deleting an existing record, and 404 if the resource being requested is not found. The 404 status code is specifically meant for resource not found, and not just for page not found errors.

https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/404

Therefore, I recommend using 200 for successful operations and 404 for missing resources. It can also assist in managing the test cases to ensure proper implementation.

谁的年少不轻狂 2024-11-23 18:29:51

另一种选择:

始终返回200(确定),输出删除的资源数量(0 或1)。

优点:

  • 如果您有另一条允许通过搜索/过滤删除多个对象的路线,那么它是一致的。
  • API 的用户始终知道资源是否被删除(并且检查很简单)。
  • 状态码保持不变,感觉不错;至少对我来说。
  • 返回已删除文档/行/对象的数量(可以为 0)的方法在数据库中很常见。

Another alternative:

Always return 200 (OK) outputting the number of resources deleted (0 or 1).

Benefits:

  • It's consistent if you have another route that permits deleting multiple objects by search/filtering.
  • The user of your API always knows if a resource got deleted or not (and the check is trivial).
  • The status code remains the same, which feels right; at least to me.
  • The approach of returning the number of deleted documents/rows/objects (which can be 0) is common in databases.
<逆流佳人身旁 2024-11-23 18:29:50

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

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

As HTTP requests in a stateless system should be independent, the results of one request should not be dependent on a previous request. Consider what should happen if two users did a DELETE on the same resource simultaneously. It makes sense for the second request to get a 404. The same should be true if one user makes two requests.

I am guessing that having DELETE return two different responses does not feel idempotent to you. I find it useful to think of idempotent requests as leaving the system in the same state, not necessarily having the same response. So regardless of whether you DELETE an existing resource, or attempt to DELETE a resource that does not exist, the server resource state is the same.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文