Status code when deleting a resource using HTTP DELETE for the second time
Given t开发者_高级运维hat 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)?
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.
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.
- 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 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:
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.
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.
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).
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.
精彩评论