Is it to be considered good practice to reuse RFC HTTP Status codes like this, or should we be making up new ones that map exactly to our specific error reasons?
We're designing a web service API around a couple of legacy applications.
In addition to JSON/XML data structures in the Response Body, we aim to return HTTP Status Codes that make sense to web caches and developers.
But how do you go about mapping different classes of errors onto appropriate HTTP Status codes? Everyone on the team agrees on the following:
GET /package/1234 returns 404 Not Found if 1234 doesn't exist
GET /package/1234/next_checkpoint returns 400 Bad Request if "next_checkpoint" and 1234 are valid to ask for but next_checkpont here doesn't make sense...
and so on... but, in some cases, things needs to be more specific than just "400" - for example:
POST /dispatch/?for_package=1234 returns 412 Precondition Failed if /dispatch and package 1234 both exist, BUT 1234 isn't ready for dispatch just yet.
(Edit: Status codes in HTTP/1.1 and Status codes in WebDAV ext.)
RESTful use of HTTP means that you must keep the API uniform. This means that you cannot add domain specific methods (ala GET_STOCK_QUOTE) but it also means that you cannot add domain specific error codes (ala 499 Product Out Of Stock).
In fact, the HTTP client error codes are a good design check because if you design your resource semantics properly, the HTTP error code meanings will correctly express any errors. If you feel you need additional error codes, your resource design is likely wrong.
Jan
422 Unprocessable Entity is a useful error code for scenarios like this. See this question what http response code for rest service on put method when domain rules invalid for additional information.
GET /package/1234/next_checkpoint
returns 400 Bad Request if
"next_checkpoint" and 1234 are valid
to ask for but next_checkpont here
doesn't make sense...
This is the wrong way to think about that URI.
URIs are opaque, so observing that parts of it are 'valid' and others are not doesn't make any sense from a client perspective. Therefore you should 'just' return a 404 to the client, since the resource "package/1234/next_checkpoint" doesn't exist.
You should use 4xx series responses that best match your request when the client makes a mistake, though be careful to not use ones that are meant for specific headers or conditions. I tend to return a human-readable status message and either a plain-text version of the error as the response body or a structured error message, depending on application context.
Update: Upon further reading of the RFC, "procondition failed" is meant for the conditional headers, such as "if-none-match". I'd give a general 400 message for that instead.
Actually, you shouldn't do this at all. Your use of 404 Not Found
is correct, but 400 Bad Request
is being used improperly. A 400 Bad Request
according to the RFC is used solely when the HTTP protocol is malformed. In your case, the request is syntactically correct, it is just an unexpected argument. You should return a 500 Server Error
and then include an error code in your REST result.