Facebook Graph API in aws lambda failing - javascript

I'm having trouble getting this to run. It runs just fine if I make the same FB.api call directly from the front end or through "serverless invoke local" and it console.logs my response. But when I deploy this function to a lambda and try to call it, I hit the "console.log("TRY"), get a 502 error, and then nothing after that. No response from the FB.api call, no errors, no info at all. I've tried upping the timeout as well and have brought it up to as much as 15 seconds and still getting no response. Anyone else run into this? Thanks!
export async function main(event, context, callback){
var FB = require('fb');
const data = JSON.parse(event.body)
console.log("DATA: ", data)
const requestString = data.Id + '/accounts'
console.log(requestString)
console.log("ACCESS TOKEN: ", data.accessToken)
const pages = []
try{
console.log("TRY")
await FB.api(requestString, 'get', { access_token: data.accessToken }, function(response){
console.log("RESPONSE: ", response)
callback(null, success(response));
})
}
catch (e){
console.log("CATCH")
console.log(e)
callback(null, failure({ status: false }));
}
}

Related

How to perform a POST request using background task for React Native apps using expo

I am trying to log my GPS coordinates in a React-Native expo application.
The background task runs successfully and consoles log the coordinates.
Now I want to send them to my server.
For example a post request to /api/mylocation?lon=123&lat=345
I tried a regular fetch method but I get a timeout error.
regular meaning fetch(url,{ method:'POST' etc}) (I know how to perform a basic fetch)
How can I solve this? I suspect it has to do with async and all that.
const LOCATION_TRACKING = 'location-tracking';
const startLocationTracking = async () => {
console.log('startLocationTracking');
await Location.startLocationUpdatesAsync(LOCATION_TRACKING, {
accuracy: Location.Accuracy.Highest,
timeInterval: 10000,
distanceInterval: 0,
});
const hasStarted = await Location.hasStartedLocationUpdatesAsync(
LOCATION_TRACKING
);
console.log('tracking started?', hasStarted);
};
TaskManager.defineTask(LOCATION_TRACKING, async ({ data, error }) => {
console.log('running task:', data, error);
// send_driver_location()
if (error) {
console.log('LOCATION_TRACKING task ERROR:', error);
return;
}
if (data) {
const { locations } = data;
let lat = locations[0].coords.latitude;
let long = locations[0].coords.longitude;
console.log(
`${new Date(Date.now()).toLocaleString()}: ${lat},${long}`
);
// add a fetch method here?
// fetch(url, {...}
}
});
Obviously, this will be helpful when I want to fetch tokens from my server for authentication purposes also.

How can I send messages to my queue and a post request?

I have a function that posts data to the database. It works fine but I would also like to use the same function to send a message to trigger another function.
I have tried to simultaneouslysend the message and make the post request but at this moment only the post request works
Here is what my code looks like
const params = {
"TableName": "sites",
"Item": {
userId: event.requestContext.identity.cognitoIdentityId,
siteId: siteIdFinal,
...data,
createdAt: Date.now()
}
};
const messageParams = {
MessageBody: 'Waddup fam',
QueueUrl: ' https://sqs.eu-west-1.amazonaws.com/106845550704/MyQueue'
};
try {
await dynamoDbLib.call("put", params);
sqs.sendMessage(messageParams, (err, data) => {
if (err) {
console.log("Error: "+err);
} else {
console.log("Success: "+data.MessageId);
}
});
return success(params.Item);
} catch (e) {
console.log(e);
return failure({ status: false });
}
I am not getting any error I am just getting returned back the data that has been posted. I thought i should receive the message Id of the message I sent but I am not getting that. When ever I look at the cloudwatch logs, the message isnt sent
Your async function returns params.Item before sendMessage executes a callback.
Use a promise to make sure that both methods finish properly
await sqs.sendMessage(messageParams).promise()
.then(function(data) {
console.log("Success: "+data.MessageId);
}).catch(function(err) {
console.log("Error: "+err);
});
More on aws-sdk and promises:
https://aws.amazon.com/blogs/developer/support-for-promises-in-the-sdk/

Firebase Cloud Function never failing on 404 API call

