Should I use different satus codes in restful api, instead only 200? - rest

I'm developming RESTful API service. I've got disagreement between Me and my Team Lead, on the subject: "HTTP Response status codes".
My Team Lead talks, that default HTTP status codes written in RFC is awful and it's very hard to handle them on the client side(frontend). He thinks that custom status codes in response body, with HTTP status code 200 (every time 200) - the best way. His response body will like following, when trying to execute action without permissions:
HTTP/1.1 200 OK
{
code: 1005, // Custom code instead 403
data: {
message: "Forbidden."
}
}
I think that is wrong way to response. My response scheme will be like this:
HTTP/1.1 403 Forbidden
{
code: 403,
success: false,
message: "Forbidden."
}
Should we use RFC HTTP status codes, or we can use our own custom? Where is the best and right way?

The short
You are absolutely right.
The long answer
In restful API design you have to make use of the official HTTP codes specified in RFC-7231. Please do not send a 200 OK for every request. 200 OK is reserved for requests which actually succeeded and the server responds with a valid state of a particular resource. There are codes for most use cases. If you still need to differ errors of the same type, for example FORBIDDEN you may send a custom error code along. But the HTTP response is still an error therefore you shall not use 200 OK.
Regarding your proposed error scheme, you should not send the code and status within the body. This is already sent as the HTTP status and therefore redundant. Also a boolean success flag is redundant since the type of HTTP code already points out if it was a success or not (2xx => success, 4xx client error, 5xx server error).
The body should contain additional context which will help an API client to resolve the problem.
A well designed API error response should contain helpful information to fix a possible problem:
Request ID which gets generated per request on the server
Detailed error message
(Optional) Internal error code
(Optional) Error category
(Optional) Reference to the api documentation/error description
Example:
HTTP/1.1 403 Forbidden
{
"requestId": "a5e5dd13-0047-4d2e-b96c-55a5031f0511",
"message": "You are not allowed to access this resource. Missing write permission.",
"category": "AccessControl"
}
If this still is not enough for your team lead to believe you may point out some well designed REST API's:
GitHub API v3
Kubernetes API

Related

What should be the response status code when data present in body is not found in DB

The request sent to api is :
url: /users/{userid}respource/{resourceid}
method: POST
body: {SubResourceId: 6, Message: ''}
So it is a post api. It creates some mapping of user and resource and subresource.
In this case if user or resource is not found , then api returns 404. But what should be the status code if subresource(which is passed in Body) is not found in DB?
I think you should use a 4** error, because it is a client error, they are referencing a non-existent subresource. If you look at the definitions of the HTTP status errors you see that for example 400 bad request means bad syntax, where the client should not try the same request again. However a 404 means not found, yet it might be available in the future so the request can be tried again at a later time.
In all cases there should be an informative message offering more detail if available. So in this case you should probably send a 404 and a message explaining that the subresource cannot be found. Basically you are passing on a 404 from a deeper level.
There is an arguement to be made that 'the resource' that you refer to in the URI was found, and that 404 is not perfect. However looking at the various status codes available in the w3c Definitions there does not seem to be a more appropriate one.
The other option I would consider is a 500, internal server error. You could argue that the server should expect a request with a valid subresourceid. Since the subresource does not exist, the server cannot further process the request. Again, as long as their is a clear error message this can work, but it feels like more of a stretch than the 404.
But most importably, make sure you are consistent when it comes to error handling in your API(s).
Ideally the response code should be 200 with message saying that no sub-resource was found, it can also be "204 No Content". you can read more about it at wiki link.
It needs to be consistent with Response codes you have been using throughout the application.

Details about why an HTTP request has been 403'ed

