Correct REST API Response HTTP Status Code - rest

I am creating a REST API which will run a simple database query and return some data, based on the payload.
If my SQL query returns no results then I am returning the plain text "No Records Found".
What HTTP response code would be appropriate for such an event. Is it 200 or 404.

If you are returning a JSON payload and your resource can be represented as a collection, then it makes sense to return 200 along with an empty array ([]) in the response payload.
If you are returning a single resource for a given identifier, and no resource can be found with the given identifier, then it makes sense to return 404.

Related

HTTP status while POST with incorrect data (using id of resource which does not exist)

What would be the correct HTTP status to return when I am performing the POST request to create a new user, but one of its parameters is incorrect - the company id I am including with the user data doesn't exist in the database.
POST
data: {username: 'newuser', age: 99, company_id: 34}
the company with id 34 does not exist in the database.
I was thinking whether that could be:
400, kind of invalid data, but it is valid but nonexistent id
404 - but it is not so clear which resource does not exist
409, because it is kind of conflict and the user can resolve that by changing the company id
422?
or 500 - because it is kind of database error while non existing id's are not allowed there
400 or 422
First of all, keep in min that it's a client error, so 5xx status codes are not suitable here. You should pick a 4xx status code then.
The most obvious options are 400 and 422:
If the JSON is syntactically invalid, return 400.
If JSON is syntactically valid but its content is invalid, return 422 to indicate that the request entity cannot be processed by the server.
See the following quote from the RFC 4918 (for your situation, just read JSON when it says XML):
11.2. 422 Unprocessable Entity
The 422 (Unprocessable Entity) status code means the server
understands the content type of the request entity (hence a
415 (Unsupported Media Type) status code is inappropriate), and the
syntax of the request entity is correct (thus a 400 (Bad Request)
status code is inappropriate) but was unable to process the contained
instructions. For example, this error condition may occur if an XML
request body contains well-formed (i.e., syntactically correct), but
semantically erroneous, XML instructions.
A similar situation was addressed in this answer.
For example purposes, the GitHub API v3 also returns 422 if the content of the payload contains invalid values (but is syntactically valid):
There are three possible types of client errors on API calls that
receive request bodies:
Sending invalid JSON will result in a 400 Bad Request response. [...]
Sending the wrong type of JSON values will result in a 400 Bad Request response. [...]
Sending invalid fields will result in a 422 Unprocessable Entity response. [...]
Michael Kropat put together a set of diagrams that's pretty insightful when it comes to picking the most suitable status code. See the following diagram for 4xx status codes:
404 Not Found is a problematic status to return for a POST request. It implies the resource you are sending the request to doesn't exist; the caller got the URL wrong.
The most obvious (and generic) answer is: 400 Bad Request
This just indicates there is something wrong with your request (the fault lies with the caller not the server) and then express the specific detail of what went wrong in your response body. This is typically how request validation is handled.
The ideal answer is to make it so you add a user by sending a request to the company they are a member of:
POST /company/34
Content-Type: application/json
{
"username": "newuser",
"age": 99
}
This means the caller has to find a valid company resource to send the request to. If company/34 doesn't exist, a 404 Not Found response is appropriate; you tried adding a user to a company which does not exist.
This does mean your API has to be structured with resource semantics and a user has to belong to exactly one company.
Here, this picture is very good, and I've used it many times.
Which code should I return?
I'd go with 404. The resource could exist (not a format error) but it just doesn't (and hence can't be found).

HTTP status code for GET request with non-existing query parameter value

Let's clarify three common scenarios when no item matches the request with a simple example:
GET /posts/{postId} and postId does not exist (status code 404, no question)
GET /posts?userId={userId} and the user with userId does not have any posts
GET /posts?userId={userId} and the user with userId does not exist itslef
I know there's no strict REST guideline for the appropriate status codes for cases 2 and 3, but it seems to be a common practice to return 200 for case 2 as it's considered a "search" request on the posts resource, so it is said that 404 might not be the best choice.
Now I wonder if there's a common practice to handle case 3. Based on a similar reasoning with case 2, 200 seems to be more relevant (and of course in the response body more info could be provided), although returning 404 to highlight the fact that userId itself does not exist is also tempting.
Any thoughts?
Ok, so first, REST doesn't say anything about what the endpoints should return. That's the HTTP spec. The HTTP spec says that if you make a request for a non-existent resource, the proper response code is 404.
Case 1 is a request for a single thing. That would return 404, as you said.
The resource being returned in case 2 is typically an envelope which contains metadata and a collection of things. It doesn't matter if the envelope has any things in it or not. So 200 is the correct response code because the envelope exists, it just so happens the envelope isn't holding any things. It would be allowable under the spec to say there's no envelope if there are no things and return 404, but that's usually not done because then the API can't send the metadata.
Case 3, then, is exactly the same thing as case 2. If expected response is an envelope, then the envelope exists whether or not the userId is valid. It would not be unreasonable to include metadata in the envelope pointing out that there is no user with userId, if the API designer thinks that information would be useful to clients.
Case 2 and Case 3 are really the same case, and should both either return 200 with an empty envelope or 404.
First piece, you need to recognize that /posts?userId={userId} identifies a resource, precisely in the same sense that /posts/{userId} or /index.html specifies a resource.
So GET /posts?userId={userId} "requests transfer of a current selected representation for the target resource."
The distinction between 200 and 404 is straight forward; if you are reporting to the consumer that "the origin server did not find a current representation for the target resource or is not willing to disclose that one exists", then you should be returning 404. If the response payload includes a current representation of the resource, then you should use the 200 status code.
404 is, of course, an response from the Client Error response class
the server SHOULD send a representation containing an explanation of the error situation, and whether it is a temporary or permanent condition.
So a way of figuring out which of these status codes to use, is to just look at the message body of the response. If it is a current representation of the resource, then you use the 200 status code. If it is a representation of a message that explains no current representation is available, then you use the 404 status code.
Of course that ducks the big question: what should the representation of the resource be in each case? Once you know that, you can work out the rest.
If you you think that an unexpected identifier indicates an error on the client (for example, a corrupted link), then it will probably improve the consumer's experience to report that as an explicit error, rather than returning a representation of an empty list.
But that's a judgment call; different API are going to have different answers, and HTTP isn't particularly biased one way or the other; HTTP just asks that you ensure that the response code and headers are appropriate for the choice that you have made.

HTTP 200 or 404 for empty list?

I know this is a fairly common question, but I haven't found an answer that satisfies me.
I've been using django rest framework for a while now, but this is mostly irrelevant other than the example given. Its default behaviour is to return an HTTP 200 with an empty list resource when accessing a route with an empty list of items.
E.g.: if we had a route such as /articles/ to access a list of articles but it contained no items we would get a response like the following json:
{"count":0, "next":null, "previous":null, "items": []}
Which is perfectly fine. We found the resource we were looking for at /articles/, it just happens to have no items in it.
If we access the route /articles/?page=1, we get the exact same response.
So far so good. Now we try to access /articles/?page=2, and the response code changes. Now get get a 404 as if the resource could not be found with an error message saying that the page contains no results. Which is the same case as with ?page=1...
I was perfectly ok with this behaviour, but today I started questioning this design. How is the ?page=1 case different than ?page=2 ? And what's more, how could you tell if the request was "valid" when issuing a HEAD request? Valid in the sense of containing any results.
This could be useful in cases like filtering a list checking the availability of a certain field (for example, issuing a HEAD request to /users/?username=ted).
A 200 response would clearly mean the request was understood and items were found.
A 404 would mean the request was understood, but no items were found at that location/URI (AFAIK the query parameters are also part of the URI)
In case the request could not be understood a 400 would be returned for syntactic errors, and a 422 for semantic errors.
Is this a good design? Why do most people seem to disagree with it and what drawbacks are there in it?
I would go for 200 because the resource is articles.
While querying for ted in users the same applies, users is the resource and as long it is there, a 200 is okay from my point of view.
If you would GET users/ted a 404 would be as good as a 410 (GONE) if a user named ted was there in the past (may better applies to articles than users).
Because we are ok with an empty page1, not ok with an empty page2.
This is driven by the UI consideration (page1 must exist!), nevertheless, it decides the response code.
This really boils down to the "null vs empty collection" argument. The cases for null are also cases for HTTP 404, and the cases for an empty collection are also cases for HTTP 200.
if we had a route such as /articles/ to access a list of articles but it contained no items
Assuming this is a global list of articles, i.e:
http://mywebsite/articles
then this response can never be null, and therefore should never be a 404. The global list of articles always exists, and therefore the collection is always not-null, regardless of whether it contains elements or not.
A simple example here is thinking of a SQL query. If a table exists, even if it's empty, a query will return a result (be it empty or not), so use 200. If the table itself does not exist, you get a query error, so 404.
But if the articles are contained within another resource, e.g. their author:
http://mywebsite/authors/johndoe/articles
Now we get to the part where null (and thus 404) is meaningfully possible.
If johndoe exists and has articles, you return a non-empty list
If johndoe exists and does not have articles, you return an empty list and HTTP status 200
If johndoe does not exist, then you return null and HTTP status 404
This communicates the correct response to the user. 200 reveals that the data was correctly fetched, whereas 404 reveals that the requested resource simply does not exist.
Note that this is slightly different when referring to a specific article instead of a list. When returning a specific resource (or not), instead of a list, 404 is the only correct HTTP status for a 'no item' response.
http://mywebsite/article/1
Here, you either return the article or null.
http://mywebsite/authors/johndoe/articles/1
Here, you return 404 when either author johndoe or article 1 does not exist.
200 simply means the request has succeeded. The information returned with the response is dependent on the method used in the request, for example:
GET an entity corresponding to the requested resource is sent in the response;
HEAD the entity-header fields corresponding to the requested resource are sent in the response without any message-body;
POST an entity describing or containing the result of the action;
TRACE an entity containing the request message as received by the end server.
404 - The server has not found anything matching the Request-URI - In this case I think it means we did not find the page that articles would have been listed on.
So 200 it is. - but perhaps understand what is being returned and format a message that 0 article have been returned.

Correct status code for no results because of an incorrect request

I've got a GET resource that takes a couple of parameters, let's call them CompanyId and CategoryId
This resource can return no results if either the CompanyId or CategoryId are invalid values (Ie: the CompanyId or CategoryId don't exist), or if they're valid, but we just don't have any data for them.
I'd like the client to be able to distinguish between the two cases, so simply returning a an empty 200 or 204 with no data for the former case isn't appropriate.
One way would be just to return a 200 with a message of "Company with Id of x does not exist, but this feels to me like a client error, they've supplied incorrect data.
Is it appropriate to use 422 'Unprocessable Entity' in this instance?
The HTTP response codes in the range of 4xx are for error in request, distinct from 5xx which are supposed to be sent after a server error.
Maybe in simple word:, 4xx if client or its request is bad, 500 if something went bad at server side.
400 Bad Request Is the standard and canonical status code for such event.
By default, web servers, web frameworks and also browsers will understand a 400 as Bad request but you should also provide a message in the response body explaining what went bad by the client.
See this Wikipedia article or this by W3C.
If your request isn't successful, you shouldn't use a status code 2xx.
I would rather return a status code 400 with a payload describing the problem (query parameter xx is required).
I would use a status 422 if a payload was sent with a method POST or PUT.
Hope it helps you.
Thierry

REST status code 204 on paginated result

I am designing a REST like API for paginated data retrieval of a YUI-based client.
The REST URL looks like this for a GET request:
/app/catalog/data?startIndex=<int>&results=<int>&sort=<sting>&dir=<string>
All parameters are optional, i.e. if no parameters are given, all data from DB will be dumped.
Now say that there are only 1000 records in the database. Following reqeust is made:
/app/catalog/data?startIndex=1100&results=25
What status code should I return if the paginated result from the database remains empty though the request was fine?! I can't decide whether this is 204 or 404.
The produced media types are JSON and CSV.
I would say 204 is most appropriate. The request was successful, just with no results.
10.2.5 204 No Content
The server has fulfilled the request but does not need to return an entity-body, and might want to return updated metainformation.
Sounds exactly like the case.
I can't decide whether this is 204 or 404.
Neither. Just return 200 with an empty result (empty XML document or JSON array, whatever you use). Typically I use REST services with paginated views so along with results page I return total number of records. This will help clients to realize the mistake. But technically it is nothing wrong.
Use 204 for DELETE operations (there's really no content to return) and for PUT.
BTW (bold mine):
if no parameters are given, all data from DB will be dumped
Believe, you don't want to do this...
What format do you normally return your results in? I'd be inclined to make this 204 or even 200 returning an empty list.
HTTP 204 in pagination response is not factible because of the payload. When paginating you should return pagination information like, items returned, total items, offset, etc. which makes no sense with HTTP 204.
HTTP 204 is useful on resource updates (ie PUT) when you want to explicitly say that the resource does not need to be fetched again (GET). For example, resources that have calculated fields and require a refresh of the view after every update, fetching those calculated fields from the server. Therefore, the 204 status code has specific use cases and must be designed and documented.
I would use one of:
HTTP 200 with count=0 and no items in the returned list.
HTTP 400 because invoker asked for an url that is invalid
HTTP 404 because items to return are not found
Choose the one that best suits the way your API works.
I think it's safe to return an error (4xx + error info) in this situation because the offset can be exceeded by one of these assumptions:
A coding error
Invoker is not fetching data from begining (no fresh state)
Invoker ignored pagination data (present on each response)
You are not using total field in the response (which is optional because there are some situations where you can not count all items or simply it's very expensive counting them). In this case, if your last page has the same number of items (count) as the number of items asked for in the request (limit), there is no way to know that this is the last page, so you try another one. In that last request you will get a count=0 in the response and you can stop asking for pages. This case makes it fair to return a 200 code also because the programmer did exactly what you asked for in the API documentation.