I'm building a REST API, but I've encountered a problem.
It seems that accepted practice in designing a REST API is that if the resource requested doesn't exist, a 404 is returned.
However, to me, this adds unnecessary ambiguity. HTTP 404 is more traditionally associated with a bad URI. So in effect we're saying "Either you got to the right place, but that specific record does not exist, or there's no such location on the Internets! I'm really not sure which one..."
Consider the following URI:
http://mywebsite/api/user/13
If I get a 404 back, is that because User 13 does not exist? Or is it because my URL should have been:
http://mywebsite/restapi/user/13
In the past, I've just returned a NULL result with an HTTP 200 OK
response code if the record doesn't exist. It's simple, and in my opinion very clean, even if it's not necessarily accepted practice. But is there a better way to do this?
As with most things, "it depends". But to me, your practice is not bad and is not going against the HTTP spec per se. However, let's clear some things up.
First, URI's should be opaque. Even if they're not opaque to people, they are opaque to machines. In other words, the difference between
http://mywebsite/api/user/13
,http://mywebsite/restapi/user/13
is the same as the difference betweenhttp://mywebsite/api/user/13
andhttp://mywebsite/api/user/14
i.e. not the same is not the same period. So a 404 would be completely appropriate forhttp://mywebsite/api/user/14
(if there is no such user) but not necessarily the only appropriate response.You could also return an empty 200 response or more explicitly a 204 (No Content) response. This would convey something else to the client. It would imply that the resource identified by
http://mywebsite/api/user/14
has no content or is essentially nothing. It does mean that there is such a resource. However, it does not necessarily mean that you are claiming there is some user persisted in a data store with id 14. That's your private concern, not the concern of the client making the request. So, if it makes sense to model your resources that way, go ahead.There are some security implications to giving your clients information that would make it easier for them to guess legitimate URI's. Returning a 200 on misses instead of a 404 may give the client a clue that at least the
http://mywebsite/api/user
part is correct. A malicious client could just keep trying different integers. But to me, a malicious client would be able to guess thehttp://mywebsite/api/user
part anyway. A better remedy would be to use UUID's. i.e.http://mywebsite/api/user/3dd5b770-79ea-11e1-b0c4-0800200c9a66
is better thanhttp://mywebsite/api/user/14
. Doing that, you could use your technique of returning 200's without giving much away.The Uniform Resource Identifier is a unique pointer to the resource. A poorly form URI doesn't point to the resource and therefore performing a GET on it will not return a resource. 404 means The server has not found anything matching the Request-URI. If you put in the wrong URI or bad URI that is your problem and the reason you didn't get to a resource whether a HTML page or IMG.
This old but excellent article... http://www.infoq.com/articles/webber-rest-workflow says this about it...
404 Not Found - The service is far too lazy (or secure) to give us a real reason why our request failed, but whatever the reason, we need to deal with it.
So in essence, it sounds like the answer could depend on how the request is formed.
If the requested resource forms part of the URI as per a request to
http://mywebsite/restapi/user/13
and user 13 does not exist, then a 404 is probably appropriate and intuitive because the URI is representative of a non-existent user/entity/document/etc. The same would hold for the more secure technique using a GUIDhttp://mywebsite/api/user/3dd5b770-79ea-11e1-b0c4-0800200c9a66
and the api/restapi argument above.However, if the requested resource ID was included in the request header [include your own example], or indeed, in the URI as a parameter, eg
http://mywebsite/restapi/user/?UID=13
then the URI would still be correct (because the concept of a USER does exits athttp://mywebsite/restapi/user/
); and therefore the response could reasonable be expected to be a 200 (with an appropriately verbose message) because the specific user known as 13 does not exist but the URI does. This way we are saying the URI is good, but the request for data has no content.Personally a 200 still doesn't feel right (though I have previously argued it does). A 200 response code (without a verbose response) could cause an issue not to be investigated when an incorrect ID is sent for example.
A better approach would be to send a
204 - No Content
response. This is compliant with w3c's description *The server has fulfilled the request but does not need to return an entity-body, and might want to return updated metainformation.*1 The confusion, in my opinion is caused by the Wikipedia entry stating 204 No Content - The server successfully processed the request, but is not returning any content. Usually used as a response to a successful delete request. The last sentence is highly debateable. Consider the situation without that sentence and the solution is easy - just send a 204 if the entity does not exist. There is even an argument for returning a 204 instead of a 404, the request has been processed and no content has been returned! Please be aware though, 204's do not allow content in the response bodySources
http://en.wikipedia.org/wiki/List_of_HTTP_status_codes 1. http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
Use
404
if the resource does not exist. Don't return200
with an empty body.This is akin to
undefined
vs empty string (e.g.""
) in programming. While very similar, there is definitely a difference.404
means that nothing exists at that URI (like an undefined variable in programming). Returning200
with an empty body means that something does exist there and that something is just empty right now (like an empty string in programming).404
doesn't mean it was a "bad URI". There are special HTTP codes that are intended for URI errors (e.g.414 Request-URI Too Long
).404 Not Found technically means that uri does not currently map to a resource. In your example, I interpret a request to
http://mywebsite/api/user/13
that returns a 404 to imply that this url was never mapped to a resource. To the client, that should be the end of conversation.To address concerns with ambiguity, you can enhance your API by providing other response codes. For example, suppose you want to allow clients to issue GET requests the url
http://mywebsite/api/user/13
, you want to communicate that clients should use the canonical urlhttp://mywebsite/restapi/user/13
. In that case, you may want to consider issuing a permanent redirect by returning a 301 Moved Permanently and supply the canonical url in the Location header of the response. This tells the client that for future requests they should use the canonical url.