Dialogflow using AWS Lambda webhook - amazon-web-services

I am trying to leverage AWS Lambda as the webhook for dialogflow call.
I want to use all the agent/google actions libraries.
So I copied the sample code and pasted it to Lambda what we get in Dialogflow console. I installed all the npm libraries. But when testing I am getting this issue:
TypeError: Cannot read property 'result' of undefined
at new WebhookClient (/var/task/node_modules/dialogflow-fulfillment/src/dialogflow-fulfillment.js:84:27)
at exports.dialogflowFirebaseFulfillment.functions.https.onRequest (/var/task/index.js:13:17)
at cloudFunction (/var/task/node_modules/firebase-functions/lib/providers/https.js:57:9)
I have exposed Lambda earlier but as the requirement is for the Dialogflow, I am not able to do so.
Note: I am passing the same request payload in Google Cloud and AWS Lambda, Google Cloud is returning correct but Lambda is returning error as mentioned above.
Not sure if I am missing any step or my understanding is wrong here.
Please help.

Can you please post some code here as well for more reference?
If you've installed the required npm libraries for dialog-flow then it should work as far as I can understand.
Also please note if you're trying to access input request parameters of DialogFlow such as {"userId": string,"idToken " string} it will not be accessible by default in the lambda events & hence you may face errors like Cannot read property 'result.originalRequest.user.idToken' of undefined.
You'll have to first enable google integrations on the fulfillment intents so that google can ask users the permission to send these attributes in the request body.
Also since this was asked many months ago please let me know if your issue was resolved.

Related

AWS CDK - How to run API and Lambdas locally?

