HTTP Status code and Response Body in HTTP POST for data validation - validation

Let's suppose to have an HTTP POST that accept as input a JSON with some data and it must validate these data. The method should return also a validation message in the response body.
Ex.
{
"A" : 1,
"B" : 1,
"C" : 3
}
Suppose to have some validation rules defined over the JSON, for example (A + B) should be less than C parameter.
I have some doubts about the HTTP status code.
If the JSON is valid the HTTP POST should returns 200
If the JSON is not valid (missing parameters or wrong types) the HTTP POST should returns 400
But in case the JSON is valid (there are all the requested parameters and the types are correct) but the parameters don't respect the defined rules (A + B < C) what should be the HTTP Status?
200 and than an explanation in the response body?
400 and the explanation in the response body?
Is there the need to differentiate the HTTP Status from the Validation rules Status?
Cheers

That's what status code 422 ("Unprocessable Entity") has been designed for.
See https://www.greenbytes.de/tech/webdav/rfc4918.html#STATUS_422.

It all depends on the use-case / functionality you want to achieve.
If you want to make it easy for others to work with valid messages, I would perhaps return 2xx only if the message is completely valid, and in all other cases return 4xx. In this case the caller does not need to parse the result, which makes it easy to work with.
If the use-case is to provide some analytic service that others will use to analyze messages, not specifically to use the message itself, then I would return 2xx with the result of the analysis unless the message can not be parsed (not a json for example), in which case 4xx is warranted.

your response need to be 400 with the follwing message: "Bad Request: parameters don't respect the rules".
400 error

Related

What status should be set used for returning validation errors on an entity in HttpStatus

What status should be set used for returning validation errors on an entity from org.springframework.http.HttpStatus
If we want to return validation errors if certain fields are empty, what status would be preferable to use
400 - Bad Request is the common response code sent if the request doesn't contain all the required parameters or if it is in a invalid format.
More on this: 400 BAD request HTTP error code meaning?

REST HTTP Status Code Best Practice for validation API

I am creating a simple API to validate a membership. Client will have to input a String ID and Server will check if the ID is a valid member of our, lets say, community. The ID must be numeric only, with length 10.
Quite simple right?
If the ID is a valid, of course we will return HTTP Status Code OK.
If the ID is contains alfabet, or less/more than 10, then we will return HTTP Status Code BAD REQUEST.
The question is, what is the best practive HTTP Status Code to return when the ID is numeric and length = 10, but is NOT a member of our community? and why is that.
The endpoints of a REST API are normally resources on which you act using HTTP methods like GET,PUT,POST,DELTE. When you do it like that, its much easier to decide which HTTP status to return.
So may be you could make an endpoint
/member/{id}
if a member with this id exists, return HTTP 200 and if you want some JSON with basic member info
if the id is valid, but no member exists, return HTTP 404 - NOT FOUND
if the id is not valid, length !=10 or contains invalid chars, return a HTTP 400 BAD REQUEST
Here you can find more about REST API design

How to inject a header from the errormessage

