tags:

views:

91

answers:

3

Using REST principles, 404 seems to be used to indicate that an entity does not exist. However, how can clients distinguish this case from hitting an incorrect endpoint altogether?

I want to distinguish between, "you came to the right endpoint, but that entity doesn't exist" and "you're not at the right endpoint". Technically, this can be distinguished using other response codes, custom headers, etc. but I am mainly concerned with REST best-practices in this area so clients are as simple and standard as possible.

+1  A: 

I believe the determination of the correct endpoint is the sole responsibility of the REST client. (Of course, an endpoint resolution service could be easily implemented.) A 404 error just means that this particular endpoint doesn't host that particular entity.

Nothing in RESTful design requires a server to know if a client is interacting with the "correct" host.

maerics
A: 

Assuming a framework laid out like this:

/ -- root
|____+
     /object
     |____+
          /members
          |____+
               /attributes
               |____+
                    /attribute_1
                    /attribute_2
                    ...
                    /attribute_n

 
If you mean that you want to be able to distinguish between someone hitting
/object/members/attributes/incorrect_attribute
(a 404 using all the right commands, but attempting to retrieve a non-existent resource)
and someone hitting /object/members/big-bird
(Assuming that members cannot be a valid endpoint on its own
[and that /object/members/attributes is not a valid endpoint either])
then I believe that you could return either a 501 error (not implemented) or a 403 error (Forbidden) depending on where you wanted to place the blame. (Alternately, 418 (I'm a teapot) is also valid here).

EDIT:
Finally, if attribute_n used to exist and no longer does, you could respond with a 410 (resource gone).

See: http://en.wikipedia.org/wiki/List_of_HTTP_status_codes

Sean Vieira
What happens if the teapot gets mislabeled as a coffee pot?
JAB
@JAB; then you should respond with a 424 (Failed dependency) since the teapot really ought to contain tea (Earl Grey, hot -- preferably).
Sean Vieira
Let me try and explain it this way: For a given server, the universe of all URLs returns 404 (except for the API we've defined). This is the same return code we use for a specific resource not existing. If someone typos /objec*k*/members/attributes/attribute_1, this returns 404. This may not be recognized by the client user very quickly because it was interpreted as attribute_1 doesn't exist when really a much more serious "error" occurred that wasn't communicated to the client properly.
jnorris
@jnorris - Precisely. If you want to communicate the idea "Your *doing* it wrong" (As opposed to "that is not here") then you should send either a 501 ("You're asking for something to be provided in a way we haven't provided for") or a 403 ("We will not give you that").
Sean Vieira
I can't send a "Your doing it wrong" because ever web service in the world returns a 404 for the universe of URLs that are non-existant. I can't change that. When 404 is also used for a business-level "entity doesn't exist", a client can't distinguish the difference. (Perhaps this problem is insignificant? Especially given the benefit of "fixing" it may be heavily outweighed by con of straying from best-practices).
jnorris
+3  A: 

you came to the right endpoint, but that entity doesn't exist

If there is no resource identified by the URL, how could it be the right endpoint? The only possible scenario I could think of is that the entity has been deleted, in which case 410 Gone is the correct response.

Remember that if you are following RESTful principles then the URL should have been provided by the server and if so, why is the server handing out invalid URLs?

Darrel Miller
There is a difference between a) no resource existing at an URL endpoint and b) no resource could ever exist at an endpoint (because it's structurally the wrong endpoint). HATEOAS principles only softens the effect of this because not all resource URLs are provided by the server (eg: entry points).
jnorris
Perhaps another way to state this difference is if a request was made to /employee/{employeeId}, it is nice to return something that says an employee with that ID does not exist, but if it did, this is the URL it would be at.
jnorris
I'm open to the possibility that this distinction isn't important in the practice. However, it seems like it is important. If an API changes, I want clients to "fail" properly, not just start reporting that all entities in the world don't exist.
jnorris
Don't forget that URLs are completely opaque to the client, therefore they cannot be expected to distinguish between `/Employee/34` where 34 does not exist and `/employeeasdf/uiop` I really don't see any value in attempt to return a different error code.
Darrel Miller
I don't think this is an issue of opacity. I think it's a matter of client configuration wrt the API. I think it would be very valuable to distinguish your example because in the first case, the client is configured correctly and the employee doesn't exist. In the second case, the client is configured incorrectly, but it still returns 404 so the user may not realize it is configured incorrectly. (Unfortunately, I don't think there is an easy solution to this that doesn't stray significantly from best-practices - which would be a bad tradeoff).
jnorris
Maybe it is an issue of opacity. However, I don't understand how opacity (http://www.w3.org/TR/webarch/#uri-opacity) reconciles with RESTful API design. For example if the API states that you can get employee data of some content-type at /employee/{employeeId}, can't I infer that the API URLs are as documented? If I infer this, am I violating the opacity principle? (Again, I realize that with good RESTful designs, most URLs are server generated according to HATEOAS principles, but not all (eg: entry points)).
jnorris
A RESTful API should never state that you can get employee data at /employee/{employeeId}. A RESTful API would say, when you receive the foo media type you will find a link relation bar that will allow you to retrieve an employee document by following the provided link.
Darrel Miller
You are basically asking for the server to be able to return an error code that says "badly formed identifier". However, considering clients are not supposed to construct identifiers, the error would be redundant.
Darrel Miller
That's interesting. 1) The API requires a documented entry point does it not? 2) Popular REST API frameworks like JAX-RS don't preclude you from doing HATEOAS (which is what I'm assuming you are referring to) but it isn't the path of least resistance by any means. Is this consequently a "bad" REST framework in your opinion? (I need to read the RESTful Web Services book again (http://oreilly.com/catalog/9780596529260) - do you have any other good REST book or article recommendations? Also, perhaps you can point to some public APIs that use the style you are recommending. Thanks)
jnorris
Darrel Miller
Are you suggesting a client should only create an endpoint URL (ie: hostname and base URL) then traverse links from there? Should every client go through this discovery mechanism? Is there every a place for clients to do "deep linking" (ie: analogous to deep WWW bookmarking)? If there is, then it would be nice to detect if the API url structure "breaks" in the future instead of just starting to return "entity doesn't exist" (at a business level) for every entity ID in the universe.
jnorris
@jnorris Yes. Yes. Yes. I understand your point and you have every right to choose that approach. However, that's not the way REST over HTTP says it should be done.
Darrel Miller