Node.js Lambda Function "response is invalid" Amazon Alexa - node.js

UPDATE: I had a mistake on my http request endpoint. I had not set the appropriate authentication options so that fixed a lot of errors possibly this specific one.
My question is similar to one here:
Node.js Lambda function returns "The response is invalid" back to Alexa Service Simulator from REST call
However the solution to that question does not solve my problem. So I make an http request call to an xsjs service in Hana cloud. I am getting the 'response is invalid' error message. I can't see why. Here is my function:
// Create a web request and handle the response.
function httpGet(query, callback) {
console.log("/n QUERY: "+ query);
var host = 'datacloudyd070518trial.hanatrial.ondemand.com';
var path = '/LocationInformation/getLocationInfo.xsjs?location=';
var hostname = 'https://' + host + path + query;
var auth = 'user1:D1anafer';
var req = http.request({'hostname': hostname,
'auth': auth
}, (res) => {
var body = '';
res.on('data', (d) => {
body += JSON.stringify(d);
});
res.on('end', function () {
callback(body);
});
});
req.end();
req.on('error', (e) => {
console.error(e);
});
}
And the function that calls it:
'getNewsIntent': function () {
//self = this;
httpGet(location, function (response) {
// Parse the response into a JSON object ready to be formatted.
//var output = JSON.parse(response);
//output = output['change'];
var output = response;
var cardTitle = location;
var cardContent = output;
alexa.emit(':tellWithCard', output, cardTitle, cardContent);
});
},
Thank You
-Diana

Inside your AWS account go to your Lambda function and click on the monitoring tab, where you should see "View Logs in Cloudwatch" in the right hand corner. If you click that link and you should see the errors that are being produced.
You can also use console.log() to log any information being returned from your REST api, which will be logged in cloudwatch and can help you see where your errors are.

