I'm building a messenger bot that queries an API once a day and sends the information contained there to users. it's hosted on Heroku and uses Node.js
I'm currently using this to query the API:
var request = require('request');
//url for classes JSON
var url = 'https://example.api';
//get JSON, parse it and store it in jsonstorage variable
request(url, (error, response, body)=> {
if (!error && response.statusCode === 200) {
jsonstorage = JSON.parse(body)
console.log("Got a response")
} else {
console.log("Got an error: ", error, ", status code: ", response.statusCode)
}
})
The problem with this is that it doesn't refresh the API query ever, so the values returned are always the same. If I try and put it within the functions that send the data once a day though, it claims the jsonstorage variable is 'undefined'.
How can I refresh the query regularly?
Thanks!
Found an answer to this myself - the issue I was running into was that request is asynchronous, so I needed to wait for request to receive a result before running the rest of the script.
Related
I want to make a GET request to a web site using the Amazon Profile API. I am trying to do what is described in the last code chunk in this article: https://developer.amazon.com/blogs/post/Tx3CX1ETRZZ2NPC/Alexa-Account-Linking-5-Steps-to-Seamlessly-Link-Your-Alexa-Skill-with-Login-wit (very end of article) and it just does not happen. My callback function never seems to get called.
I have added the required context.succeed(), actually the latest version of that, and am still not getting results. I know the url is good, as I can take it and copy/paste into a browser and it returns an expected result.
Here is a SO answer on using the appropriate context function calls within the callback, which I have tried. Why is this HTTP request not working on AWS Lambda?
I am not using a VPC.
What am I doing wrong? I feel like a moron, as I have been researching this and trying solutions for 2 days. I log the full URL, and when I copy/paste that out of the log file, and put it in a browser window, I do get a valid result. Thanks for your help.
Here is the code:
function getUserProfileInfo(token, context) {
console.log("IN getUserProfileInfo");
var request = require('request');
var amznProfileURL = 'https://api.amazon.com/user/profile?access_token=';
amznProfileURL += token;
console.log("calling it");
console.log(amznProfileURL);
console.log("called it");
request(amznProfileURL, function(error, response, body) {
if (!error && response.statusCode == 200) {
var profile = JSON.parse(body);
console.log("IN getUserProfileInfo success");
console.log(profile);
context.callbackWaitsForEmptyEventLoop = false;
callback(null, 'Success message');
} else {
console.log("in getUserProfileInfo fail");
console.log(error);
context.callbackWaitsForEmptyEventLoop = false;
callback('Fail object', 'Failed result');
}
});
console.log("OUT getUserProfileInfo");
}
This is the logging output I get in CloudWatch:
2017-03-08T22:20:53.671Z 7e393297-044d-11e7-9422-39f5f7f812f6 IN getUserProfileInfo
2017-03-08T22:20:53.728Z 7e393297-044d-11e7-9422-39f5f7f812f6 OUT getUserProfileInfo
Problem might be that you are using var request = require('request'); which is external dependency and will require you to make a packaged lambda deployment for it to work. See this answer for relevant information.
AWS Node JS with Request
Another way is that you can use NodeJS module such as var http= require('http'); which is builtin module to make the requests. This way you can just make plain lambda script deployment.
Reference
http://docs.aws.amazon.com/lambda/latest/dg/nodejs-create-deployment-pkg.html
What is wrong with this code? I want to pull my hair out! I'm getting JSON from the Instagram API. console logging just body gives me the JSON, but when I do something like body.data or body.pagination, I get nothing! Help please and thank you.
var express = require("express"),
app = express(),
https = require("https"),
fs = require("fs"),
request = require("request");
request("https://api.instagram.com/v1/tags/nofilter/media/recent?access_token=xxxxx&scope=public_content&count=1", function(error, response, body) {
if (!error && response.statusCode == 200) {
console.log(body) // returns all the relevant JSON
console.log(body.data) // **returns undefined!!!!!**
}
}).pipe(fs.createWriteStream("./test.txt"))
body is literally what it says on the tin - the body of the HTTP response. In other words, it's a string - you need to run it through JSON.parse to actually access it as an object.
console.log(JSON.parse(body).data);
Obviously, if you were going to use this for real, you'd assign the parsed object to a variable rather than running it every time you access it.
I have a node.js/express webservice that I would like to use to verify Google token coming from a mobile app.
From this tutorial (https://developers.google.com/identity/sign-in/android/backend-auth) I learned that I have to make such a call:
https://www.googleapis.com/oauth2/v3/tokeninfo?id_token=XYZ123
So I came up with this in my code:
var request = require('request');
module.exports = function(app) {
app.get('/authenticate', function(req, res) {
request('https://www.googleapis.com/oauth2/v3/tokeninfo?id_token=XYZ123', function (error, response, body) {
if (!error && response.statusCode == 200) {
console.log(body)
}
})
});
};
Then, based on the response from google api, I would like to return true or false.
But it doesn't work. When I put "https://www.google.com" in the request, body is printed in the console, but the request is still being executed for some time.
What am I missing here? Is is the correct approach to the problem I described or should I do it in a completely different way?
You need to send a response to your incoming HTTP request.
Call res.send(...).
For more information, see the Express documentation.
There may already by an answer to this question but I was unable to find it.
Let's say I have a Node.js webpage doing somewhat time-consuming API calls and computations:
var request = require('request'),
Promise = require('es6-promise').Promise,
is_open = require('./is_open');
// Fetch the name of every eatery
var api_url = 'url of some api';
request(api_url, function (error, response, body) {
if (error) {
console.log(error);
} else if (!error && response.statusCode == 200) {
// Good to go!
var results = JSON.parse(body).events;
results.(function (result) {
// This line makes its own set of API calls
is_open(result
.then(function (output) {
console.log(output);
if (output == false) {
console.log('CLOSED\n');
} else {
console.log(output);
console.log();
}
})
.catch(console.error);
});
} else {
console.log('Returned an unknown error.');
console.log(error);
console.log(response);
console.log(body);
}
});
(I haven't yet created an actual web server, I'm just running the app locally through the command line.)
I want the web server to serve a loading page first to every user. Then, once the API calls are complete and the data is ready, it should send that data in a new webpage to the same user.
The reason I think there's an issue is because in order to serve a webpage, you must end with:
res.end();
Therefore ending the connection to that specific user.
Thanks for the help!
You must conceptually separate static content from dynamic content (later you will serve static with nginx or apache leaving only dynamic to node)
The best solution to your "problem" is to make the first webpage ask the data via AJAX once loaded. Ideally, your node app will return JSON to an ajax query from the first page, and js on the page will format the result creating DOM nodes.
I am trying to build a simple node service that
Handles a GET request from a web client
Parses the params submitted
Uses those params to query another REST service asynchronously
Returns the REST service results back to the original GET request.
I'm just getting started with asynchronous programming in node, in general I'm struggling to understand how to preserve scope between asynchronous calls.
Basically - how do I send the JSON service 'result' back to the original GET request via the 'req'?
I'm using Express and Request, the route handler looks like:
exports.list = function(req, res){
var params = req.query;
var queryParam= params.queryParm;
var restURL = "http://some-json-service.com?queryParam=" + queryParam;
var request = require('request');
request(restURL, function (error, response, body) {
if (!error && response.statusCode == 200) {
var result = JSON.parse(body);
// ? How do I send result back to the req?
}
})
You can literally return the response, so where you have your comment you will do:
request(restURL, function (error, response, body) {
if (!error && response.statusCode == 200) {
var result = JSON.parse(body);
res(result)
}
})
the problem with this approach is that your client request will be pending a response from the second service which is fine if it has to be done. Just be aware of the delay that you might be causing.
Also make sure in case of an error you also return a response.
This seems simple enough, so let me know if I didn't fully understand your question.
Cheers.
Vitor.