I'm writing a microservice for validating promo codes. The client sends me a promo code and a product ID (json). There is the 200 OK case where the code is good, I apply a discount for their order. But there is an error-ish case where the promo code doesn't apply for this product. I'm unsure what response code to use.
Should this also be 200 OK (with some sort of message saying the validation of the code fails)?
Should it be 400 Bad Request?
Neither seems entirely appropriate, it's odd to say 200 OK when it wasn't "OK", however 4xx is usually for signifying a problem with the structure of the request / http protocol - and in this case the structure of the request is fine.
I'll second steveax. 422 seems like a good choice.
IMHO, you should never use 200 if the request failed.
Use an error code & if necessary, provide details in the response body:
HTTP/1.1 422 Unprocessable Entity
Content-Type: application/json
{ "reason": 1, "text": "Invalid promo code." }
On second thought, I think 403 is a good fit here:
HTTP/1.1 403 Forbidden
Content-Type: application/json
{ "reason": "bad_promo_code" }
Ultimately, it doesn't matter as long as it's documented.
I will suggest 409:
10.4.10 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.
Related
Example: An API endpoint that accepts in a PET field the values "DOG" and "PET". If it receives an request with the payload value with "RABBIT",
{
"animal": "RABBIT"
}
is a good practice return a 400 Bad Request (or even a 422 Unprocessable Entity) with the list of the valid values in the message?
Like "Invalid value for the animal field. Valid values: "DOG" and "CAT"? Or should i just return the http code?
You SHOULD (in the RFC 2119 sense) return a representation that explains the situation.
Except when responding to a HEAD request, the server SHOULD send a representation containing an explanation of the error situation, and whether it is a temporary or permanent condition. These status codes are applicable to any request method. User agents SHOULD display any included representation to the user. -- RFC 7231
HTTP status code 400 is much general than 422. HTTP status code 422 feels like a much more appropriate response for situations where the data is understood, but is still not valid.
Even if you want to return 400 status code, it's correct. In any case, make sure that the error response in body explains what issue is.
HTTP/1.1 422 Unprocessable Entity
{
"message": "Validation Failed",
"errors": [
{
"field": "animal",
"code": "RABBIT is not valid value. Value must be either PET or DOG"
}
]
}
Recently I have been updating my GO REST APIs into graphQl API's and I came across issue where I am unable to customise my status code with gqlgen.
Response I got
Headers
Status Code: 200 OK
{
data: null,
errors: [
{message: "Unauthorized access", path: ["..."]}
]
}
Expected Header
Status Code: 401 UNAUTHORISED
Any help would be really appreciating!
Assume you have a gqlgen resolver similar to this:
func (r *queryResolver) SecretItems(ctx context.Context, userID string,
password string) ([]SecretItems, error) {
// ...
if !isAuthorized(userID, password) {
return nil, errors.New("Unauthorized access")
}
// ...
}
then the described behavior is expected. Errors should be returned as part of
the response body.
GraphQL is transport agnostic. While it is often served over HTTP, it might be
served over other client-server Protocols as well. Handling errors in the
response body requires no assumptions about the protocol. Hence, you shouldn't
rely on HTTP status codes.
Handling errors in the response body has another advantage: Assume a request
contains multiple queries. Some of them succeed, some of them fail. Then the
response can contain the result of successful queries under data and errors
related to failed queries under errors.
References:
GraphQL website
Specification: Response
Hasura: GraphQL vs REST
Possible reason why you expected a 401 status code
The gqlgen docs on
authentication contain an example
where 401 status code is returned.
Why? This happens in a http handler used as middleware on the chi http server.
The 401 status code is not returned by a GraphQL resolver.
I'm trying to understand which Http Status Code to use in the following use case
The user tries to do a GET on an endpoint with an input ID.
The requested data is not available in the database.
Should the service send back:
404 - Not Found
As the data is NOT FOUND in the database
400 - Bad Request
As the data in the input request is not valid or present in the db
200 - OK with null response
200 - OK with an error message
In this case we can use a standard error message, with a contract that spans across all the 200 OK responses (like below).
BaseResponse {
Errors [{
Message: "Data Not Found"
}],
Response: null
}
Which is the right (or standard) approach to follow?
Thanks in advance.
Which is the right (or standard) approach to follow?
If you are following the REST API Architecture, you should follow these guidelines:
400 The request could not be understood by the server due to incorrect syntax. The client SHOULD NOT repeat the request without modifications.
It means that you received a bad request data, like an ID in alphanumeric format when you want only numeric IDs. Typically it refers to bad input formats or security checks (like an input array with a maxLength)
404 The server can not find the requested resource.
The ID format is valid and you can't find the resource in the data source.
If you don't follow any standard architecture, you should define how you want to manage these cases and share your thought with the team and customers.
In many legacy applications, an HTTP status 200 with errors field is very common since very-old clients were not so good to manage errors.
Usually, we use POST to create a resource on the server-side.
So ideally if everything goes right, the server should respond either with a 201 Created HTTP status or in case of an asynchronous operation with 202 Accepted HTTP status.
Is there any valid scenario where a POST request can be returning a 200 OK HTTP status?
Or should we never use 200 OK HTTP status for a POST request?
I see 200 as a very common response to POST requests on internet. It's fine to use it.
From RFC 7231:
6.3.1. 200 OK
The 200 (OK) status code indicates that the request has succeeded.
The payload sent in a 200 response depends on the request method.
For the methods defined by this specification, the intended meaning
of the payload can be summarized as:
GET a representation of the target resource;
HEAD the same representation as GET, but without the
representation
data;
POST a representation of the status of, or results obtained from,
the action;
PUT, DELETE a representation of the status of the action;
OPTIONS a representation of the communications options;
TRACE a representation of the request message as received by the
end
server.
And section 4.3.3:
Responses to POST requests are only cacheable when they include
explicit freshness information (see Section 4.2.1 of [RFC7234]).
However, POST caching is not widely implemented. For cases where an
origin server wishes the client to be able to cache the result of a
POST in a way that can be reused by a later GET, the origin server MAY
send a 200 (OK) response containing the result and a Content-Location
header field that has the same value as the POST's effective request
URI (Section 3.1.4.2).
Yes, You can return 200 Ok HTTP status, but you SHOULD return a response BODY.
In general, we have 3 options according to your API requirements:
Return 201 Created HTTP status, with EMPTY BODY.
In case you don't need to return a response body.
Return 200 Ok HTTP status, with BODY.
In case you need to return a response body [containg created resource].
Return 202 Accepted HTTP status, with EMPTY BODY.
In case the action will be queued.
The Dropbox API docs state that in the event of being rate limited, a 503 HTTP status code will be returned, with a "Retry-After" header. However, in what I suspect is a case of rate limiting, this is the actual reponse I get:
[503] Error parsing response body or headers: Body - '\r\n<html>\r\n<head><title>Dropbox
- 5xx</title>\r\n<link href="https://www.dropbox.com/static/css/ Headers - {'transfer-
encoding': 'chunked', 'server': 'nginx', 'connection': 'keep-alive', 'cache-control':
'no-cache', 'date': 'Sat, 31 May 2014 12:55:40 GMT', 'content-type': 'text/html'}
(Actually this is the str(e) of dropbox.rest.ErrorResponse as e)
There is no Retry-After header, so this may not be a case of rate limiting. If that's the case then I don't know what this error is telling me.
Does anyone have an example of an actual rate-limiting response that I can test against?
The response just indicates some random server glitch. You should try the request again. As you've indicated, this scenario is documented in the Standard API Errors section of the Core API Reference:
503
If the response includes the Retry-After header, this means your ... app is being rate limited. Otherwise, this indicates a transient server error, and your app should retry its request.