This is just a guess from the top of my head. To really help some detailed error message would be required like mentioned about.
But just a guess: Your http.request() is using the http module (https://nodejs.org/api/http.html) and your are accessing the a https resource. If so there is a https (https://nodejs.org/api/https.html) module or use something like axios https://www.npmjs.com/package/axios or requestjs (https://github.com/request/request) this will handle both.
Like I said just a blind guess without detailed error message and seeing your require statements but I am happy to dive deeper if you happen to have details.
HTH

Your callback from the Lambda has to return a valid status code and body. Like this:
let payload = {
statusCode: 400,
body: JSON.stringify('body'),
headers: {"Access-Control-Allow-Origin": "*"}
};
callback(null, payload);
On top of that, to call this from client side code, you have to pass the CORS header back.

Related

How do I send a proper request to browserstack in nightwatch.js custom command?

I've done a ton of research on this (browserstack docs, this older example, and npm docs to name a few) yet my code is still not working. I also reached out to browserstack, so I'm pending help from them. First I set the session ID:
module.exports.command = function (browser, done) {
browser.session(function (session) {
browser.browserStackSessionId = session.sessionId;
console.log("browser.bsSessionID: "+ browser.browserStackSessionId);
done();
});
Then, I make the request:
var request = require("request");
console.log("making request");
request({
uri: `https://${BROWSERSTACK_USERNAME}:${BROWSERSTACK_ACCESS_KEY}#api.browserstack.com/automate/sessions/${browser.browserStackSessionId}.json`,
method:"PUT",
form:{"status":"failed","reason": JSON.stringify(browser.currentTest.results.failure)}},
function (error, response, body) {
console.log("Error " + error);
console.log("Response " + JSON.stringify(response.statusCode));
})
When the code runs, the console logs appear in terminal. The session ID is what I expect. I incorrectly set the auth at first so I was receiving error responses which tells me that the code is running, but I'm not seeing updates in my browserstack dashboard so maybe the data isn't sending.
I see that you want to mark a test session as failed. Could you please try executing a sample NodeJS script:
var request = require("request");
request({uri: "https://your_browserstack_username:your_browserstack_access_key#api.browserstack.com/automate/sessions/<session-id>.json", method:"PUT", form:{"status":"passed","reason":""}})
The same details are available in the link: https://www.browserstack.com/automate/node#rest-api

Error: getaddrinfo ENOTFOUND in node.js webhook for dialogflow

I am trying to follow the dialogflow tutorial. I have set up a node.js webhook, that is called from Dialogflow, inside the webhook code I call out to an api. However, my node.js webhook is saying "Error: getaddrinfo ENOTFOUND". This works fine when I run it in visual code but cannot find the api with in the nodejs webhook, when called via DialogFlow. There is something about the fact that it is being called from Dialogflow that seems to be making it not work.
I have spent a lot of time on this, and had previsouly discovered that DialogFlow wont work with https where it is a self signed certificate, as such I put an azure function, so the webhook calls the azure function and then the azure function call the api that I need.
Sorry for the long post...
Here is the node.js code:
'use strict';
const http = require('http');
var request = require('request');
const apiUrl ="https://myapi";
exports.saledurationWebhook = (req, res) => {
// Get the city and date from the request
// let city = req.body.queryResult.parameters['geo-city']; // city is a required param
let city = "sdjk";
// Call the weather API
callSalesDurationApi(city).then((output) => {
res.json({ 'fulfillmentText': output }); // Return the results of the weather API to Dialogflow
})
.catch((err) => {
console.log(err);
//res.json({ 'fulfillmentText': `I don't know the sales duration is but I hope it's quick!` });
res.json({ 'fulfillmentText': err.message});
})
;
};
function callSalesDurationApi(city) {
return new Promise((resolve, reject) => {
console.log('API Request: ' + apiUrl);
var myJSONObject = {
"Inputs": "stuff"
};
request({
url: apiUrl,
method: "POST",
json: true, // <--Very important!!!
body: myJSONObject
}, function (error, response, body) {
console.log("successfully called api");
let output = "Current conditions in the " + body;
console.log(output);
console.log(body);
resolve(output);
});
});
}
Does anyone know why this might be happening? Or what frther steps I can take to investigate it? I have already looked at the loges for the webhook, and for the azure function.
Any help would be really gratefully recieved, I have already wasted days on this. If this is a duplicate question then I am sorry, I have tried to look for existing answers on this issue.
Thanks Laura
I have found this question already answered at: https://stackoverflow.com/a/46692487/7654050
It is because I have not set billing up for this project. I thought it been set up as it is on my work account.

Alexa: REST API call from intent

I am trying to code a simple skill. I'm trying to call Rest API from each intent.
For example:
TM.prototype.intentHandlers = {
"startIntent": function (intent, session, response) {
console.log("startIntent start");
// HOW TO CALL get http://mysite.site.com/app/start/1234
console.log("startIntent end");
response.ask("bla bla");
},
"endIntent": function (intent, session, response) {
console.log("endIntent start");
//HOW TO CALL post http://mysite.site.com/app/end/1234
console.log("endIntent end");
response.ask("bla bla bla");
},
Can anyone point me how would I called the URLS. I have try in many ways but the it seems that the request never arrived to the server.
Many thanks, Jeff
Repository of Alexa Cookbooks contains a lot of examples. Performing HTTP calls one of them.
The cookbook describes itself as:
AWS Lambda functions running Node.JS can make calls over the Internet
to APIs and services using the https module included in Javascript.
It contains the example how make HTTP calls.
you can use below sample code to call a REST api,
var req = http.get(url, (res) => {
var body = "";
res.on("data", (chunk) => {
body += chunk
});
res.on("end", () => {
var body = JSON.parse(body);
callBack(body)
});
}).on("error", (error) => {
callBack(err);
});
}
Please don't forgot to add the HTTP package like below,
var http = require('http');

Malformed Lambda proxy response

I am trying to access a Lambda function using a POST method. When I try to test the POST resource I put in the Request body {"article_url": "http://technewstt.com/bd1108/"}
This makes the API Gateway respond with Execution failed due to configuration error: Malformed Lambda proxy response My code is below.
exports.handler = (event, context, callback) => {
//event = {"article_url": "http://technewstt.com/bd1108/"};
console.log(event.article_url);
var http = require('http');
var TextAPI = require('textapi');
var textapi = new TextAPI({
application_id: "randomn numbers",
application_key: "randomn numbers"
});
textapi.summarize({
url: event.article_url,
sentences_number: 3
}, function(error, response) {
if (error === null) {
response.sentences.forEach(function(s) {
console.log(s);
//var body = JSON.parse(s);
// TODO implement
//callback(null, s);
callback(null, {"statusCode": 200, "body": JSON.stringify(s)});
});
}
});
};
Please note that if I uncomment the second line the API gateway works fine.
Any help with this issue would be greatly appreciated.
You are using Lambda Proxy integration which always expects output of the format http://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html#api-gateway-simple-proxy-for-lambda-output-format
"Malformed Lambda proxy response" is returned if the lambda response format is unexpected. You can enable logging with full request/responses which should show you the response being returned from lambda. Its likely there was an error in you lambda function which returned an error.

Node.js and the connect module: How do I get the message out of a request object sent to a web server

I'm using Node.js and connect to create a simple web server. I have something similar to the following code and I can't figure out how to access the actual request message body from the request object. I'm new to this so bear with me. I'm also taking out some of the stuff that's not necessary for the example.
function startServer(dir) {
var port = 8888,
svr = connect().use(connect.static(dir, {"maxAge" : 86400000}))
.use(connect.directory(dir))
/*
* Here, I call a custom function for when
* connect.static can't find the file.
*/
.use(custom);
http.createServer(svr).listen(port);
}
function custom(req, res) {
var message = /* the message body in the req object */;
// Do some stuff with message...
}
startServer('dirName');
Make sense? I've tried logging that object to the console and it is full of TONS of stuff. I can easily see headers in there plus the request URL and method. I just can't seem to isolate the actual message body.
You should include the connect.bodyParser middleware as well:
svr = connect().use(connect.static(dir, {"maxAge" : 86400000}))
.use(connect.directory(dir))
.use(connect.bodyParser())
.use(custom);
That will provide the parsed message body as req.body to your handler.
If you want the raw message body, you shouldn't use it but instead read the req stream yourself:
function custom(req, res) {
var chunks = [];
req.on('data', function(chunk) {
chunks.push(chunk);
});
req.on('end', function() {
var rawbody = Buffer.concat(chunks);
...do stuff...
// end the request properly
res.end();
});
}
if(req.method == "POST"){
var body = '';
req.on('data', function(data){
body += data;
});
}
Then body should contain your message if you posted correctly.
A better idea would be to use Express, then use the bodyparser middleware - which will give you this functionality out of the box without worrying about somebody hammering your server. The code above has NO functionality to worry about attacks - but it will get you started.

Resources