I am trying to use the same AWS Lambda function to do two things with the same DynamoDB dataset.
I have already implemented this, and the Skill is operating correctly. I am using NodeJS and the Amazon Skills Kit version 2. The last few lines of my index.js are as follows:
const skillBuilder = Alexa.SkillBuilders.standard();
exports.handler = skillBuilder
.addRequestHandlers(
LaunchRequest,
HelpIntent,
// .... various other intents
UnhandledIntent
)
.addErrorHandlers(ErrorHandler)
.lambda();
The NodeJS code I have set up for the Alexa skill, processes DynamoDB data in order to provide the skill responses. I want to use the same codebase (i.e. the same Lambda function) to produce summaries for my own benefit. I don't want to copy-paste pieces of the Lambda function into a separate function. I would much rather have the same code do both tasks, in order to keep everything in step.
My problem is that the structure of the Lambda code for returning this JSON response to my request is as follows, from https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-create-api-as-simple-proxy-for-lambda.html:
'use strict';
console.log('Loading hello world function');
exports.handler = function(event, context, callback) {
let name = "you";
let city = 'World';
// etc ... more code ...
callback(null, response);
};
I think I want to achieve this effect:
if ( /* test whether being called by Alexa or by API Gateway */ )
{ /* Make the Alexa Response */ }
else
{ /* Construct the JSON data summary response */ }
From what I can make out, each Lambda function (in the sense of each Amazon Resource Number for a Lambda function) has to have only one entry file, i.e. I can't make Lambda start index_Alexa.js
versus index_JSON.js
.
I am open to any suggestion on how to get the same Lambda function (in the sense of the same JS file or package of files) do both things.
I question the usefulness of the approach somewhat, and the following has some potential for optimization remaining, but one way of accomplishing this is to declare exports.handler
as a simple wrapper that invokes the correct previously-declared handler function based on a condition you can test in the request.
// set up handler for alexa
const skillBuilder = Alexa.SkillBuilders.standard();
const alexa_handler = skillBuilder
.addRequestHandlers(
LaunchRequest,
HelpIntent,
// .... various other intents
UnhandledIntent
)
.addErrorHandlers(ErrorHandler)
.lambda();
// set up handler for API Gateway
const api_gateway_handler = function(event, context, callback) {
let name = "you";
let city = 'World';
// etc ... more code ...
callback(null, response);
};
// for each invocation, choose which of the above to invoke
exports.handler = function(event, context, callback) {
if(/* some test that is true only for API Gateway */)
{
api_gateway_handler(event, context, callback);
}
else
{
alexa_handler(event, context, callback);
}
};
The line if(/* some test that is true only for API Gateway */)
is something you'll need to work out, but I suspect something like this might work:
if(event.input && event.input.requestContext && event.input.requestContext.apiId)
The API Gateway docs suggest that this value would always be present.