Page reloads on completion of AJAX request using NodeJS - javascript

I am trying to use a get request to run a python script and return a result using AJAX, Nodejs (using express) and Python-Shell (which runs a server side python script). I'm wanting this result to be returned into a div on my page.
The code does return a result from the python script back to into the web page (it flashes up for a second in the div), but then almost immediately, the page reloads.
My client side JS Function (which is triggered through a button onclick event)
function getResult() {
xmlhttp = new XMLHttpRequest()
ResultCoords = encodeURI('oLat=' + document.getElementById('originLat').innerHTML + '&oLng=' + document.getElementById('originLng').innerHTML + '&dLat=' + document.getElementById('destLat').innerHTML + '&dLng=' + document.getElementById('destLng').innerHTML);
xmlhttp.open("GET", "http://localhost:3000/run?" + ResultCoords, false);
xmlhttp.onreadystatechange = function () {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
string = xmlhttp.responseText;
document.getElementById('result').innerHTML = string
}
}
xmlhttp.send(ResultCoords)
}
My server side script
router.get('/run?*', (req, res) => {
let options = {
mode: 'text',
pythonPath: 'my python path',
pythonOptions: ['-u'],
scriptPath: 'my script path',
args: [req.query.oLat, req.query.oLng, req.query.dLat, req.query.dLng]
};
PythonShell.run('pythonScript.py', options, function (err, results) {
if (err) throw err;
console.log(results);
const data = results;
return res.send(data)
});
});
I'm still very much a beginner with express, AJAX etc. so i'm open to any suggestions on improving the code if this isn't the right way to be doing these sort of things etc.
Thanks!

Related

GET call, get query params from callback url

I am making a GET call with the following URL
https://auth.ebay.com/oauth2/authorize?client_id=CLIENT_ID&response_type=code&redirect_uri=REDIRECT_URI&scope=https://api.ebay.com/oauth/api_scope
This URL will redirect me to a "success.php" website from my server. With that redirection, it adds in params to the URL. For example: https://www.example.com/success.php?code=12345.
I need to get that code param from this redirection. How can I do that?
I tried to do a basic .get() call, but it doesnt seem to work..
https.get(url, (resp) => {
let data = '';
// A chunk of data has been received.
resp.on('data', (chunk) => {
data += chunk;
});
// The whole response has been received. Print out the result.
resp.on('end', () => {
console.log(JSON.parse(data).explanation);
});
}).on("error", (err) => {
console.log("Error: " + err.message);
});
I have tried other ways that I thought would work from research on here, like waiting for the redirect, etc. Nothing seems to work.
It is a query param ( seems to me you are working with an oAuth flow, reading about how these flows work would also help you work out an approach to this)
So I would capture it the following way
app.get('/callback', function (req, res) {
var code = req.query.code || null;
console.log(code);
}
where /callback is the URL you are redirected to and where you can capture the code to request the authorization token
Based on the code you already have it seems you might want the following.
var https = require('https');
var url = 'https://auth.ebay.com/oauth2/authorize?client_id=CLIENT_ID&response_type=code&redirect_uri=REDIRECT_URI&scope=https://api.ebay.com/oauth/api_scope';
https.get(url, (resp) => {
var location = new URL(resp.headers.location);
var code = location.searchParams.get('code');
console.log(code);
}).on("error", (err) => {
console.log("Error: " + err.message);
});
My answer assumes you are writing the code that is making the request while #Jordi Riera assumes you are writing code to process the request. Might you tell us which it is?

How to fix not getting text response from Post request

I'm new to using nodejs and javascript so I'm sorry if I'm just doing something obviously wrong. I have a nodejs app I'm running and serves a html page. That html page can send Post requests using XMLHttpRequest. The request goes though and my node app calls the function that my request is meant to invoke. The problem is I want to get some data back from that request so I am trying to get that from the response to the request. The issue is I am getting an empty response and I do not know why.
Here is my request.
function SendCachedTriangulation(){
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
document.getElementById('responseLog').textContent = "sent triangulation: " + this.response;
}
};
xhttp.open("Post", "/sendCachedTriangulation");
xhttp.setRequestHeader("Content-type", "application/json");
var text = '{ "data" : ' + '{ "someData":"' + '1' + '" } }';
xhttp.send(text);
return false;
}
The result I get from this is response is empty. It does update the element I am trying to update but it just says "sent triangulation: ".
On the nodejs side this is my code.
router.post('/sendCachedTriangulation', (req, res, next) => {
client.SendCachedTriangulation(() => {
res.status(200)
;}, req.body
);
res.status(200).message = "sent triangulation";
res.send();
});
Which this seems to be calling my function to send cached triangulation properly i just don't get that "sent triangulation" message.
What do I need to change to display that message in my HTML page?
Actually I understood your snippet. I also understand that is complicated at first time with Node, because is everything Javascript. Let me explain: in your HTML, think the request is OK, but actually have, let's say, two files: HTML file, that performs the request, and the node HTTP server, that responds the request. So I mean something like:
// /server/app.js
router.post('/sendCachedTriagulation', (req, res, next) => {
res.status(200).send("sent triangulation")
})
// /client/index.html
client.SendCachedTriangulation(/* do stuff */)

