I've got an afterSave handler in Cloud Code that conditionally calls a custom method.
From my testing, both functions appear to be working exactly as desired. The custom method is skipped appropriately (with confirming console messages looking correct). It is also called appropriately, and the custom method creates a new object exactly as desired.
What's confusing me is that when the custom method IS called, I get something like the following in my Cloud Code log:
Input: {"title":"title","ownerId":"ownerId"}
Result: undefined
Like I said, the values seem to be passed in correctly, and the method seems to run correctly, but I don't understand why I get Result: undefined.
In the method that is called, I've placed a response.success() or response.error() in every pathway that's possible.
So, is this something to worry about?
The custom method is a "fire-and-forget" type of method, so my afterSave method doesn't wait around for a response. Is that why I'm getting Result: undefined?
The reason you are getting undefined is because your response and error functions don't pass any values. Replace it with this.
success: function(result) {
//...
response.success(result);
},
error: function(error) {
response.error(error);
}
Then you'll no longer have an undefined result.
Related
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/
Im trying to call cloud function from parse.com at Restask in Tasker
I already configured custom headers, parameter, etc.
But it always returns 400. And return body empty. Not sure why.
I'm doing something similar to what you're trying to do and just managed to POST an object into parse. The problem you're facing is that your request's body is empty (should be a JSON)
You can set that in RESTask's settings under "Custom body".
I initially had problems with variables inside the body, but after talking to John from RESTask, he said that the variables work:
it won't work, however, when you use the "test" function inside
RESTask, as there is no context of a task
Good luck and let us know what you've built .)
Z.
"Routes and controllers that handle actions must place action handlers inside an actions hash. Even if a route has a method with the same name as the actions, it will not be triggered unless it is inside an actions hash. In the case of a controller, while there is deprecated support for triggering a method directly on the controller, it is strongly recommended that you put your action handling methods inside an actions hash for forward compatibility."
That is from the ember documentation, it sounds like I should put my actions inside the actions hash within a controller, but after I put the action inside the hash, my controller complains that Uncaught Error: Nothing handled the event 'submit'.
//this works
App.StartController = Ember.Controller.extend({
submit:function(){
alert(1);
}
});
// this complains Uncaught Error: Nothing handled the event 'submit'.
App.StartController = Ember.Controller.extend({
actions:{
submit:function(){
alert(1);
}
}
});
BTW, I am using v1.0.0rc
Just to reference #mavilein's comment, I updated my ember libraries and it's working now.
I'd like to know what the success and error do in the Ember.js RESTAdapter's ajax function.
hash.success = function(json) {
Ember.run(null, resolve, json);
};
hash.error = function(jqXHR, textStatus, errorThrown) {
Ember.run(null, reject, jqXHR);
};
I know hash is the data sent through AJAX, but what role do success and error play? I assume they'd be run based on a successful or erroneous AJAX response, right? They're set before the AJAX is called, as callbacks? How do they work?
but what role do success and error play? I assume they'd be run based on a successful or erroneous AJAX response, right?
Right, since ember uses jQuery under the hood the functions mentioned are just plain jQuery methods.
They're set before the AJAX is called, as callbacks? How do they work?
As for the functions itself, see this info taken from the jQuery official docs:
error callback option is invoked, if the request fails. It receives the jqXHR, a string indicating the error type, and an exception object if applicable. Some built-in errors will provide a string as the exception object: "abort", "timeout", "No Transport".
success callback option is invoked, if the request succeeds. It receives the returned data, a string containing the success code, and the jqXHR object.
I should also mention that the success callback is in recently jQuery version being replaced with done and is marked as deprecated as noted here:
Deprecation Notice: The jqXHR.success(), jqXHR.error(), and jqXHR.complete() callbacks are deprecated as of jQuery 1.8. To prepare your code for their eventual removal, use jqXHR.done(), jqXHR.fail(), and jqXHR.always() instead.
But don't worry, because I guess until jQuery removes this methods completely the ember team has surely catched up with the new callback versions.
And finally if you where wondering what the call to Ember.run does you can have a look here. But basically it ensures that the passed target and method are run inside of a RunLoop, ensuring also any deferred actions like bindings and views updates, this are flushed at the end. This SO answer on the Runloop is also very informative.
Hope it helps.
why do I always have so much trouble...? given that I didn't solve the problem in my other article, I decided to just code the javascript right into the values... so I have:
OnSuccess="alert('ok')",
OnFailure="alert('failed')",
so my problem is the submission works fine; a record gets inserted into the database and I get a callback... but I get the wrong callback! I get a failure even though the record got inserted. heeeeelp!
You should be able to read data from the response to figure out why it's considered a failure:
OnFailure="handleError",
...
function handleError(ajaxContext) {
var response = ajaxContext.get_response();
var statusCode = response.get_statusCode();
alert("Sorry, the request failed with status code " + statusCode);
}
Alternatively, use Fiddler and look at the response. Make sure the status code, content type and content are all as expected.
ok, I figured out a few things:
OnFailure="handleError" is the correct way to do this (see the other article I mentioned for resolution)
ajaxContext didn't have a get_response() method because I was actually hooking up the function to the OnComplete event instead (my bad)! once hooked up to the OnSuccess, I get my controller's method Json return value natively
I was getting the OnSuccess handler called when the database entry was failing. this is because my controller method was try{} catch{}ing and therefore never failed! me being dopey :(