Should I return a 410 Gone in response to a successful HTTP DELETE request? - rest

I'm implementing DELETE support on a ReST API (build on ServiceStack) and wondering what response code to return following a successful DELETE.
HTTP defines 410 as:
The requested resource is no longer available at the server and no forwarding address is known. This condition is expected to be considered permanent. Clients with link editing capabilities SHOULD delete references to the Request-URI after user approval. If the server does not know, or has no facility to determine, whether or not the condition is permanent, the status code 404 (Not Found) SHOULD be used instead. This response is cacheable unless indicated otherwise.
Now, if a resource has just been DELETEd, I probably do want many of those recommendations to apply... but accepted practice seems to be returning a 200 OK following a successful DELETE - especially since the 4XX range is supposed to denote error conditions.
Any compelling arguments one way or another beyond the guidelines in the HTTP spec?

RFC 2616 Section 9.7 specifically states the following regarding the response for DELETE:
A successful response SHOULD be 200 (OK) if the
response includes an entity describing the status,
202 (Accepted) if the action has not yet been
enacted, or 204 (No Content) if the action has been
enacted but the response does not include an entity.

Related

REST: which HTTP Status for rejecting method on current state of resource

Imagine the following scenario:
The clients wants to change the state of a resource (e.g Order) via PUT.
The method is allowed for this resource, but the final state change to orderState=payed requires some precondition (like POSTing a valid payment resource to the order).
So PUT is only allowed when the target resource is in a specific state.
What would be a suitable response code?
I think that 405 - Method Not Allowed doesn't really fit to this scenario as it implies that the client can't use PUT at all on that resource.
I'm currently considering 409, 423, 424 and 428 but I'd like to know if there are some best practices regarding this specific scenario.
I would expect 405 Method Not Allowed to cover your case:
The 405 (Method Not Allowed) status code indicates that the method received in the request-line is known by the origin server but not supported by the target resource. The origin server MUST generate an Allow header field in a 405 response containing a list of the target resource's currently supported methods.
My reading is that "currently supported" implies that the list of supported methods may evolve over time.
403 Forbidden is also fine:
The 403 (Forbidden) status code indicates that the server understood the request but refuses to authorize it.... a request might be forbidden for reasons unrelated to the credentials.
As with any 4xx class status-code, the message-body should include "a representation containing an explanation of the error situation", which is where you insert the explanation of the problem.

RESTful API: Delete Entity - What should I return as result?

I am implementing a RESTful API and an endpoint of one controller is Delete. Delete does two actions depending of the entity to be removed: it updates the entity or it deletes the entity from the database. If delete updates the entity I would send the HttpStatus 200 and the updated entity. But if the delete removes the entity from the database I would send only the HttpStatus 200. In one case I am returning an object. But in the other case, the object doesn't existe any more. Is it a good approach or I am missing anything?
Short answer
The suitable status codes for a DELETE request that has succeeded are 200, 202 and 204.
Long answer
DELETE does two actions depending of the entity to be removed: it updates the entity or it deletes the entity from the database. [...] Is it a good approach or I am missing anything?
The DELETE method is not meant for performing updates.
See the following quote from the RFC 7231, one of the documents the define the HTTP/1.1 protocol, for details on what the DELETE method is about:
4.3.5. DELETE
The DELETE method requests that the origin server remove the
association between the target resource and its current
functionality. In effect, this method is similar to the rm command
in UNIX: it expresses a deletion operation on the URI mapping of the
origin server rather than an expectation that the previously
associated information be deleted. [...]
If the delete operation has succeded, the server can return one of the following status codes:
202: Indicates that the request has been accepted for processing, but the processing has not been completed.
204: Indicates that the server has
successfully fulfilled the request and that there is no additional
content to send in the response payload body.
200: Indicates that the request has succeeded and the request payload includes a representation of the status of the action.
See the following quote from the same document:
If a DELETE method is successfully applied, the origin server SHOULD
send a 202 (Accepted) status code if the action will likely succeed
but has not yet been enacted, a 204 (No Content) status code if the
action has been enacted and no further information is to be supplied,
or a 200 (OK) status code if the action has been enacted and the
response message includes a representation describing the status.
The commonly considered HTTP Statuses for DELETE include:
200 OK (MDN)
202 Accepted (MDN)
204 No Content (MDN)
204 is ideal if your service is not returning any additional info. It is also popular for PUT update requests. Many services return 204 including Docker as shown below:
Ref: https://docs.docker.com/engine/api/v1.24/
However, if you are implementing HATEOAS, it is better to use 200 OK and provide some links for the service. Think of an application that has just issued a delete and needs to navigate a user to a location. Without providing a URL for that location, the client app needs to keep state. Providing a 200 OK with a link allows the REST API to keep state for the client.
The following article describes this issue well (read the blog for more discussion):
Avoid 204 responses if you're building a HATEOAS application.
This is a lesson about REST API design that I learned while building non-trivial REST APIs. In order to be as supportive of the client as possible, a REST API should not return 204 (No Content) responses.
From the service's perspective, a 204 (No Content) response may be a perfectly valid response to a POST, PUT or DELETE request. Particularly, for a DELETE request it seems very appropriate, because what else can you say?
However, from the perspective of a proper HATEOAS-aware client, a 204 response is problematic because there are no links to follow. When hypermedia acts as the engine of application state, when there are no links, there's no state. In other words, a 204 response throws away all application state.
If a client encounters a 204 response, it can either give up, go to the entry point of the API, or go back to the previous resource it visited. Neither option is particularly good.
Ref: http://blog.ploeh.dk/2013/04/30/rest-lesson-learned-avoid-204-responses/

