For example you run a GET request for users/9
but there is no user with id #9.
Which is the best response code?
- 200 OK
- 202 Accepted
- 204 No Content
- 400 Bad Request
- 404 Not Found
For example you run a GET request for users/9
but there is no user with id #9.
Which is the best response code?
I'd say, neither is really appropriate. As has been said – e.g. by @anneb, I, too, think that part of the problems arises from using an HTTP response code to transport a status relating to a RESTful service. Anything the REST service has to say about its own processing should be transported by means of REST specific codes.
1
I'd argue that, if the HTTP server finds any service that is ready to answer a request it was sent, it should not respond with an HTTP 404 – in the end, something was found by the server – unless told so explicitly by the service that processes the request.
Let's assume for a moment the following URL:
http://example.com/service/return/test
.404
is correct. The same is true, if it asks some kind of service to deliver exactly this file and that service tells it that nothing of that name exists.Without any response from the service explicitly requiring a different behaviour, the HTTP server can only say 3 things:
503
if the service that is supposed to handle the request is not running or responding;200
otherwise as the HTTP server can actually satisfy the request – no matter what the service will say later;400
or404
to indicate that there is no such service (as opposed to “exists but offline”) and nothing else was found.2
To get back to the question at hand: I think the cleanest approach would be to not use an HTTP any response code at all other than said before. If the service is present and responding, the HTTP code should be 200. The response should contain the status the service returned in a separate header – here, the service can say
REST:EMPTY
e.g. if it was asked to search for sth. and that research returned empty;REST:NOT FOUND
if it was asked specifically for sth. “ID-like” – be that a file name or a resource by ID or entry No. 24, etc. – and that specific resource was not found (usually, one specific resource was requested and not found);REST:INVALID
if any part of the request it was sent is not recognized by the service.(note that I prefixed these with “REST:” on purpose to mark the fact that while these may have the same values or wording as do HTTP response codes, they are sth. completely different)
3
Let's get back to the URL above and inspect case B where service indicates to the HTTP server that it does not handle this request itself but passes it on to
SERVICE
. HTTP only serves out what it is handed back bySERVICE
, it does not know anything about thereturn/test
portion as that is handeled bySERVICE
. If that service is running, HTTP should return200
as it did indeed find something to handle the request.The status returned by
SERVICE
(and which, as said above, would like to see in a separate header) depends on what action is actually expected:return/test
asks for a specific resource: if it exists, return it with a status ofREST:FOUND
; if that resource does not exist, returnREST:NOT FOUND
; this could be extended to returnREST:GONE
if we know it once existed and will not return, andREST:MOVED
if we know it has gone hollywoodreturn/test
is considered a search or filter-like operation: if the result set is empty, return an empty set in the type requested and a status ofREST:EMPTY
; a set of results in the type requested and a status ofREST:SUCCESS
return/test
is not an operation recogized bySERVICE
: returnREST:ERROR
if it is completely wrong (e.g. a typo likeretrun/test
), orREST:NOT IMPLEMENTED
in case it is planned for later.4
This distinction is a lot cleaner than mixing the two different things up. It will also make debugging easier and processing only slightly more complex, if at all.
Summary
The problem and discussion arises from the fact that HTTP response codes are being used to denote the state of a service whose results are served by HTTP, or to denote sth. that is not in the scope of the HTTP server itself. Due to this discrepancy, the question cannot be answered and all opinions are subject to a lot of discussion.
The state of a request processed by a service and not the HTTP server REALLY SHOULD NOT (RFC 6919) be given by an HTTP response code. The HTTP code SHOULD (RFC 2119) only contain information the HTTP server can give from its own scope: namely, whether the service was found to process the request or not.
Instead, a different way SHOULD be used to tell a consumer about the state of the request to the service that is actually processing the request. My proposal is to do so via a specific header. Ideally, both the name of the header and its contents follow a standard that makes it easy for consumers to work with theses responses.
Encode the response content with a common enum that allows the client to switch on it and fork logic accordingly. I'm not sure how your client would distinguish the difference between a "data not found" 404 and a "web resource not found" 404? You don;t want someone to browse to userZ/9 and have the client wonder off as if the request was valid but there was no data returned.
In previous projects, I've used 404. If there's no user 9, then the object was not found. Therefore 404 Not Found is appropriate.
For object exists, but there is no data, 204 No Content would be appropriate. I think in your case, the object does not exist though.
Why not use 410? It suggests the requested resource no longer exists and the client is expected to never make a request for that resource, in your case
users/9
.You can find more details about 410 here: https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
204 is more appropriate. Especially when you have a alert system to ensure you website is secure, 404 in this case would cause confusion because you don't know some 404 alerts is backend errors or normal requests but response empty.
According to w3 post,
The request has succeeded. The information returned with the response is dependent on the method used in the request
The request has been accepted for processing, but the processing has not been completed.
The server has fulfilled the request but does not need to return an entity-body, and might want to return updated metainformation.
The request could not be understood by the server due to malformed syntax. The client SHOULD NOT repeat the request without modifications
The request requires user authentication. The response MUST include a WWW-Authenticate header field
The server has not found anything matching the Request-URI. No indication is given of whether the condition is temporary or permanent