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.
Related
I want to fordward a call to a Studio Flow after the agent in flex hangs up so a CSAT survey can play for the user.
I created a plugin that calls a function inside Twilio but there is a "Error - 11200" after the forwarding is done.
I replaced the hang up action so it redirects the call to a function in twilio. The function is supossed to send the call to a flow that will play the survey. I suspect the problem has to do with authentication but I can't find much about it.
I'm fairly new to twilio, so any help will be greatly appreciated
This is the part of the plugin that calls the function:
flex.Actions.replaceAction("HangupCall", (payload) => {
console.log('task attributes: ' + JSON.stringify(payload.task.attributes));
if (payload.task.attributes.direction === "inbound") {
// Describe the body of your request
const body = {
callSid: payload.task.attributes.call_sid,
callerId: payload.task.attributes.from,
destination: '+18xxxxxxxx',
Token: manager.store.getState().flex.session.ssoTokenPayload.token
};
// Set up the HTTP options for your request
const options = {
method: 'POST',
body: new URLSearchParams(body),
headers: {
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
}
};
// Make the network request using the Fetch API
fetch('https://TWILIO INSTANCE.twil.io/TransferUtil', options)
.then(resp => resp.json())
.then(data => console.log(data));
} else {
original(payload);
}
});
And this is the function in twilio:
const TokenValidator = require('twilio-flex-token-validator').functionValidator;
exports.handler = TokenValidator(async function(context, event, callback) {
const response = new Twilio.Response();
response.appendHeader('Access-Control-Allow-Origin', '*');
response.appendHeader('Access-Control-Allow-Methods', 'OPTIONS, POST, GET');
response.appendHeader('Access-Control-Allow-Headers', 'Content-Type');
response.appendHeader('Content-Type', 'application/json');
const client = require('twilio')();
const callSid = event.callSid;
const callerId = event.callerId;
const destination = event.destination;
console.log('Call Sid:', callSid);
console.log('Transfer call from:', callerId, 'to:', destination);
try {
let url = 'https://studio.twilio.com/v2/Flows/FWXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Executions';
let call = await client.calls(callSid).update({method: 'POST', url: encodeURI(url)});
console.log(JSON.stringify(call));
response.appendHeader('Content-Type', 'application/json');
response.setBody(call);
callback(null, response);
}
catch (err) {
response.appendHeader('Content-Type', 'plain/text');
response.setBody(err.message);
console.log(err.message);
response.setStatusCode(500);
callback(null, response);
}
});
EDIT:
In the error Log I get this information:
Argh, I read the error wrong. There isn't anything wrong with the Function, the error is coming from the call trying to make a webhook request to the URL https://studio.twilio.com/v2/Flows/FWXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Executions. That's the REST API trigger and needs to be requested in the same way as any other API request using your account credentials or API keys.
You should set that URL to the webhook trigger URL, which looks like https://webhooks.twilio.com/v1/Accounts/${ACCOUNT_SID}/Flows/${FLOW_SID}. Then the call will be able to request it as part of a normal webhook flow.
So I'm new to AWS serverless architecture. I deployed my first lambda function using Claudia. I'm not sure whether I did it correctly. I deployed all the APIs to one lambda function using Claudia. The API endpoints works individually when I test it on Insomnia. But when I use it in my application only one specific API works and the lambda dies. For instance, I used this POST request to post some items and I have a useEffect in my React application which has a get request to retrieve all the items from the database. But once I post the item, nothing is returned. Could anyone help me understand what I'm doing wrong. P.S this is my final year project which is due in a few weeks. So, a quick answer would be appreciated.
Here is a sample code.
// Create a new Intake
router.post("/create", async (req, res) => {
const intake = req.body;
const { name, intakeCode, intakeYear } = req.body;
const checkIntake = await Intakes.findOne({
where: {
intakeCode: intakeCode,
},
});
if (checkIntake) {
res.json({ err: `An intake under ${intakeCode} already exists!` });
} else {
try {
await Intakes.create(intake);
res.json({ msg: `Successfully created ${name} ` });
} catch (e) {
if (e.name == "SequelizeDatabaseError") {
res.json({ err: "Year only accepts integer" });
} else {
res.json({ err: e.name });
}
}
}
});
// Find all Intakes
router.get("/findAll", async (req, res) => {
const listOfIntakes = await Intakes.findAll();
res.json(listOfIntakes);
});
Cheers
Looks like you are trying to build a Lambda function using JavaScript - but have encountered problems. I'm not familiar with Claudia. One suggestion that I have is to follow the official AWS SDK for JavaScript DEV Guide here:
https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/scheduled-events-invoking-lambda-example.html
That content will walk you through how to create a Lambda function using JS.
On firebase function I need to get data from Paypal and do 4 things :
1. returns an empty HTTP 200 to them.
2. send the complete message back to PayPal using `HTTPS POST`.
3. get back "VERIFIED" message from Paypal.
4. *** write something to my Firebase database only here.
What I do now works but i am having a problem with (4).
exports.contentServer = functions.https.onRequest((request, response) => {
....
let options = {
method: 'POST',
uri: "https://ipnpb.sandbox.paypal.com/cgi-bin/webscr",
body: verificationBody
};
// ** say 200 to paypal
response.status(200).end();
// ** send POST to paypal back using npm request-promise
return rp(options).then(body => {
if (body === "VERIFIED") {
//*** problem is here!
return admin.firestore().collection('Users').add({request.body}).then(writeResult => {return console.log("Request completed");});
}
return console.log("Request completed");
})
.catch(error => {
return console.log(error);
})
As you can see when I get final VERIFIED from Paypal I try to write to the db with admin.firestore().collection('Users')..
I get a warning on compile :
Avoid nesting promises
for the write line.
How and where should I put this write at that stage of the promise ?
I understand that this HTTPS Cloud Function is called from Paypal.
By doing response.status(200).end(); at the beginning of your HTTP Cloud Function you are terminating it, as explained in the doc:
Important: Make sure that all HTTP functions terminate properly. By
terminating functions correctly, you can avoid excessive charges from
functions that run for too long. Terminate HTTP functions with
res.redirect(), res.send(), or res.end().
This means that in most cases the rest of the code will not be executed at all or the function will be terminated in the middle of the asynchronous work (i.e. the rp() or the add() methods)
You should send the response to the caller only when all the asynchronous work is finished. The following should work:
exports.contentServer = functions.https.onRequest((request, response) => {
let options = {
method: 'POST',
uri: "https://ipnpb.sandbox.paypal.com/cgi-bin/webscr",
body: verificationBody
};
// ** send POST to paypal back using npm request-promise
return rp(options)
.then(body => {
if (body === "VERIFIED") {
//*** problem is here!
return admin.firestore().collection('Users').add({ body: request.body });
} else {
console.log("Body is not verified");
throw new Error("Body is not verified");
}
})
.then(docReference => {
console.log("Request completed");
response.send({ result: 'ok' }); //Or any other object, or empty
})
.catch(error => {
console.log(error);
response.status(500).send(error);
});
});
I would suggest you watch the official Video Series on Cloud Functions from Doug Stevenson (https://firebase.google.com/docs/functions/video-series/) and in particular the first video on Promises titled "Learn JavaScript Promises (Pt.1) with HTTP Triggers in Cloud Functions".
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');
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.