What should be the API Response for already performed or unneeded operations

What response (code + content) should I return when my JsonAPI is requested to perform some operation that has already been done or does not make sense ?
Example : suppose I want to request an article publication. The article draft is updated through a specific endpoint (irrelevant here), and there is a specific endpoint one for publication (whose response we are interested in)
4 different scenarii, I need to figure out what type of response to send each time :
Publication had never been requested, and the article has all publication mandatory information, it makes sense to request publication so I'm returning a 202 accepted response with the article resource including the "publication requested at" attribute
A successful publication publication request was already sent/acknowledged, and no one had time to review it in between. What should I return ?
A previous publication request was reviewed by someone and accepted (the article is now published). The API receives once more a publication request to this article that was already published, it doesn't make sense, what should I return ?
The article does not have all mandatory information filled and someones make a publication request. I must inform the user his request was not granted because of errors. I was thinking for this one I could return the list of validation errors. Sounds fair ?
Your first two bullets...
Publication had never been requested, and the article has all publication mandatory information, it makes sense to request publication so I'm returning a 202 accepted response with the article resource including the "publication requested at" attribute
A successful publication publication request was already sent/acknowledged, and no one had time to review it in between. What should I return ?
...are amenable to 202 Accepted:
202 Accepted: The request has been accepted for processing, but the processing has not been completed. The request might or might not be eventually acted upon, and may be disallowed when processing occurs.
Your third bullet:
A previous publication request was reviewed by someone and accepted (the article is now published). The API receives once more a publication request to this article that was already published, it doesn't make sense, what should I return ?
I would probably use a 303 redirect here:
303 See other: The response to the request can be found under another URI using a GET method. When received in response to a POST (or PUT/DELETE), the client should presume that the server has received the data and should issue a redirect with a separate GET message.
But you could also consider a 308 permanent redirect:
308 Permanent Redirect (RFC 7538): The request and all future requests should be repeated using another URI. 307 and 308 parallel the behaviors of 302 and 301, but do not allow the HTTP method to change. So, for example, submitting a form to a permanently redirected resource may continue smoothly.
But I'd lean towards the 303.
And your last bullet:
The article does not have all mandatory information filled and someones make a publication request. I must inform the user his request was not granted because of errors. I was thinking for this one I could return the list of validation errors. Sounds fair ?
This is a standard "bad client request" (4xx) with errors:
400 Bad Request: The server cannot or will not process the request due to an apparent client error (e.g., malformed request syntax, too large size, invalid request message framing, or deceptive request routing).
Just make sure you don't expose the implementation details of your service when you enumerate the errors in your response.
Remember:
2xx responses indicate success
3xx responses indicate redirection
4xx responses indicate a failure on the part of the client
5xx responses indicate a failure on the part of the application servicing the request
Source: List of HTTP status codes

