Send POST HTTP with ClaudiaJS and AWS Lambda - node.js

I building a service for push notifications in the facebook messenger. My nodejs app works fine in my localhost, but doesn't in AWS.
I use request module (npm) for send message.
My service can get the parameters, but doesn't send HTTP POST.
var ApiBuilder = require('claudia-api-builder'),
api = new ApiBuilder();
var request = require('request')
api.get('hello', function (req) {
var token = req.queryString.token;
var sender = req.queryString.sender;
var msg = req.queryString.msg;
messageData = {};
messageData.text = msg;
request({
url: 'https://graph.facebook.com/v2.6/me/messages',
qs: { access_token: token },
method: 'POST',
json: {
recipient: { id: sender },
message: messageData,
}
}, function (error, response, body) {
if (error) {
return 'Error sending message: ' + error;
} else if (response.body.error) {
return 'Error: ' + response.body.error;
}
});
return sender + ' ' + messageData.text ;
})
module.exports = api;

You need to return a promise out of the API builder method handler for asynchronous operations. You can use something like got or minimal-request-promise to turn the HTTP request into a Promise, or just use a simple promise wrapper such as return new Promise((resolve, reject) => request(...., function (error, result) { if (error) { return reject(errror); else resolve(result) } }))
See item #4 in the guide on how to use external services from Claudia here: https://claudiajs.com/tutorials/external-services.html

Related

return a value from azure function to another function nodejs

I am trying to get a value from another azure function within another azure function.
When I call this function from postman I get the correct response. I get the accessToken. But when I call the same function in code and assign it to a variable it just becomes a big weird object.
const request = require("request");
module.exports = function GetAuth(context, req) {
context.log('JavaScript HTTP trigger function processed a request.');
var url = "myurl.com";
clientId = "****";
clientSecret = "****";
tenantId = "****";
const requestParams = {
grant_type: "client_credentials",
client_id: clientId,
client_secret: clientSecret,
resource: "https://graph.windows.net"
};
request.post({ url: url, form: requestParams }, function (err, response, body) {
if (err) {
console.log("error");
}
else {
let parsedBody = JSON.parse(body);
if (parsedBody.error_description) {
console.log("Error=" + parsedBody.error_description);
}
else {
context.res = {
body: parsedBody.access_token
};
context.done();
}
}
});
}
This is how I am calling the function.
module.exports = async function (context, req) {
context.log('JavaScript HTTP trigger function processed a request.');
const accessToken = request.get("http://localhost:7071/api/GetAuth");
console.log(accessToken);
}
I don't quite know how to get it from the GetAuth function to the other function.
Any help is appreciated.
One work around would be to use axios to make the calls to the other azure function.
Here I have use .get method to make a get request to the other function and then console.log the response.
axios.get('http://localhost:7071/api/HttpTrigger1').then(resp=>{console.log(resp.data); })
Here the http://localhost:7071/api/HttpTrigger1 is returning a Json object.

Issue posting API request from AWS Lambda with nodejs

completely beginner question here, but im stuck for hours, hope someone can help!
I'm building some thing over AWS API Gateway + Lambda, where I receive a POST request on AWS and I send some data to another API.
I'm using https from NodeJS (from examples i found here on stackoverflow) but it doesnt seem to be working...I'm testing by sending it to a webhook inbox in beeceptor
Could you give me some light?
exports.handler = async (event) => {
if(event.httpMethod == 'POST'){
return pedido(event);
}
};
var aid = '';
var cep = '';
const pedido = event => {
let body = JSON.parse(event.body);
var aid = body.cid;
//var sku = body.items.id
var cep = body.cep;
callapi(cep,aid);
console.log("teste cep ", body.cep);
return{
statusCode: 200,
body: JSON.stringify({
message: body.cep,
convid: aid
})
};
};
function callapi(cep,aid){
const https = require('https');
const data = JSON.stringify({
message: cep,
convid: aid,
test: 123
});
console.log("data is ", data);
const options = {
hostname: 'testbot.free.beeceptor.com',
//port: 443,
path: '/',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': data.length
}
};
console.log("code was here ");
var req = https.request(options, (res) => {
console.log('req:', req);
console.log('res:', res);
console.log('statusCode:', res.statusCode);
console.log('headers:', res.headers);
res.on('data', (d) => {
process.stdout.write(d);
});
});
console.log('req:', req);
req.on('error', (e) => {
console.error(e);
});
req.write(data);
req.end();
}
There's at least one problem with your code:
The callapi function is making a request and this request is using a callback to notify you about a response. However, you are not waiting for it in your Lambda code and hence you won't see its response in your logs. Add appropriate awaits or Promises to it, so your code won't return before you've received a response.
The structure of your code could look similar to this:
exports.handler = async (event) => {
if (event.httpMethod === 'POST') {
return await pedido(event);
}
};
async function pedido(event) {
// init vars...
// wait for your API call
await callapi(cep, aid);
// then return a response
return {...}
}
async function callapi(cep, aid) {
// init vars like https and others...
// then use a promise and resolve it when you receive the request's callback (= response) or an error
return new Promise((resolve, reject) => {
const req = https.request(options, (res) => {
// handle response however you like ...
// then resolve the promise when you're done
resolve();
});
req.on('err', (e) => {
// reject in case the request fails
reject(e);
});
});
}
Does this solve your problem? If not, having some more logs of your method and a simplified code example would help a lot!

I can't save the response of a request request in node.js