edit: Turns out the solution is in the docs. I had bog standard normal 'sam' installed but I needed what they call the 'public preview version' AKA 'sam-beta-cdk'. With this installed the API can be started locally with sam-betacdk start-api and works well. While I appreciate the answers which suggest that development should be done using purely TDD I feel there is also value in this more interactive, manual mode as it permits quicker exploration of the problem space.
I'm trying to build my first app with CDK + Typescript using API Gateway, Lambdas and DynamoDB. I have built a couple of Lambdas and deployed them and they work fine live on the web. However I don't want a minute long deploy cycle and various associated AWS costs as part of my workflow. What I want is to be able to test my API locally.
I have struggled to find docs on how to do this. Amazon seem to recommend using the SAM CLI here so that is what I've been trying.
The docs claim running sam local xyz runs cdk synth to make a "could assembly" in ./aws-sam/build but I see no evidence of this. Instead what I get is a complaint that sam could not find a 'template.yml'. So I manually run cdk synth > template.yml which creates one in the root folder. Then I run sam local start-api and it seems happy to start up.
Then I try and hit my test lambda using CURL: curl 'http://127.0.0.1:3000/test' I get {"message":"Internal server error"} and a huge ugly stack trace in the console that is running sam local start-api
The lambda is this...
exports.handler = async function() {
console.log("WooHoo! Test handler ran")
return {statusCode: 200, headers: {"Content-Type": "application/json"}, body: "Test handler ran!"}
}
Start of the huge ugly stack trace...
Mounting /home/user/code/image-cache/asset.beeaa749e012b5921018077f0a5e4fc3ab271ef1c191bd12a82aa9a92148782e as /var/task:ro,delegated inside runtime container
START RequestId: 99f53642-b294-4ce5-a1b4-8c967db80ce1 Version: $LATEST
2021-09-15T12:33:37.086Z undefined ERROR Uncaught Exception {"errorType":"Runtime.ImportModuleError","errorMessage":"Error: Cannot find module 'test'\nRequire stack:\n- /var/runtime/UserFunction.js\n- /var/runtime/index.js","stack":["Runtime.ImportModuleError: Error: Cannot find module 'test'","Require stack:","- /var/runtime/UserFunction.js","- /var/runtime/index.js"," at _loadUserApp (/var/runtime/UserFunction.js:100:13)"," at Object.module.exports.load (/var/runtime/UserFunction.js:140:17)",
The end of the huge ugly stack trace...
Invalid lambda response received: Lambda response must be valid json
So it would seem sam local start-api can't find test and throws and error which means the API gateway doesn't get a valid 'lambda response'. So far this has not helped me chase down the problem :/ It certainly seems aware that test is a route, as trying to hit other endpoints gives the classic {"message":"Missing Authentication Token"} but it chokes hard trying to fulfill it despite me having both functions/test.ts and the compiled functions/test.js present.
I have the test route and handler defined in my CDK stack definition like so...
const testLambda = new lambda.Function(this, "testLambdaHandler", {
runtime: lambda.Runtime.NODEJS_14_X,
code: lambda.Code.fromAsset("functions"),
handler: "test.handler"
})
api.root
.resourceForPath("test")
.addMethod("GET", new apigateway.LambdaIntegration(testLambda))
I considered posting my template.yml but that is even longer than the big ugly error message so I haven't.
So I have three questions (well actually a million but I don't want to be too cheeky!)
Is this actually the canonical way of locally testing apps made with CDK
If so, where am I going wrong?
If not, what is the better/proper way?
Lambda handlers are just functions. They do not need any special environment to function - they are called at a specific point in the Lambda Invocation process, and provided an event (a json object) and a context (another json object)
You can (and should!) unit test them just like any other individual function in your language/testing framework.
As #Lucasz mentioned, you should rely on the fact that, if set up properly, API gateway and Lambda will interact the same way every time. Once you have run one end to end test and you know that the basics work, any further implementation can be done trough unit testing
There are numerous libraries for mocking AWS service calls in unit testing, and there are plenty of good practice work arounds for the services that are more difficult to mock (ie: its difficult to mock a Lambda call from inside another lambda - but if you wrap that lambda call in its own function, you can mock the function itself to return whatever you want it to - and this is good practice for testing as well!)
using jest, in a coded unit test, you can call the lambda handler, give it stubbed or mocked event json, as well as a context json (probably just blank as youre not using it) and the lambda handler will act just like any other function with two parameters you've ever written, including returning what you want it to return.
You must be doing something wrong with your file directory. Where is your index.js located? If you generate the template.json, is the directory correct?
Also in what directory do you execute the Sam local command?
The thing with testing your serverless application is you don't have to test your full application. You need to count on AWS that API gateway, dynamodb and lambda is perfectly working.
The only thing you need to test is the logic you implemented.
In here you make sure your function prints out something and returns a 200. That's all you have to do.
Look into 'jest' for testing js.
If you want to test cdk you should into https://docs.aws.amazon.com/cdk/latest/guide/testing.html
Also "running Aws locally" is not good practice. it's never the same as how it's running in real life aka the cloud. You use plugins for this, tools for that... Local is not the same as in the cloud.
If you have any more questions, feel free to ask.

"internal server error" with API gateway and lambda on AWS

There are tons of similar questions both on this site and on the web, which leads me to believe there is something really wrong with AWS' documentation due to this causing grief to so many people.
So, I decided to post the most basic example step by step.
First, we create a new function:
It has default "everything", I don't touch a single line of code.
(the red error message is AWS not playing nice with Firefox)
The default code passes the test:
Now I add a trigger:
This gives me the link for the trigger:
I can go to the API endpoint: https://spy3z1jvu8.execute-api.ap-northeast-1.amazonaws.com/default/test
And it works:
Now, the problems will start. I open the API gateway that was created:
and try the default link: https://spy3z1jvu8.execute-api.ap-northeast-1.amazonaws.com
And...
Most of the people having similar questions seem to be having an issue with the gateway expecting some json content, etc, but here is an untouched AWS sample and the gateway link doesn't work.
The troubleshooting steps say to add logging and troubleshoot it that way, but there is nothing of interest in the logs.
What could be the origin of that problem?
What could be the origin of that problem?
You are correct. This is AWS/console fault. Specifically, it provides wrong permissions in the lambda's resource-based permissions for the default route to work. To fix that you have to edit the permissions.
Specifically, go to your function's Resource-based policy (this is different then execution role). You should find one Policy statement there which you have to edit. Then change in Source ARN from something like:
arn:aws:execute-api:ffffff:xxxx:api-id/*/*/function-name
to
arn:aws:execute-api:ffffff:xxxx:api-id/*/*

Unable to import module Error in AWS Lambda Nodejs

I am working on an AWS Lambda where I need to use AWS Textract, for this, I have used AWS-SDK, with AWS-SDK I was able to import s3, but AWS Textract is not working, when I deploy and test it shows,
Unable to import module 'src/functions/routes/handler': Error
I think it has something to do with packaging, like may be It is not packaging the relevant file, but not sure and I don't know how to make it package if it is the problem, any suggestions are appreciated.
Since you have not given any code to go on, I will consider the possibility that you have properly written your import code and this error is a valid response to an issue. In that case, you should note that there are issues with importing Textract in Lambda via the aws-sdk. See this reported issue:
https://github.com/aws/aws-sdk-js/issues/2728
For a thorough and thoughtful example of using Textract with a Lambda service, consider this excellent article posted with complete details:
https://medium.com/#sumindaniro/aws-textract-with-lambda-walkthrough-ed4473aedd9d

Error - functions: failed to create function dialogflowFirebaseFulfillment

when i'm trying to deploy firebase function from my local machine i'm getting this error.
functions: failed to create function dialogflowFirebaseFulfillment
HTTP Error: 400, Default service account 'project-id#appspot.gserviceaccount.com' doesn't exist. Please recreate this account (for example by disabling and enabling the Cloud Functions API), or specify a different account.
and the project that i'm trying to deploy is, https://github.com/actions-on-google/codelabs-nodejs/tree/master/level1-complete
It seems your service account is removed. You may want to check whether your firebase & actions on google projects are removed or not.
If they are not, check for service accounts on console.cloud.google.com and make sure all your accounts are same as you are trying to deploy. (firebase, dialogflow, app-engine etc.) Also, disabling and enabling the Cloud Functions API may help as mentioned in error.
I notice that your error has 'project-id#appspot.gserviceaccount.com'.
Shouldn't the project-id be your {project-id} from the google action that you created, and not the word project-id.

Serverless Framework AWS 403 Forbidden Error with Domain Only

I am working on a serverless setup for a project and ran into a strange error. This was working fine before I had to delete my old certificates and make a new one.
In short, I am following the tutorial series at serverless-stack.com for reference, and when running the apig-test command I get the following error.
{ status: 403,
statusText: 'Forbidden',
data: { message: 'Forbidden' } }
This screams to me policy error. So I went to check my policy to make sure it allows execution for the AuthRole and indeed it does. I verified this in IAM section under Roles and looked my services Auth_Role that I created when I set up Cognito.
I don't want to give information overload here, but if anyone has any ideas for where to look next I would be much appreciative and I'll give any details you want to see here.
One thing I want to note is that if I run the apig-test command with the direct URL to the Lambda function instead of my domain it works perfectly fine.
This proves that nothing is wrong with my code but more a policy setting regarding how I setup the domain.
I ran sls create_domain accordingly and I see the entries in the Route53 & API Gateway and they have finished their 40 minutes many hours ago. I insured its using correct certificate since I wiped out the other one.
My custom domains have worked in the past thanks to a plugin I found and this tutorial here (https://serverless.com/blog/serverless-api-gateway-domain/), its only recently that it stopped working when I realized I needed to add some more domains to my SSL cert.
So I assume the policy error is somewhere around this but not sure where to look?
Ok I found the answer. In the API Gateway under custom domains there is a section called Base Path Mappings This MUST be set to one of your functions with the default path of / (or just enter nothing for the path) and then the destination to your lambda service. This seemed to make it work for me.