What HTTP code return when record is in inappropriate state?

I need to set particular resource accessible via REST Api to one of defined states - idle, running or stopped. How to inform a REST API client that record is already in requested state? E.g. client wants to start the record and that record is already running? He needs to know that record is running and operation is not processable.
It's definitively client error, so status code from 4xx family should be the answer. I have an idea to use 400, 409 or 412 but not sure.
There is "look-before-you-leap" technique that might be useful here.
You could insert If-Match header in your PUT (I assume its PUT) request
PUT /states HTTP/1.1
Host: www.example.com
Content-Type: text/plain
If-Match: "running"
Running
Either you get 200 or 412 (Precondition Failed).
How to inform a REST API client that record is already in requested state
Closest I could find is
409 Conflict
The request could not be completed due to a conflict with the current state of the resource. This code is only allowed in situations where it is expected that the user might be able to resolve the conflict and resubmit the request. The response body SHOULD include enough information for the user to recognize the source of the conflict. Ideally, the response entity would include enough information for the user or user agent to fix the problem; however, that might not be possible and is not required.
Conflicts are most likely to occur in response to a PUT request. For example, if versioning were being used and the entity being PUT included changes to a resource which conflict with those made by an earlier (third-party) request, the server might use the 409 response to indicate that it can't complete the request. In this case, the response entity would likely contain a list of the differences between the two versions in a format defined by the response Content-Type.
emphasis mine
RFC 2616

What should return if a client issues a DELETE to a web API resource which doesn't exist

Sometimes clients have outdated info which may result in them superfluously issuing
DELETE theApiURL/theEntity/1234
The first time this request is issued and all goes well we return 204
Any subsequent times there is no inherent error condition and the server will delete any entity at the identified location, but that entity may not exist. So the operation of "delete the entity with id 1234" completes successfully.
I could return 404 because that entity doesn't exist.
I could return 2xx because the request completed "successfully"... might a 205 be appropriate here to indicate that the request completed fine, but that the user should refresh their content?
I would return 404.
Unless you know that resource existed at some point and want to inform that to the consumer, in which case 410 seems appropriate. But defaulting to 410 seems wrong if you are not checking if the resource has ever existed.
I feel that trying to delete something which doesn't exist is a client-error. I think that 404 isn't right in this case because the DELETE request was found and it did work.
410 GONE makes sense to me. The entity has been deleted and is GONE and it is up to the client to remove that link.
What made me think to use 410 is the this clause: If the server does not know, or has no facility to determine, whether or not the condition is permanent, the status code 404 (Not Found) SHOULD be used instead. We can determine and know that the entity is deleted and gone forever (unless you reuse ids).
Per RFC 2616:
10.4.5 404 Not Found
The server has not found anything matching the Request-URI. No indication is given of whether the condition is temporary or permanent. The 410 (Gone) status code SHOULD be used if the server knows, through some internally configurable mechanism, that an old resource is permanently unavailable and has no forwarding address. This status code is commonly used when the server does not wish to reveal exactly why the request has been refused, or when no other response is applicable.
...
10.4.11 410 Gone
The requested resource is no longer available at the server and no forwarding address is known. This condition is expected to be considered permanent. Clients with link editing capabilities SHOULD delete references to the Request-URI after user approval. If the server does not know, or has no facility to determine, whether or not the condition is permanent, the status code 404 (Not Found) SHOULD be used instead. This response is cacheable unless indicated otherwise.
The 410 response is primarily intended to assist the task of web maintenance by notifying the recipient that the resource is intentionally unavailable and that the server owners desire that remote links to that resource be removed. Such an event is common for limited-time, promotional services and for resources belonging to individuals no longer working at the server's site. It is not necessary to mark all permanently unavailable resources as "gone" or to keep the mark for any length of time -- that is left to the discretion of the server owner.
So, after the initial DELETE is successful, any subsequent request for the resource should return 410 if the server knows the resource once existed, otherwise return 404 instead.