I'm working on a RESTful API. I have a complex authorization condition: let's say that you can access the API if you have three different conditions (let's call them A, B, and C). When one of the conditions is not met, the server responds 403 Forbidden (or 401 Unauthorized if the user should log in, or 404 Not Found based on security concerns). However, I would also like to give feedback on why the authorization failed, showing different friendly errors depending on what condition failed. I know that 404 has no body (nor I would want to send one) while 401 and 401 should only have authentication schemes to help the user authenticate.
Is there a way to send responses like 403("reason: A") or 403("reason: C")?
I know that 404 has no body [...]
You seem to be messing the things up. While responses with 204 must have no response body, there's nothing wrong in sending a response body along with 404.
Is there a way to send responses like 403 ("reason: A") or 403 ("reason: C")?
You surely can return details on why the request has been forbidden (just be careful to not give away too much information that could be exploited by a malicious user).
Have a look at the RFC 7807, which defines simple JSON and XML document formats to inform the client about a problem in a HTTP API. It's a great start point for reporting errors in your API and it also defines the application/problem+json and application/problem+xml media types.
For reference, check the example provided by such RFC:
HTTP/1.1 403 Forbidden
Content-Type: application/problem+json
Content-Language: en
{
"type": "https://example.com/probs/out-of-credit",
"title": "You do not have enough credit.",
"detail": "Your current balance is 30, but that costs 50.",
"instance": "/account/12345/msgs/abc",
"balance": 30,
"accounts": ["/account/12345",
"/account/67890"]
}

HTTP Error Code 406

I understand that correct use of HTTP Status codes is a good indicator of correct RESTful implementation of a service. I'm not sure what code to return when the following resource is called with an invalid token to confirm creation of a new user account:
/user/confirmation POST {param is confirmation token}
By best guess is 406 Not Acceptable? But maybe it's a 200 because there is no error as such in which case the response much include information to indicate a failed confirmation?
Both 406 and 200 are unsuitable for this situation:
406 is meant for content negotiation, when the server cannot send a representation of a particular resource with the media type indicated in the Accept header of the request.
200 must be used when the operation has succeeded, what's not the case.
You could probably go for the generic 400 to express a bad request or go for 403 to indicate that the request is forbidden.
Sending the right status code is as important as proving a payload that describes the problem and helps your client to determine the cause of the error.
For reporting problems in your HTTP API, I advise you to have a look at the RFC 7807: it defines simple JSON and XML document formats to inform the client about a problem in a HTTP API and also defines the application/problem+json and application/problem+xml media types.
Michael Kropat put together a pretty useful set of diagrams to determine the most suitable status code for each situation. See the following diagram for 4xx status codes:

Rest endpoint with success and a helpful warning

I have a request from the client - when the user performs an action, there can be 3 actions:
the action succeeds with 200 OK status
the action fails (400) with an error message
the action succeeds but we need to display a helpful warning message to the user. This happens when the allocated amount is almost used up.
There does not seem to be a way for REST APIs to return an indication that the action completed successfully with some helpful information that further action might fail.
Thanks
HTTP response codes are limited and I think, those to be used to indicate any generic response. To have application specific response codes or response strings, it is better to have application level response codes to be communicated via HTTP response payload.
You didn't mention which HTTP method you are preparing for. Using GET should of course not modify anything, so I'm assuming it's either POST or PUT.
For POST, the response should be 201 Created. There should be a Location header line indicating the resource that was created.
For PUT, the response should be 200 OK.
In both cases, you can return a content body, as others suggested. This body can be some status information about the current state of whatever resource you are using. Note, that this status information might be reachable explicitly by some other URI, so it can share a mime-type with that "status" resource.
REST is using HTTP methods and HTTP status to represent the status of reply, by checking HTTP status I can find code 203 I think it could be suitable for your 3rd case :
203 Non-Authoritative Information (since HTTP/1.1)
The server successfully processed the request, but is returning information that may be from another source.

What status code should be sent when a user tries to sign up with a username that already exists?

I was thinking 403. From http://www.restapitutorial.com/httpstatuscodes.html:
The server understood the request, but is refusing to fulfill it. Authorization will not help and the request SHOULD NOT be repeated. If the request method was not HEAD and the server wishes to make public why the request has not been fulfilled, it SHOULD describe the reason for the refusal in the entity. If the server does not wish to make this information available to the client, the status code 404 (Not Found) can be used instead.
Edit: Endpoint - POST /users.
The normal HTTP error code for situations like this is 409 Conflict:
The request could not be completed due to a conflict with the current state of the resource. This code is only allowed in situations where it is expected that the user might be able to resolve the conflict and resubmit the request. The response body SHOULD include enough
information for the user to recognize the source of the conflict. Ideally, the response entity would include enough information for the user or user agent to fix the problem; however, that might not be possible and is not required.
This should be issued in response to a POST or PUT, typically as part of some sort of RESTful API. It should include a useful error message in addition to the status, and the error should be appropriately encoded (e.g. with XML or JSON).
Obscure HTTP errors are less useful in front-end web services. If you are developing a user-facing website, it's preferable to simply deliver an HTML page explaining the problem with a standard 200 OK.
If you are creating a REST API to create accounts, I would expect the request to be something like:
POST /accounts HTTP/1.1
{userid: "someone#example.com", password: "passw0rd!"}
In this case, I guess an appropriate response code would be 409 Conflict with an error description in the body
HTTP/1.1 409 Conflict
{ error: "Account already exists"}
That status code is for an HTTP error, not what you need. Also, it would be very unhelpful as it does not describe the problem at all.
Why not just send:
Username already exists! Please select another.
403 is an ok response in my opinion. 409 and 412 are also possible choices.