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.
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
or 404
to indicate that there is no such service (as opposed to “exists but offline”) and nothing else was found.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)
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 by SERVICE
, it does not know anything about the return/test
portion as that is handeled by SERVICE
. If that service is running, HTTP should return 200
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 of REST:FOUND
; if that resource does not exist, return REST:NOT FOUND
; this could be extended to return REST:GONE
if we know it once existed and will not return, and REST: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 of REST:EMPTY
; a set of results in the type requested and a status of REST:SUCCESS
return/test
is not an operation recogized by SERVICE
: return REST:ERROR
if it is completely wrong (e.g. a typo like retrun/test
), or REST:NOT IMPLEMENTED
in case it is planned for later.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.
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.