Lambda setup troubleshooting
-
I am trying to get the on-premise version to work with Lambda, everything from the tutorial worked great, however when I invoke the function via the AWS PHP SDK (IAM user), I get a 200 response but nothing in the response payload which Im assuming is where the PDF / Excel data would live. Below is an example of that request/response, and the only thing that is different seems to be that Im invoking from PHP and not node. Any pointers on what could lead this type of scenario would be much appreciated.
Some initial thoughts are:
- The Lambda function was configured with authentication, maybe this should be removed?
- Perhaps there missing node modules for templating?
How its being invoked
$client = LambdaClient::factory(array( 'version'=> 'latest', 'region' => 'us-east-1', 'credentials'=> array( 'key' => getenv('AWS_ACCESS_KEY_ID_LAMBDA'), 'secret' => getenv('AWS_SECRET_ACCESS_KEY_LAMBDA'), ) )); $result = $client->invoke(array( 'FunctionName' => 'jsfunction', "InvocationType" => "RequestResponse", 'Payload' => $this->setup_data, ));
The request
{ "template":{ "shortid":"MY-SHORT-ID", "recipe":"phantom-pdf", "engine":"handlebars", "phantom":{ "margin":{ "top":"0.2cm", "bottom":"0.2cm", "left":"0.2cm", "right":"0.2cm" } } }, "options":{ "Content-Disposition":"attachment; filename=MY-FILE-NAME.pdf" }, "data":{REMOVED-FOR-PRIVACY } }
The response
Model Data ---------- Data can be retrieved from the model object using the get() method of the model (e.g., `$result->get($key)`) or "accessing the result like an associative array (e.g. `$result['key']`). You can also execute JMESPath expressions on the result data using the search() method. { "Payload": {}, "StatusCode": 200, "FunctionError": "Unhandled", "LogResult": "", "ExecutedVersion": "$LATEST", "@metadata": { "statusCode": 200, "effectiveUri": "https:\/\/lambda.us-east-1.amazonaws.com\/2015-03-31\/functions\/jsfunction\/invocations", "headers": { "date": "Mon, 15 Mar 2021 04:53:08 GMT", "content-type": "application\/json", "content-length": "604", "connection": "keep-alive", "x-amzn-requestid": "{{request-id-removed}}", "x-amz-function-error": "Unhandled", "x-amzn-remapped-content-length": "0", "x-amz-executed-version": "$LATEST", "x-amzn-trace-id": "{{trace-id-removed}}" }, "transferStats": { "http": [ [] ] } } }
-
Try to minimize the possible problems, use just the HTML recipe with the content "Hello".
-
HTML seemed to produce the same response, when digging into the the cloudwatch logs I am noticing an error after "reporter initialized" that says the response below. As a precursor to this, I had fully tested it using localhost and it worked fine, so not sure if there is something missing when createLambdaPackage.js was ran
2021-03-16T00:49:19.589Z d95bf476-ac1f-4f85-b967-71cae1033ab7 ERROR Invoke Error { "errorType": "TypeError", "errorMessage": "Cannot read property 'template' of undefined", "stack": [ "TypeError: Cannot read property 'template' of undefined", " at module.exports (/opt/nodejs/node_modules/jsreport-core/lib/render/request.js:13:43)", " at module.exports (/opt/nodejs/node_modules/jsreport-core/lib/render/render.js:114:19)", " at Reporter.render (/opt/nodejs/node_modules/jsreport-core/lib/reporter.js:324:12)", " at Runtime.exports.handler (/var/task/index.js:29:30)" ] }
-
Based on the error, it seems that the input request doesn't, doesn't include
template
property.
Does it work for you when calling from node.js?What could be the problem is that we expect the render request to be on the
renderRequet
body property.
See it here
https://github.com/jsreport/jsreport-aws-lambda-starter-kit/blob/master/index.js#L29
In the node.js test we send it like this
https://github.com/jsreport/jsreport-aws-lambda-starter-kit/blob/master/test.js#L14
-
Jan - thanks for the input, I was finally able to get to the bottom of this and sharing my outcome below for anyone else that may end up in the same position.
The AWS PHP SDK utilizes Guzzle for handling the request and response to Lambda, so in the response the actual payload is private/hidden unless you use the mechanism provided by the SDK to extract it from the response. Below is an example of how this was handled
$client = LambdaClient::factory(array( 'version' => 'latest', 'region' => 'us-east-1', 'credentials'=> array( 'key' => getenv('AWS_ACCESS_KEY_ID'), 'secret' => getenv('AWS_SECRET_ACCESS_KEY'), ) )); $result = $client->invoke(array( 'FunctionName' => 'jsfunction', 'InvocationType' => "RequestResponse", 'Payload' => $data, // your json payload )); // Get the payload from the object $body = json_decode($result['Payload']); // Base64 Decode the PDF/excel data $pdf_data = base64_decode($body->body);