I would like to return a response code of 400 to the client after throwing an error in my Lambda function. (via REST API - GET)
Here is the response from the Lambda function:
{
"errorMessage": "{\"status\": 400, \"result\": \"Invalid Input\", \"errorDescription\": \"Incorrect data format, should be YYYY-MM-DD. Refer to our documentation for further instructions.\", \"documentation\": \"link\"}",
"errorType": "ValueError",
"stackTrace": [
" File \"/var/task/lambda_function.py\", line 69, in lambda_handler\n raise ValueError(date_error_json)\n"
]
}
In the settings of the Integration Response of the API I set up the Lambda Error Regex as .*"status":400.*
For the mapping template I have:
#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))
{
"status" : "$errorMessageObj.status"
}
When calling the API I mostly receive this result:
{"errorMessage": "{\"status\": 400, \"result\": \"Invalid Input\", \"errorDescription\": \"Incorrect data format, should be YYYY-MM-DD. Refer to our documentation for further instructions.\", \"documentation\": \"link\"}", "errorType": "ValueError", "stackTrace": [" File \"/var/task/lambda_function.py\", line 69, in lambda_handler\n raise ValueError(date_error_json)\n"]}
And the status of the HTTP request tracked in Chromes Developer Tools shows as 200.
My assumption is that the Regex is incorrect since it should at least return a 400 HTTP response, even if my mapping template was incorrect.
However, surprisingly a few times I was able to get the desired result of a 400 HTTP response, as well as the desired format displayed as:
{
"status" : "400"
}
The way I got to this result was the following: When I changed the Regex around to .*400.* (which did not help) and then back to .*"status":400.*. However, as soon as I send another request to the API it was back to the situation before. (No other changes were made, only a second API request)
And this is actually repeatable, every time I switch back and forth between those Regex values I get my desired result. For 1 API request and then it switches back.
I know it sounds weird. Here is a quick screenshare of it: https://www.loom.com/share/365a7c48119944658e157c5e0a5178e8
I would like to know if there is an issue with my code or if this might be a bug on Amazon's end.
For anyone coming across the same problem in the future. I have found out the following 2 things:
After trying again to set .*400.* a little later it worked fine. Of course, this may not be a good idea, because if you return any results, that contain 400 anywhere in their response, they could incorrectly trigger a 400 HTTP response.
The workaround I found was to use .*Invalid Input.*. Since it is not expected that regular results returned from the API would contain this phrase, this should work reliably.
Related
I would like to obtain in a response of http-connector, only the “number” element, but I cannot obtain it.
I’m trying to have an inline Javascript with the following statement:
S(response).prop(“status”).prop(“number”).numberValue();
but it shows an error: SPIN/JACKSON-JSON-01004 Unable to find ‘status’
What it’s wrong in the statement?
Rest response to parse:
{
“status”: {
“number”: 200,
“type”: “OK”,
“description”: “Status OK”
}
}
There is no obvious issue with your expression. I would debug further to see if response indeed contanis the Json string you posted. The error shows that response exists, but the content differs.
This working example I just created may help you:
https://github.com/rob2universe/camunda-http-connector-example
If this does not help, you could share more info, e.g. the process model, server log, service you are calling...
I was trying to handle/receive all the responses with the 2xx status codes with the 'regex' http response code '2\d+' but it was not handling it as expected.When I enter the http status code directly (for example '202') then it was handling the response. But I want 'regex' to handle it.
#source(type='http-response', sink.id='Response',http.status.code='2\\d+', #map(type='json',#attributes(success = 'status')))
#sink(type='log')
define stream ResponseStream(success string);
Here is the response am getting when i use regex code.
[2019-11-26 07:16:42,705] ERROR
{org.wso2.extension.siddhi.io.http.source.HttpResponseMessageListener}
- No source of type 'http-response' that matches with the status code '202' has been defined. Hence dropping the response message.
Kindly help me to handle this using regex codes.
In your Siddhi query you have given status code as '2\\d+'. Please change it to '2\d+'
I'm aware about Lambda Proxy Integration, however I'm curious about Lambda Custom Proxy.
To catch the custom error, I'm going to define regular expression inside Integration Response associated with following Lambda function:
exports.handler = (event, context, callback) => {
...
// Error caught here:
var myErrorObj = {
errorType : "InternalServerError",
httpStatus : 500,
requestId : context.awsRequestId,
trace : {
"function": "abc()",
"line": 123,
"file": "abc.js"
}
}
callback(JSON.stringify(myErrorObj));
};
According to doc: "When a method of your API is integrated with the preceding Lambda function, API Gateway receives an integration response with the following payload"
{
"errorMessage": "{\"errorType\":\"InternalServerError\",\"httpStatus\":500,\"requestId\":\"e5849002-39a0-11e7-a419-5bb5807c9fb2\",\"trace\":{\"function\":\"abc()\",\"line\":123,\"file\":\"abc.js\"}}"
}
Please note that there is a backslash inside httpStatus\":500 (let's call this target), so logically Lambda Error Regex should be something like .*httpStatus\\":500.* , that is it should escape the backslash, so that it can catch that target. However, such regex doesn't catch the error, instead .*"httpStatus":500.* catches the error. The latter regex normally catches term httpStatus":500 . But this contradicts with the doc. In other words, it seems that Regular Expression of API gateway doesn't scan the string as it's explained by the docs? So, what does it exactly scan? What exactly happens in between?
{
"errorMessage": "{\"errorType\":\"InternalServerError\",\"httpStatus\":500,\"requestId\":\"e5849002-39a0-11e7-a419-5bb5807c9fb2\",\"trace\":{\"function\":\"abc()\",\"line\":123,\"file\":\"abc.js\"}}"
}
This is the raw response payload that API Gateway receives from Lambda. That is a JSON object, containing your errorMessage string, which contains a JSON object (that you put there). Lambda has JSON.stringify'ed the whole thing a second time for the wire response, as it is designed to do.
It would be inappropriate to try to parse the payload directly, so it is automatically being decoded, once, removing the outer layer of JSON serialization so that your regular expression is applied to your error message string exactly as you handed it to the callback. The backslash-escaped quotes are an artifact of JSON-in-JSON, and they are removed when the first decoding step happens.
I'm working with a slightly unconventional API that is expecting a JSON body with a GET request and I have no control over this. Unfortunately, every time I attempt to make the request, it seems to completely disappear and never make it to the API. I originally wrote the request using a standard URLSession and then switched to try Alamofire in an attempt to fix it but ended with the same result. My request looks like this:
Alamofire.request("http://192.168.1.1:8000/connect/", method: .get, parameters: ["test": "test"], encoding: JSONEncoding.default)
.responseJSON { response in
let body = response.request?.httpBody
guard response.result.isSuccess else {
onCompletion(nil)
return
}
onCompletion(response.result.value as! [String : Any]?)
}
This exact code works for a different request where there is no JSON in the body, but seemingly the moment I add it, it just times out. This has already been discussed on the alamofire github repo (https://github.com/Alamofire/Alamofire/issues/1819) but the final comment with what should be working code isn't really any different to mine, so doesn't provide any help, nor do the other linked issues.
Printing the request with debugPrint gives me this curl command
$ curl -i \
-H "Content-Type: application/json" \
-d "{\"test\":\"test\"}" \
"http://192.168.1.1:8000/connect/"
Which is missing the -X GET flag, but when I add that in, the request works as expected and the server responds, so I know the API itself is working and is happy processing the JSON in the body, so I'm at a loss as to what's going on.
I've installed Timberjack to attempt to trace things, which didn't give me any more info at all, just what I already knew
Request: GET http://192.168.1.1:8000/connect/
Headers: [
Content-Type : application/json
Content-Length : 24
]
Although I'm not sure if it's supposed to be showing me the body as well which it isn't?
In both cases (URLSession and Alamofire) the request gives the following output which I don't see at any other time:
2017-01-22 23:31:09.797453 my-app[3755:1349066] [] nw_endpoint_flow_service_writes [2 192.168.1.1:8000 ready socket-flow (satisfied)] Write request has 4294967295 frame count, 0 byte count
2017-01-22 23:32:04.484182 my-app[3755:1349066] [] __tcp_connection_write_eof_block_invoke Write close callback received error: [89] Operation canceled
Anyone have any ideas on what's going on as I'm completely at a loss at this point.
Update
I've done some more digging. If I change the endpoint to https://httpbin.org/get then the request goes through just fine and I get a response. Whilst this kind of suggests the API server is refusing to process the request, it's still working with the cURL command so that can't really be the issue.
I also forgot to mention (although not sure it should make a difference) that the API I'm trying to communicate with is connected via an ad-hoc wifi. Other requests to it work just fine though so I can definitely communicate with it.
Update 2
So I've been able to switch the server to using POST instead of GET and unsurprisingly it now works, however I would still love to know of a solution to the original problem
URLSession and CFHTTPMessage cannot send a message body for a GET request. They send the content length for the body, but do not send the body itself. This results in a timeout.
In order to resolve this issue I've used libcurl to handle the GET requests which have a message body to my project. I use URLSession everywhere else. When you add a body to a request using libcurl it changes the request to a POST, but that can be changed back to a GET after setting the body and before submitting the request.
I can't figure out if my problem has to do with my query or my response or something else.
In my route I'm using a queryRecord:
model(params) {
return this.store.queryRecord('invitation', {
'invitation_token' : params.invitationToken
});
},
I'm properly receiving on the server side but I'm testing the case where the invitation token no longer exists. Therefore, the server is returning a 400 with a json payload which has an explanation of the error.
{"error":"Error finding invitation"}
But back on the ember side I'm just getting two errors (really it is just one).
Error while processing route: accept-invitation Ember Data Request GET /api/users/invitation returned a 400
Error: Ember Data Request GET /api/users/invitation returned a 400
It used to be (under Ember 2.2.1):
Error while processing route: accept-invitation Adapter operation failed Error: Adapter operation failed
Error: Adapter operation failed
What am I supposed to be returning from the server in the case that the token wasn't found? These messages makes it looks like something unexpected happen within Ember.
I'd assume that a 400 would tell Ember that there was an error, and it would go to the error state for the route. But instead it goes to the error state at the application level and spits out these error messages in the log.
I'm expecting the server to return a 400, so I'm not sure why Ember is complaining. What should I be returning and how should I properly handle this?
I believe that your application should be returning a response that is formatted differently. As per the JSON API specification,
Error objects MUST be returned as an array keyed by errors in the top
level of a JSON API document.
The specification also specifies that the following members, among others, may be provided (see the link for the full list).
title: a short, human-readable summary of the problem that SHOULD NOT
change from occurrence to occurrence of the problem, except for
purposes of localization.
detail: a human-readable explanation
specific to this occurrence of the problem. Like title, this field's
value can be localized
status: the HTTP status code applicable to this problem, expressed as
a string value.
If you try returning something along the lines of what is below, how does the tooling behave?
{
"errors": [
{
"status": "400",
"title": "Error finding invitation"
}
]
}