第二次使用 HTTP DELETE 删除资源时的状态代码
鉴于 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
我同意当前选择的答案所说的,第二个(和第三个、第四个……)删除应该得到 404。而且,我注意到该答案有 143 票赞成,但也有一个相反的评论,有 54 票赞成,因此社区被分为 2 个阵营,比例约为 3:1。这里有更多信息来解决这场长期争论。
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 返回的合理性是完全无关的。
好的,所以这与幂等性无关。但接下来的一个问题可能是,如果我们在后续的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.
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 shouldDELETE /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:
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.
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 butDELETE /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.
RESTful Web 服务食谱是这方面的一个很好的资源。偶然间,其 Google 预览 显示有关的页面删除(第 11 页):
The RESTful web services cookbook is a great resource for this. By chance, its google preview show the page about DELETE (page 11):
首次删除:200 或 204。
后续删除:200 或 204。
基本原理< /strong>:DELETE 应该是幂等的。如果您在第二次 DELETE 时返回 404,则您的响应将从成功代码更改为错误代码。客户端程序可能会基于 DELETE 失败的假设而采取不正确的操作。
示例:
只是为了说明此方法的使用, HTTP PayPal API 风格指南 具有以下准则:
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:
Just to illustrate the use of this approach, the HTTP API style guide for PayPal has the following guideline:
我将把
410 Gone
加入其中。 RFC 7231,第 6.5.4 410 节已消失 说因此,
204
表示第一个DELETE
,410
表示后续的DELETE
。它也很好而且一致,因为GET
、PUT
等也会返回410
。但是,这需要服务器跟踪已删除的内容,并且规范确实继续说道
因此,如果跟踪已删除的资源很有价值(例如,如果您需要防止重新创建它们),请使用 410,否则, 404 如本答案中建议的,或者换句话说"it取决于”。
I'm going to throw
410 Gone
into the mix. RFC 7231, section 6.5.4 410 Gone saysSo
204
for the firstDELETE
and410
for the subsequentDELETE
s. It's nice and consistent too, as aGET
,PUT
, etc will also return410
.However, it would require the server to keep track of what has been deleted and the spec does go on to say
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".
据我观察,大多数开发人员倾向于使用 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.
另一种选择:
始终返回200(确定),输出删除的资源数量(0 或1)。
优点:
Another alternative:
Always return 200 (OK) outputting the number of resources deleted (0 or 1).
Benefits:
由于无状态系统中的 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.