Node.js Doesn't Recognize Ajax Request

I am trying to make a private page dedicated to an Ajax request. Here is the simple request.
window.onload = loaded;
function loaded(){
var xhr = new XMLHttpRequest();
xhr.open('GET', '/data_annotations', true);
xhr.onload = function(){
if(this.status == 200){
var data = xhr.responseText;
console.log(JSON.parse(data));
} else {
console.log("Rip");
}
}
xhr.send();
//httpreq.abort();
}
Here is the node.js that it's running off of:
...
app.get('/', function(req, res, next){
console.log("Connected Successfully.");
res.render('home');
});
app.get('/data_annotations', function(req, res, next){
if(req.xhr || req.headers.accept.indexOf('json') > -1) {
const mc = mongo.MongoClient;
const url = 'mongodb://localhost:27017/';
const dbName = 'practiceMDB';
console.log("Got Data Annotations.");
mc.connect(url, { useNewUrlParser: true }, (err, client) =>{
if(err){
console.log(err);
} else {
const db = client.db(dbName);
data = db.collection('DataAnnotations');
data.find({}).toArray(function(err, data){
res.send(data)
});
client.close();
}
});
} else {
res.redirect('/');
}
});
app.listen(port, function(){
console.log('Server Started on Port '+port);
});
I only want /data_annotaion to run if it's from the Ajax request. If a user types in /data_annotations in the url, it should redirect them to the home page. When I ran this I got these results:
Server Started on Port 3000
Connected Successfully.
Connected Successfully.
This is indicating (to me) that the ajax request isn't registering as an ajax request, and is registering as a normal request. Further, I am getting this error:
Uncaught SyntaxError: Unexpected token < in JSON at position 0
I believe it is due to the redirection. The Ajax request gets redirected, it takes the response of the home page and is unable to parse it (I believe this to be happening because it cannot parse HTML text or string text - don't quote me on that). How do I get Node JS to register my Ajax request?
PS: I looked at this answer to determine if a request is Ajax or not, but it always determines my requests as not Ajax: https://stackoverflow.com/a/28540611/6804700
First thing - In your client-side code you need to set the accept header, because that is what you are looking for in your server side code.
xhr.setRequestHeader("accept", "application/json");
Second you can use the following code to return the data as json in your server side code
res.json(data);
Another comment. It is bad practice to change the result type or redirect in an API. Your url is either returning JSON or redirecting to and HTML page which means the result is not consistent.

Saving API data to JSON file with NodeJS (or PHP)

Is there a way to save data from an API to a JSON file, with NodeJS using XMLHttpRequest?
The API data is supposed to be displayed on a website, but the API is increcibly slow, so to combat this I would save the data on the server and display the newest data on the website every 5 minutes.
The API is public, the link is http://lonobox.com/api/index.php?id=100002519 if that helps.
Any help is greatly appreciated.
Hey I do a similar thing with a node server that performs basic function on JSON data that I use at work. When it comes to saving the data I just POST it to the server.
But when it come to reading the data I use a XMLHttpRequest to do it, let me illustrate how it works which should give you a good start.
POST file to server.
function processFile(e) {
var file = e.target.result,results;
if (file && file.length) {
$.ajax({
type: "POST",
url: "http://localhost:8080/",
data: {
'data': file
}
}).done(function(msg) {
appendText("Data Saved: " + msg);
});
}
}
From here you can fetch the data with XMLHttpRequest like so...
function getFile(){
var rawFile = new XMLHttpRequest();
rawFile.open("GET", "filename.json", false);
rawFile.onreadystatechange = function ()
{
if(rawFile.readyState === 4)
{
if(rawFile.status === 200 || rawFile.status == 0)
{
var fileText = rawFile.responseText;
}
}
}
rawFile.send(null);
}
Server Code
app.post('/', function(req, res) {
var fileLoc = __dirname.split("\\").length > 1 ? __dirname + "\\public\\filename.json" : __dirname + "/public/filename.json";
fs.writeFile(fileLoc, req.body.data, function(err) {
if (err) {
res.send('Something when wrong: ' + err);
} else {
res.send('Saved!');
}
})
});
Server side requires FS and I use Express for routing.

What is the best way to determine Tomcat has started with node.js

I am building an application using node.js and that application communicates with a Tomcat server. While the tomcat server is launching, I am not sure if Tomcat is ready and has come up or not, for now I use CURL and WGET on Windows and Mac with a timeout of 2 seconds to keep checking if localhost:8080 has come up.
Is there a better way to do this without relying on CURL and WGET?
The suggested way is to create a heartbeat service on the tomcat application (I.E. a simple service that sends OK when it's up), and poll that every x seconds.
A heartbeat service is essential for monitoring while the application is running, and there are also times when the application isn't ready even though it's already listening on the port (because there is some heavy initialization going on).
There are other ways though, if you're on the same server, you can tail the catalina.out until you receive "server started" line.
You can setup your tomcat application to notify your server that it's up (though that means the tomcat needs to know the url for the node.js server), or alternatively setup some kind of message queue (like ApacheMq or such) that you can register when the tomcat is up, this will also allow push messages between the two services.
You could implement a httpWatcher (mimicking the contract of file watcher - fs.watch). It could poll an http endpoint (a status route or html file) and would fire a callback when a 200 is returned (or when a max runs has been reached). Something like this:
var request = require('request');
var watch = function(uri) {
var options;
var callback;
if ('object' == typeof arguments[1]) {
options = arguments[1];
callback = arguments[2];
} else {
options = {};
callback = arguments[1];
}
if (options.interval === undefined) options.interval = 2000;
if (options.maxRuns === undefined) options.maxRuns = 10;
var runCount = 0;
var intervalId = setInterval(function() {
runCount++;
if(runCount > options.maxRuns) {
clearInterval(intervalId);
callback(null, false);
}
request(uri, function (error, response, body) {
if (!error && response.statusCode == 200) {
clearInterval(intervalId);
callback(null, true);
}
});
}, options.interval);
}
Then use it like so:
watch('http://blah.asdfasdfasdfasdfasdfs.com/', function(err, isGood) {
if (!err) {
console.log(isGood);
}
});
Or pass in options...
watch('http://www.google.com/', {interval:1000,maxRuns:3},
function(err, isGood) {
if (!err) {
console.log(isGood);
}
});
Well, you can make requests from Node.JS app:
var http = require("http");
var options = {
host: "example.com",
port: 80,
path: "/foo.html"
};
http.get(options, function(resp){
var data = "";
resp.on("data", function(chunk){
data += chunk;
});
resp.on("end", function() {
console.log(data);
// do something with data
});
}).on("error", function(e){
// HANDLE ERRORS
console.log("Got error: " + e.message);
}).on("socket", function(socket) {
// ADD TIMEOUT
socket.setTimeout(2000);
socket.on("timeout", function() {
req.abort();
// or make the request one more time
});
});
Documentation:
http://nodejs.org/docs/v0.4.11/api/http.html#http.request

Categories

Resources