I have a function running on the creation of a document.
When I send this information to an external API Firebase returns on 'ok' message before the API call is complete.
const functions = require('firebase-functions');
const request = require('request');
const admin = require('firebase-admin');
const rp = require('request-promise');
const port = '****';
const ip = '***.***.***.***';
admin.initializeApp(functions.config().firebase);
exports.sendUser = functions.firestore
.document('user/{userId}')
.onCreate((snap, context) => {
const data = snap.data();
const options = {
method: 'POST',
uri: 'http://' + ip + ':' + port + '/user',
body: data,
json: true,
};
rp(options)
.then(function (parsedBody) {
console.log('TEN ', parsedBody);
return parsedBody;
})
.catch(function (err) {
console.log('ERR ', err);
return err;
});
});
As you can see from my function it is not doing anything special apart from sending the data to an external source.
The API look like the following:-
app.post('/user', function (req, res) {
fs.exists(path, function(exists) {
if (exists === true) {
console.log('Currently Printing Different User Info');
fs.unlinkSync(path);
res.status(404).json({errorCode: 404, errorMessage: 'Currently Printing Different User.'});
return;
} else {
fs.writeFile(path, '', () => { console.log('File Created'); });
fs.unlinkSync(path);
res.status(200).json({statusCode: 200, statusMessage: 'Here we go'});
return;
}
});
})
How can I get Firebase to recognise the returned 404 as a failed call, and also wait until the call is complete before returning ok or failed.
The API is behaving correctly with Postman but not when data is posted via Firebase.
Has anyone encountered this before, or can anybody see what I am doing wrong?
The data is being parse over to the serve but only once Firebase has returned with 'ok' even if I purposely trigger a fail.
I need this in place to be able to use the Firebase Cloud Function retry function.
Images can be seen # https://imgur.com/a/1qYxrci
The Cloud Function returns the result before the call is complete because you don't return the Promise returned by the request-promise call.
Changing your code as follows should do the trick (at least for this problem):
exports.sendUser = functions.firestore
.document('user/{userId}')
.onCreate((snap, context) => {
const data = snap.data();
const options = {
method: 'POST',
uri: 'http://' + ip + ':' + port + '/user',
body: data,
json: true,
};
return rp(options) // <-- See the change here
.then(function (parsedBody) {
console.log('TEN ', parsedBody);
return parsedBody;
})
.catch(function (err) {
console.log('ERR ', err);
return err;
});
});
I would suggest you watch the official Video Series (https://firebase.google.com/docs/functions/video-series/) which explain very well this point about returning Promises for background functions (in particular the ones titled "Learn JavaScript Promises").

Azure Table Storage return query results

I'm trying to create an Azure Function that will take take in parameter(s) and return a value stored in an Azure Table. I believe the issue I'm having has more to do with javascript than it does with the Azure Table SDK.
How are you supposed to return the value from the query via http response? I have attached a copy of the code and it should explain where I'm confused. My main confusion is due to the fact that I'm able to call context.log() but unable to call context.res{} from the function in the query method.
I know that scope has something to do with it but I am not an expert when it comes to javascript and nested functions. Some guidance or example would be appreciated
var azure = require('azure-storage');
module.exports = function (context, req) {
context.log('Some Function');
var hostUri = 'https://*******.table.core.windows.net'
var sasToken = 'abc123'
if (req.query.value) {
var tableService = azure.createTableServiceWithSas(hostUri, sasToken)
var nothing = tableService.retrieveEntity('Table', 'Partition', 'Row', function(error, result, response) {
if (!error) {
context.log('I am able to send data to the logs here')
context.res = {
status: 200,
body: "This is what I am tring to return -> " + JSON.stringify(result)
};
}
})
context.res = {
status: 200,
body: "I'm able to get a response here"
};
}
else {
context.res = {
status: 400,
body: "Somthing went wrong..."
};
}
context.done();
};
Solution first:
if (req.query.value) {
var tableService = azure.createTableServiceWithSas(hostUri, sasToken)
tableService.retrieveEntity('Table', 'Partition', 'Row', function(error, result, response) {
if (!error) {
context.log('I am able to send data to the logs here')
context.res = {
status: 200,
body: "This is what I am tring to return -> " + JSON.stringify(result)
};
}
else{
context.res = {
status: 400,
body: error
};
}
context.done();
})
}
else {
context.res = {
status: 400,
body: "Value is empty"
};
context.done();
}
Explanation:
Let's mark the context.res in order as c1 and c2 to avoid redundant.
You are caught by callback function. The callback function(error, result, response){} is not executed until entity is retrieved from remote sever(or error happens). This operation may take some time, the program continues executing while waiting for it to complete, this pattern is called asynchronous.
So your code snippet c1 in callback is not executed immediately but instead c2 is. Then context.done(); runs before the entity retrieved(you see response message I'm able to get a response here), callback is hence never called.
Code relying on result of callback should be included in callback, so that it can execute exactly after callback is finished. Put context.done(); in both callback and else segment to assure it won't run in advance.
Also one blog about asynchronous-javascript for you to refer.

Done function never called after $.ajax

I'm a bit new to all this (including Javascript callbacks and ES6). I'm using NodeJS + Express + MongoDB.
I'm calling an Ajax function to update an item and the success Ajax call is never done.
Here is my Ajax call (called from React)
editBug : function(bug){
console.log('about to edit bug with these values',bug);
$.ajax({
url:'/api/bugs',
method: 'PUT',
data:bug
})
.done((jqxhr) => {
console.log('succcess while editing the bug');
this.setState({successVisible : true});
})
.fail((jqxhr) => {
console.log('error : ' + jqxhr);
})
},
Here is my API function:
app.put('/api/bugs',function(req,res){
//console.log('req',req);
console.log('query string : ',req.query);
console.log('query params : ',req.params);
console.log('query body: ',req.body);
let id = new ObjectID(req.body._id);
req.body._id = new ObjectID(req.body._id);
db.collection('bugs').replaceOne(
{_id:id},
req.body,
function(err,result){
assert.equal(err,null);
console.log('Successfull replace!');
res.status(200);
}
);
});
The Successfull replace! log is correctly shown on the server side.
The about to edit bug with these values is correctly shown on the front side. But the succcess while editing the bug log is not shown on front end and it seems .done call is never executed.
The problem is that you are not sending any response back to the browser on node side. Try the following snippet and you should be good to go
Also, I'd like to point out that you should handle the errors. While updating the bugs if something goes wrong, the best practice would be to inform the browser with the 500 status code indicating that the intended action failed. I've added this aspect in the snipped below
app.put('/api/bugs', function(req, res) {
//console.log('req',req);
console.log('query string : ', req.query);
console.log('query params : ', req.params);
console.log('query body: ', req.body);
let id = new ObjectID(req.body._id);
req.body._id = new ObjectID(req.body._id);
db.collection('bugs').replaceOne({
_id: id
},
req.body,
function(err, result) {
if (err) {
console.log('Failed replace');
res.status(500).end(); // <- We set the response status code and end the request
} else {
assert.equal(err, null);
console.log('Successfull replace!');
res.status(200).end(); // <- We set the response status code and end the request
}
}
);
});
Don't you need to end your response object on the Node.js side?
Try adding res.end(); or any kind of response to your response object.
Also, you can use chrome's (or any other browser's) network tab to actually see how your AJAX requests end up, to see if they hang or finish.

Categories

Resources