actions-on-google / actions-on-google-nodejs

Node.js client library for Actions on Google
https://actions-on-google.github.io/actions-on-google-nodejs
Apache License 2.0
899 stars 193 forks source link

AWS Lambda with API Gateway #368

Open valhus opened 5 years ago

valhus commented 5 years ago

I'm having a issue with AWS that I really can't understand. My app starts correct, using the simulator that will trigger an intent results in an error that I really don't understand.

Code in AWS:

const { dialogflow, Table, Image } = require('actions-on-google');
const df = dialogflow({debug: true});

df.intent('nextdeparture', async (conv, params) => {
  conv.close('aws test');
});

exports.fulfillment = df;

From the logs in aws I can see a simpleResponse

{
    "status": 200,
    "headers": {
        "content-type": "application/json;charset=utf-8"
    },
    "body": {
        "payload": {
            "google": {
                "expectUserResponse": false,
                "richResponse": {
                    "items": [
                        {
                            "simpleResponse": {
                                "textToSpeech": "aws test"
                            }
                        }
                    ]
                }
            }
        }
    }
}

But this is what I'm getting in the simulator:

MalformedResponse Failed to parse Dialogflow response into AppResponse because of invalid platform response: Could not find a RichResponse or SystemIntent in the platform response for agentId: 0da3cbb2-f7db-4297-bb2c-4bbf18a73db1 and intentId: 9aa705a5-6984-4905-859e-9307d4af625e.

JBaczuk commented 5 years ago

I'm seeing the same thing. Did you find a resolution?

JBaczuk commented 5 years ago

It appears the sdk does not support Lambda + Api Gateway out of the box, like the docs suggest, it returns an object with additional properties (status, body, etc.). You have to create your own custom handler and only send the body, see https://github.com/actions-on-google/actions-on-google-nodejs/issues/219#issuecomment-466573394

module.exports.handler = (event: any, context: any, callback: any) => {
  const body = event.body || event;
  const headers = event.headers || context.request.headers || [];
  return app.handler(body, headers).then(res =>
    if (res.status != 200) {
        callback(null, {"fulfillmentText": `I got status code: ${res.status}`});
    } else {
        callback(null, res.body);
    }
  };
};

I also had to forward the headers from API Gateway using this guide: https://aws.amazon.com/premiumsupport/knowledge-center/custom-headers-api-gateway-lambda/