I've been attempting to inject a custom header for a error response status (and failing).
I have a very simple lambda being used
exports.handler = (event, context, callback) => {
// TODO implement
//callback(null, 'Hello from Lambda');
var error = {
name:"error",
message:"I am a failure",
statusCode: 400
};
error["x-test"] = 'foo';
callback(JSON.stringify(error), null);
};
In the api gateway, I've done the following:
set up CORS to include x-test
responsetemplate = "$input.path('$.errorMessage')"
responseparameter to include:
method.response.header.x-test = integration.response.body.x-test
Also, I have a statusCode mapped using '.*statusCode.*?400.*'
This has turned out empty.
so I decided to take a step back and see what happens if I do:
method.response.header.x-test = integration.response.body
I found that I get the stringified response of errorMessage.
{"x-test":"{\"errorMessage\":\"{\\\"name\\\":\\\"error\\\",\\\"message\\\":\\\"I am a failure\\\",\\\"statusCode\\\":400,\\\"x-test\\\":\\\"foo\\\"}\"}"}
So I decided to change the responsetemplate to force it to json by doing the following:
responsetemplate = "$util.parseJson($input.path('$.errorMessage'))"
and I still get the stringified response:
{"x-test":"{\"errorMessage\":\"{\\\"name\\\":\\\"error\\\",\\\"message\\\":\\\"I am a failure\\\",\\\"statusCode\\\":400,\\\"x-test\\\":\\\"foo\\\"}\"}"}
My guess is that it doesn't transform as expected, but only for the final output.
So how would you take a value and shove it into a header?
Thanks,
Kelly
I think this is more of a design choice regarding the limitation imposed by both Lambda and APIGateway. I will try my best to walk through my thoughts.
First of all, in Lambda, callback(error, result) function can either take an error string as first argument, or an object as result response. If you want to pass along a simple error message, you could definitely just do that. However, in your case, as you tried to pass along an entire error object, choosing the second option is clearly a better solution (in contrast to stringifying an object and parse it into object again). As a result, the final line of your Lambda function should be:
callback(null, error);
Yes, in this case, if you test your function in Lambda, the output result will no longer be red and flag it as an error, but this won't matter as you can format your headers and response in APIGateway.
Now you need to set things up in APIGateway, in which you need to make use of the object passed by Lambda.
It's actually rather easy to use method execution interface to configure headers.
In Method Response, you need to add the headers you want to include in the response for a specific status code, which in your case is x-test. (If you want the API to return different status codes, you can also configure that in this panel.)
Then go to Integration Response, under the same status code, you will see the added header available. According to this documentation from AWS, you can use integration.response.body.JSONPath_EXPRESSION to assign the header value (this is another reason that you should return object rather than string in Lambda, as there is no formal API to parse object from string at this stage). This time, as your Lambda is passing an object, the value of x-test header is:
integration.response.body['x-test']
Now your API should have the proper header included.
NOTE: In order to set up different status code in APIGateway, you should leave some distinguishable data fields (your statusCode: 400 should work perfectly) in you response body, so you can use RegEx to match those fields to a specific status code.
So... above doesn't work with success message. I found this blog though talking about error handling design pattern. Apparently what they suggest is only mapping status code when there is an error, in which case no body should be passed (only the errorMessage), as browser won't care about response body for a status code other than 200 anyway.
I guess after all, it is impossible to customize both status code and header at the same time with Lambda passing an object to APIGateway?
This is due to the fact that you are stringifying the error object coming from your Lambda function. API Gateway attempts to resolve the JSON-Path expression and can't evaluate "x-test" in a string. If you return an object instead of a string, this should work.
You may want to consider using proxy integrations which allow you to control the headers and status directly from your Lambda function.
Update: I've written a blog post on this topic with sample code # https://rpgreen.wordpress.com/2017/01/25/how-to-send-response-headers-for-aws-lambda-function-exceptions-in-api-gateway/

HTTP response for validation request

I've got a service that validates names, that can be used to check whether a username is OK. It looks something like this:
POST http://names.myservice.com/validate
content-type: application/json
{"name": "Abdul Hideo McDodgycharacter¬§(*&^$%£!"}
=> 200 OK
{"errors": "contains invalid characters"}
So the point of the service is to check the validity of a proposed username, also checking in my db to see whether it's already been taken. My question is: should the response code be 400 (Bad Request) when there are validation errors?
If I was building a user API to create users, that's what I'd do when presented with Abdul here, but I'm not. In this case the request is for validation, the input data is acceptable, and the response contains the requested representation, which is a list of errors for the supplied data, so a 200 OK feels right. A 400 would indicate my validation request was malformed, and the data to be validated couldn't be identified.
I realise that this isn't very RESTful, because "validate" is basically a verb, so if there's another way to do this that solves my query, please suggest it!
If the request for validation was successful, then 200 (OK) is the correct response code. As far as endpoints, you can consider
POST /validated-names

Custom http codes

Could I use custom HTTP codes?
I want to use these codes as response for AJAX requests.
Example:
220 - will be correspond to status that some item was created successfully
420 - will be correspond to status that some validations errors were occurred
Each response will be has json string.
You can define extension codes, but it only makes sense if you want to standardize something; in which case you need to write a spec, and get the status code registered (see http://greenbytes.de/tech/webdav/draft-ietf-httpbis-p2-semantics-12.html#rfc.section.4.1).
If this is just between your server and your client, simply put the additional information into the response body and use a more generic status code.
That being said -- what you called "420" is already defined as "422 Unprocessable Entity".
Using your server side language of choice you can send headers to the browser with the relevant HTTP code and message.

Resources