I created a login function that receives the mail and the pass, to receive the jwt. I have tried that the function returns the jwt but I have not succeeded.
This is the method that I have developed, it has a post request that sends the mail and pass parameters. in the resp variable I try to save the request response, but when invoking the function it prints :
undefined.
login(mail, pass) {
var options = {
'method': 'POST',
'url': 'https://inventario.demos.adlnetworks.com/api/login',
'headers': {
'Content-Type': 'application/json'
},
body: JSON.stringify({ "email": mail, "password": pass })
};
var resp;
var req = request(options, function(error, response) {
if (error) throw new Error(error);
resp = response.body;
});
return resp;
}
The problem is that "request" is an async function. You can't do this
var resp;
var req = request(options, function(error, response) {
if (error) throw new Error(error);
resp = response.body;
});
return resp;
Because "resp" always be undefined. You would need to do something like this
var resp;
var req = request(options, function(error, response) {
if (error) throw new Error(error);
return response.body;
});
But it wont work for you.
The short and easy solution is change the library to make http request, and use "async" and "await" to use easily async functions.
For example:
const fetch = require('node-fetch');
async function main(){
const data = await login();
console.log(data);
}
async function login(){
const url = "https://jsonplaceholder.typicode.com/posts";
const data = {
title: 'foo22222',
body: 'ba222r',
userId: 1
};
const response = await fetch(url, {
method: 'POST',
body: JSON.stringify(data),
headers: {
"Content-type": "application/json; charset=UTF-8"
}
});
const json = await response.json()
return json;
}
main();
In this case i use "node-fetch" library and consume a backend (in login function) that create a post and return its response.

I get error when trying to subscribe to the getStream Websocket

Currently, I am integrating websockets for the feeds using GetStream JS library.
But I can't subscribe to the websocket by following the instruction
I have created Flat Feeds and it's working fine. I can do all the actions with activities. But I need to integrate my app with websocket so that it can update the feed live.
I've followed the steps that described in the feed document
async initializeStream(profile, followings = []) {
try {
const { peerID } = profile;
const response = await getStreamToken(peerID);
const { token } = response;
this.token = token;
this.client = stream.connect(STREAM_API_KEY, token, STREAM_APP_ID);
await this.createUser(profile);
this.feed = this.client.feed('user', peerID, token);
this.globalFeed = this.client.feed('user', 'all', token);
return true;
} catch (err) {
return false;
}
}
This is stream initialization part and it works fine without any flaw.
And below is subscription function:
subscribe (subscribingFunction) {
return this.feed.subscribe(subscribingFunction);
}
And this one is how I am using subscription function to integrate websocket:
StreamClient.subscribe((data) => {
console.log('stream - update received');
console.log(data);
// return emitter({ type: 'STREM/UPDATE_RECEIVED', payload: data });
}).then(response => {
console.log('success', response)
}).catch(response => {
console.log('failure', response)
});
Expected Result:
Websocket subscription is success and I can get the live updates through it.
Result:
I am getting this error when trying to subscribe to websocket:
klass {code: null, params: Array(0), message: "Failed to authenticate. Please check your API Token, App ID and Feed ID."}
Can you point me out what went wrong with this configuration?
Here's code for the getStreamToken function:
export const getStreamToken = (userId) => {
const apiURL = `${tokenServerAPI}/getToken?user_id=${userId}`;
const headers = {
method: 'GET',
headers: {
authorization: `Basic ${base64.encode('ob_stream_user:ob_stream_pwd')}`,
},
};
return fetch(
apiURL,
headers,
).then(response => response.json()).catch(err => {
console.log(err);
});
};

How can I implement a firebase set request within a call back

I'm new to node js and I would like to write information within a callback function to my firebase database.
I've been searching and it seems that the callback is asynchronous. How can I use firestore in this callback?
exports.registerRestaurantPayout = functions.firestore.document('*********')
.onCreate(async (paymentSnap, context) => {
var request = require('request');
var authCode = paymentSnap.data().auth_code;
var firstString = 'client_secret=********&code=';
var secondString = '&grant_type=authorization_code';
var dataString = firstString + authCode + secondString;
var options = {
url: 'https://connect.stripe.com/oauth/token',
method: 'POST',
body: dataString
};
function callback(error, response, body) {
if (!error && response.statusCode === 200) {
console.log(body);
return await firestore.document('***********')
.set({'account': body}, {merge: true});
//return await paymentSnap.ref.set({'account': body}, {merge: true});
}else{
//return await paymentSnap.ref.set({'error' : error}, { merge: true });
}
}
request(options, callback);
});
I get the following error Parsing error: Unexpected token firestore even though I can use firestore outside of the callback. The specific problem is the return statement in the callback
In a Cloud Function you should use promises to handle asynchronous tasks (like the HTTP call to the stripe API, or the write to the Realtime Database). By default request does not return promises, so you need to use an interface wrapper for request, like request-promise, and adapt your code along the following lines:
const rp = require('request-promise');
exports.registerRestaurantPayout = functions.firestore.document('*********')
.onCreate((paymentSnap, context) => {
var authCode = paymentSnap.data().auth_code;
var firstString = 'client_secret=**********=';
var secondString = '&grant_type=authorization_code';
var dataString = firstString + authCode + secondString;
var options = {
method: 'POST',
uri: 'https://connect.stripe.com/oauth/token',
body: dataString,
json: true // Automatically stringifies the body to JSON
};
return rp(options)
.then(parsedBody => {
return paymentSnap.ref.set({'account': parsedBody}, {merge: true});
})
.catch(err => {
return paymentSnap.ref.set({'error' : err}, { merge: true });
});
});
I would also suggest that you watch the two following "must see" videos from the Firebase team, about Cloud Functions and promises: https://www.youtube.com/watch?v=7IkUgCLr5oA and https://www.youtube.com/watch?v=652XeeKNHSk.

Resources