Why aws express lambda can't invoke pure lambda fucntion? - node.js

I am very new in this lambda stuffs.
I have an express app. I have uploaded the app as it is using claudia to aws lambda.
I have anothe app that is pure lambda app.
When I invoke the pure lambda function from my express app in local host, it works.
But when I call it form the express lambda function, it returns a 502 error.
I am not understanding the issue. Is it happening because I have uploaded the express app as it is(all other apis/end-points are working) or is there any configuration issue?
Contorller
exports.paywithcard = async (req,res,next) =>{
let obj
try{
obj = await StripeService.payMoney(req.body)
obj = JSON.parse(obj.body)
req.body.paid_id = obj.charge.id
res.json({
message: "Payment Successful",
success: true,
updatedAsset:assetResponse[0]
})
}
catch(err){
res.json({
message: "Rejected",
success: false,
})
}
**the service file where I invoke the pure lambda function
exports.payMoney = async(user)=>{
return await new Promise((resolve, reject) =>{
const params = {
FunctionName:'stripe_payment',
Payload: JSON.stringify({
user
})
}
console.log(params," paramsssssssssss")
lambda.invoke(params,(err,results)=>{
console.log(err," err and resultssssssssssssssssss ")
if(err) reject(err)
else {
//console.log("results ",results," results")
let res_obj = JSON.parse(results.Payload)
//obj = JSON.parse(obj.body)
// obj = JSON.parse(obj.charge)
//console.log(obj.charge.id,)
resolve(res_obj)
//return obj.charge.id
}
})
})
}
The pure Lambda function that has been being invoked
const stripe = require("stripe")(process.env.STRIPE_SECRET_TEST)
exports.handler = async (event, context, callback) => {
console.log("Hello worls!!!!!")
const requestBody = event.user;
console.log((requestBody," request body !!!!!!!!!"))
const token = requestBody.id;
const amount = requestBody.amount;
const currency = "USD";
const customer = requestBody.customer
console.log("req body",requestBody)
return stripe.paymentIntents.create({ // Create Stripe charge with token
amount,
currency,
description: 'Serverless Stripe Test charge',
payment_method: token,
customer,
confirm: true
})
.then((charge) => { // Success response
console.log(charge," charge")
const response = {
statusCode: 200,
headers: {
'Access-Control-Allow-Origin': 'https://stage-back.eidverse.io',
},
body: JSON.stringify({
message: `Charge processed succesfully!`,
charge,
}),
"isBase64Encoded": false,
};
callback(null, response);
})
.catch((err) => { // Error response
console.log(err,"err charge")
const response = {
statusCode: 500,
headers: {
'Access-Control-Allow-Origin': '*',
},
body: JSON.stringify({
error: err.message,
}),
};
callback(null, response);
})
};
There is no try catch issue in the console log.
Task timed out after 6.01 seconds
Please let me know if any other information I have missed to share. Thank you.

Related

How to use twillio to text a weather update using weather api in node.js

I have twillio texting me everyday at 8am, a message from aws lambda but I want it to text me the weather for the day. Im trying to use a weather api but I cant figure out how to do it
I tried JSON.stringify() but it didnt work
const axios = require("axios");
const options = {
method: 'GET',
url: 'https://dark-sky.p.rapidapi.com/30.4383,-84.2807',
params: {units: 'auto', lang: 'en'},
headers: {
'X-RapidAPI-Key': 'XXXXXXXX',
'X-RapidAPI-Host': 'dark-sky.p.rapidapi.com'
}
};
axios.request(options).then(function (response) {
console.log(response.data);
}).catch(function (error) {
console.error(error);
});
exports.handler = (event, context, callback) => {
const accountSid = process.env.ACCOUNT_SID;
const authToken = process.env.AUTH_TOKEN;
const client = require('twilio')(accountSid, authToken);
// Send a text message
client.messages.create({
body: 'TEXT MESSAGE EXAMPLEi',
to: 'XXXXX', // your phone number
from: 'XXXXXXX' // a valid Twilio number
})
.then((message) => {
// Success, return message SID
callback(null, message.sid);
})
.catch((e) => {
// Error, return error object
callback(Error(e));
});
};

Problem with axios and activeCampaign api

i have created firebase cloud function to create contact in activeCampain. I have problem with catch errors from activeCampaign. If i sent request direct to activeCampain from insomnia everything works correctly, but if i use firebase cloud function with axios something goes wrong.
I will show the code.
I created a contact before and now it makes another query with the same data directly to activeCampaign api:
and i get expected result. But if made same request by firebase function i get properly status code but i don't see errors response from activeCampaign
FirebaseCloud function code:
const functions = require("firebase-functions");
const axios = require("axios");
const cors = require("cors")({ origin: true });
const addTagToContact = async (contactId: string, tagId: string) => {
try {
await axios({
method: "post",
url: "https://xyz.api-us1.com/api/3/contactTags",
headers: {
"Api-Token": "api-token",
},
data: {
contactTag: {
contact: contactId,
tag: tagId,
},
},
enter code here
});
} catch (e) {
console.error(e);
}
};
export const createNewContact = functions.https.onRequest((request: { body: any; }, response: { status: (arg0: number) => void; send: (arg0: { response?: unknown; status?: string; }) => void; }) => {
cors(request, response, async () => {
const newContactData = request.body;
if(!newContactData.email || !newContactData.fieldValues) {
return response.send({
response: 'No contact data provided'
})
}
try {
const responseActiveCampaign = await axios({
method: "post",
url: "https://xyz.api-us1.com/api/3/contacts",
headers: {
"Api-Token": "api-token",
"Content-Type": "application/json"
},
data: {
contact: newContactData,
},
});
console.log('response active campaign console log', responseActiveCampaign)
await addTagToContact(responseActiveCampaign.data.contact.id, "1")
return response.send({
response: responseActiveCampaign.data
})
} catch (error) {
console.error('catch error', error);
response.status(500);
response.send({
response: error,
});
}
});
});
response from this query:
How can i fix it? I would like to get error response from activeCampaign to use on my frontend
the catch should be like this:
catch (error) {
console.error('catch error', error);
response.status(500);
response.send({
response: error.response.data,
});
}

FaunaDB returns empty array (FaunaDB + Netlify + VueJS)

My code is based on the repository - https://github.com/ttntm/recept0r-ts
Code from "\functions\read-all.js":
const faunadb = require('faunadb');
const fnHeaders = require('./_shared/headers.js');
exports.handler = (event, context) => {
const client = new faunadb.Client({
secret: process.env.FAUNA_SECRET,
domain: 'db.fauna.com',
scheme: 'https',
port: '443'
});
const q = faunadb.query;
const headers = { ...fnHeaders };
const origin = event.headers.Origin || event.headers.origin;
headers['Access-Control-Allow-Origin'] = origin ? origin : '*';
return client.query(q.Paginate(q.Match(q.Index('all_users'), false), { size: 500 }))
.then((response) => {
const listRefs = response.data;
const getListDataQuery = listRefs.map(ref => q.Get(ref)); // create new query out of list refs, then query the refs
return client.query(getListDataQuery).then((records) => {
return { statusCode: 200, headers: headers, body: JSON.stringify(records) }
})
})
.catch((error) => {
return { statusCode: 400, headers: headers, body: JSON.stringify(error) }
});
}
Code from "\src\store\modules\data.js":
async readAll({ commit, dispatch, rootGetters })
{
const fn = rootGetters['app/functions'];
const request = await fetch(fn.readAll, { method: 'GET' });
const response = await request.json();
if (response.length > 0) {
commit('SET_ALL_RECIPES', response);
commit('SET_LAST_UPDATED', new Date); }
else {
dispatch('app/sendToastMessage', { text: 'Error loading recipes. Please try again later.', type: 'error' }, { root: true });
return 'error';
}
}
Everything seems to be set. For example, this code works:
client.query(q.CreateCollection({ name: 'someCollection' }))
But can't read any data.
If launch application by "netlify dev" (localhost) - "read-all" returns empty array ("[]").
If launch application by "network" - "read-all" returns default "index.html".
I have no idea what's wrong. Maybe someone give advice...
I found a similar question - Local Netlify function server gives strange response instead of FaunaDB data
Some answer:
"In my experience, one of the most common reasons for this error is a routing problem, which is triggering a 404 response route serving HTML instead of your expected function handler."
This code works:
return client.query(q.Paginate(q.Documents(q.Collection('customers')), { size: 500 }))
.then((response) => {
const listRefs = response.data;
const getListDataQuery = listRefs.map(ref => q.Get(ref)); // create new query out of list refs, then query the refs
return client.query(getListDataQuery).then((records) => {
return { statusCode: 200, headers: headers, body: JSON.stringify(records) }
});
})
.catch((error) => {
return { statusCode: 400, headers: headers, body: JSON.stringify(error) }
});

Firebase functions take MINUTES to write in Firestore

I'm building a mobile app and on some actions (like userCreate), I trigger some Firebase functions to perform an API call to a third service, and then write something in the Firestore database.
Everything works in theory, but in practice, the API calls are quite fast (even with cold start scenarios), but the database writes can take several MINUTES to complete (if they do at all, I suspect that sometimes it takes too long and times out).
Since the API call work just fine, and so does the DB write on some occasion, I suspect that this is simply due to very poor async management from me since I know about nothing in JS.
Here are two of many example functions which are concerned by this issue, just to showcase that it happens whereas I'm triggering functions onCreate or on HTTPS.
onCreate function
const functions = require("firebase-functions");
const axios = require('axios')
// The Firebase Admin SDK to access the Firestore.
const admin = require('firebase-admin');
admin.initializeApp();
// Third party service credentials generation during onCreate request
exports.
buildCredentials = functions.auth.user().onCreate((user) => {
// Request to Third party to generate an Client Access Token
axios({
method: "post",
url: "https://api.ThirdParty.com/api/v1/oauth/token",
data: "client_id=xxx&client_secret=yyy&grant_type=client_credentials&scope=all:all",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
})
.then(function (response) {
//handle success
console.log('new user created: ')
console.log(user.id);
console.log(response.data);
// We write a new document in the users collection with the user ID and the Client Access Token
const db = admin.firestore();
const newUser = {
uid: user.uid,
clientAccessToken: response.data.access_token
};
db.collection('users').doc(user.uid).set(newUser)
.catch(function (error) {
//handle error
console.log(error);
});
})
.catch(function (response) {
//handle error
console.log(response);
});
})
HTTPS onCall function
exports.paymentRequest = functions.https.onCall(async (data, context) => {
const clientAccessToken = data.clientAccessToken;
const recipientIban = data.recipientIban;
const recipientName = data.recipientName;
const paymentDescription = data.paymentDescription;
const paymentReference = data.paymentReference;
const productPrice = parseInt(data.productPrice);
const uid = data.uid;
const jsonData = {
"destinations": [
{
"accountNumber": recipientIban,
"type": "iban"
}
],
"amount": productPrice,
"currency": "EUR",
"market": "FR",
"recipientName": recipientName,
"sourceMessage": paymentDescription,
"remittanceInformation": {
"type": "UNSTRUCTURED",
"value": paymentReference
},
"paymentScheme": "SEPA_INSTANT_CREDIT_TRANSFER"
};
(async function(){
response = await axios({
method: "post",
url: "https://api.ThirdParty.com/api/v1/pay",
headers: {
'Content-Type': 'application/json',
Accept: 'application/json',
Authorization: `Bearer ${clientAccessToken}`,},
data: jsonData,
})
// We write a the payment request ID in the user's document
const db = admin.firestore();
const paymentRequestID = response.data.id;
db.collection('users').doc(uid).set({
paymentRequestID: paymentRequestID
}, { merge: true })
.catch(function (error) {
//handle error
console.log(error);
});
console.log(response.data)
return response.data
})()
})
Am I on the right track thinking that this is an async problem?
Or is it a Firebase/Firestore issue?
Thanks
You are not returning the promises returned by the asynchronous methods (axios() and set()), potentially generating some "erratic" behavior of the Cloud Function.
As you will see in the three videos about "JavaScript Promises" from the official Firebase video series you MUST return a Promise or a value in a background triggered Cloud Function, to indicate to the platform that it has completed, and to avoid it is terminated before the asynchronous operations are done or it continues running after the work has been completed.
The following adaptations should do the trick (untested):
onCreate Function:
buildCredentials = functions.auth.user().onCreate((user) => {
// Request to Third party to generate an Client Access Token
return axios({
method: "post",
url: "https://api.ThirdParty.com/api/v1/oauth/token",
data: "client_id=xxx&client_secret=yyy&grant_type=client_credentials&scope=all:all",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
})
.then(function (response) {
//handle success
console.log('new user created: ')
console.log(user.id);
console.log(response.data);
// We write a new document in the users collection with the user ID and the Client Access Token
const db = admin.firestore();
const newUser = {
uid: user.uid,
clientAccessToken: response.data.access_token
};
return db.collection('users').doc(user.uid).set(newUser)
})
.catch(function (response) {
//handle error
console.log(response);
return null;
});
})
Callable Function:
exports.paymentRequest = functions.https.onCall(async (data, context) => {
try {
const clientAccessToken = data.clientAccessToken;
const recipientIban = data.recipientIban;
const recipientName = data.recipientName;
const paymentDescription = data.paymentDescription;
const paymentReference = data.paymentReference;
const productPrice = parseInt(data.productPrice);
const uid = data.uid;
const jsonData = {
// ...
};
const response = await axios({
method: "post",
url: "https://api.ThirdParty.com/api/v1/pay",
headers: {
'Content-Type': 'application/json',
Accept: 'application/json',
Authorization: `Bearer ${clientAccessToken}`,
},
data: jsonData,
})
// We write a the payment request ID in the user's document
const db = admin.firestore();
const paymentRequestID = response.data.id;
await db.collection('users').doc(uid).set({
paymentRequestID: paymentRequestID
}, { merge: true })
console.log(response.data)
return response.data
} catch (error) {
// See https://firebase.google.com/docs/functions/callable#handle_errors
}
})

AWS Lambda not calling third party api in loop

i am using aws lambda and i am calling third party server using request library. this library on outside the loop but on loop its not hitting even i am not getting any error or result. and i also checked on server there is no hitting
below is my code with console
exports.handler = async (event) => {
try {
let transactionList = [];
// event.body is json form object with keys and values that we send
userBrokers.forEach(async (brokers) => {
const userStocks = 50;
const qty = (qtyPercentage * userStocks) / 100;
console.log("function before api call")
request.post({
headers: {
'content-type': 'application/x-www-form-urlencoded',
"Apca-Api-Key-Id": brokers.api_key,
"Apca-Api-Secret-Key": brokers.secret_key
},
url: 'https://paper-api.alpaca.markets/v2/orders',
json: {
symbol,
qty,
side: orderType,
type: marketType,
time_in_force
}
}, function (error, response, body) {
if (error) {
console.log("api call error")
transactionList.push({
transactionSuccess: false,
reason: error,
userId: brokers.user_id,
documentId: brokers._id
})
}
else {
console.log("api response")
if (response.statusCode == 200) {
transactionList.push({
brokerOrderId: body.id,
symbol: body.symbol,
orderType: body.order_type,
marketType: body.side,
transactionSuccess: true,
userId: brokers.user_id,
documentId: brokers._id
})
}
else {
transactionList.push({
transactionSuccess: false,
reason: body.message,
userId: brokers.user_id,
documentId: brokers._id
})
}
}
});
})
console.log("function before response")
return {
statusCode: 200,
body: JSON.stringify(transactionList),
};
} catch (error) {
console.log("function catch block")
return {
statusCode: 200,
body: JSON.stringify(error.message),
};
}};
and i get below console.
function before api call
function before response
and response from lambda
status: 200 and message: []
The problem is that you're trying to execute an async method in a forEach but you have no way of enforcing Lambda to wait for the loop to finish. You should switch your forEach to a map and await all the promises:
Bad:
arr.forEach(async (val) => {})
Good:
const arrOfResults = await Promise.all(arr.map(async (val) => {}))

Resources