Trouble receiving Nodejs response from a Post request (not using express) - node.js

My server receives my post request just fine, but I get no response from the server (and nothing through my web inspector either). I've set up my headers for cross origin and everything. Here is my nodejs server code. Code in question is at the bottom.
http.createServer(function (request, response) {
if(request.url === '/action'){
//console.log("momma I made it");
let body = '';
request.on('data', chunk => {
body += chunk.toString();
});
request.on('end', () => {
var log = JSON.parse(JSON.stringify(parse(body)));
console.log(log);
if(log.accT == 'Admin') {
if(log.account == 'nUser'){
console.log("this is an new user");
randnum = random();
var sql = "INSERT INTO Admin (adminName, adminEmail, adminPassword, adminID) VALUES ('" +log.username+ "', '" +log.email+ "', '" +log.password+ "', '" +randnum+ "')"
con.query(sql, function (err, result) {
if (err) throw err;
response.end('new user created, changed response remotely')
});
}
if(log.account == 'eUser'){
console.log("this is an existing user");
var sql = "SELECT adminName,adminPassword FROM Admin WHERE adminName = '"+log.username+"'";
con.query(sql, function (err, result, fields) {
if (err) throw err;
//var pass = parse(result);
if(result.length != 0 && result[0].adminPassword === log.password) response.end('youre in big guy')
else response.end('wrong username or password');
});
}
}
if(log.accT == 'Sponsor') {
if(log.account == 'nUser'){
console.log("this is an new user");
randnum = random();
var sql = "INSERT INTO Sponsor (adminEmail,sponsorEmail, sponsorName, sponsorPassword, sponsorID) VALUES ('" +log.authEmail+ "','" +log.email+ "', '" +log.username+ "', '" +log.password+ "', '" +randnum+ "')"
con.query(sql, function (err, result) {
if (err) throw err;
response.end('new user created, changed response remotely')
});
}
if(log.account == 'eUser'){
console.log("this is an existing user");
var sql = "SELECT sponsorName,sponsorPassword FROM Sponsor WHERE sponsorName = '"+log.username+"'";
con.query(sql, function (err, result, fields) {
if (err) throw err;
//var pass = parse(result);
if(result.length != 0 && result[0].sponsorPassword === log.password) response.end('youre in big guy')
else response.end('wrong username or password');
});
}
}
if(log.accT == 'Driver') {
if(log.account == 'nUser'){
console.log("this is an new user");
randnum = random();
var sql = "INSERT INTO Driver (sponsorEmail, driverName, driverEmail, driverPassword, driverID) VALUES ('" +log.authEmail+ "','" +log.username+ "','" +log.email+ "', '" +log.password+ "', '" +randnum+ "')"
con.query(sql, function (err, result) {
if (err) throw err;
response.end('new user created, changed response remotely')
});
}
if(log.account == 'eUser'){
console.log("this is an existing user");
var sql = "SELECT driverName,driverPassword FROM Driver WHERE driverName = '"+log.username+"'";
con.query(sql, function (err, result, fields) {
if (err) throw err;
//var pass = parse(result);
if(result.length != 0 && result[0].driverPassword === log.password) response.end('youre in big guy')
else response.end('wrong username or password buckaroo');
});
}
}
if(log.action == 'update'){
//response.write('hello');
}
//response.end('ok');
});
//response.writeHead(200)
//fs.createReadStream('server2.html').pipe(response) // do NOT use fs's sync methods ANYWHERE on production (e.g readFileSync)
}
if(request.url === '/myaction'){
response.writeHead(200)
fs.createReadStream('SignUp.html').pipe(response) // do NOT use fs's sync methods ANYWHERE on production (e.g readFileSync)
}
if(request.url === '/myaction2'){
response.writeHead(200)
fs.createReadStream('SignIn.html').pipe(response) // do NOT use fs's sync methods ANYWHERE on production (e.g readFileSync)
}
if(request.url === '/?action=update'){
//response.write('hello Isaac');
}
if (request.method == 'POST') {
console.log("POST");
var body = '';
request.on('data', function (data) {
body += data;
console.log("Partial body: " + body);
});
request.on('end', function () {
console.log("Body: " + body);
});
response.setHeader('Access-Control-Allow-Origin', '*');
response.setHeader('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
response.setHeader('Access-Control-Allow-Headers', 'Content-Type');
response.writeHead(200, {'Content-Type': 'text/html'});
response.end('post received');
}
and here is my html receiving code
var xhttp = new XMLHttpRequest();
xhttp.open("POST", "url not posted because I have no security", true);
xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
console.log(this.responseText);
}
};
xhttp.send('action=update');
And my server receives the message just fine. Any help is greatly appreciated thank you!

Nodejs http doesn't have header method. You have to use setHeader method response.setHeader('Access-Control-Allow-Origin', '*');

I had a similar problem an earlier stage, when I tried to send a response to HTML just a plain text. it's doesn't send a response to HTML. so what I did that is i have stored value in variable and given response.end(variable_name); and that was worked fine...
please correct me if am wrong.

Related

Why does my function lose its return value? [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 3 years ago.
Good afternoon, I'm now learning nodeJS. Right now I have a problem with a function I devised and I can't seem to find the problem
var http = require('http');
var mysql = require('mysql');
var url = require('url');
http.createServer(function (req, res) {
if (req.url === '/favicon.ico') {
//res.writeHead(200, {'Content-Type': 'image/x-icon'} );
res.end();
//console.log('favicon requested');
return;
}
var con = mysql.createConnection({
host: "localhost",
user: "admin",
password: "admin",
database: "brandibDB"
});
res.writeHead(200, {'Content-Type': 'text/plain'});
var addr = url.parse(req.url, true);
var teste = addr.pathname.split('/');
var tester = getJson(teste,con);
console.log(tester);
//console.log(teste);
//res.write(teste[1] + teste[2]);
res.end();
}).listen(8080);
function getJson(teste,con){
var resultado = "";
con.connect(function(err){
if (err) throw err;
if(teste[1] == 'users'){
if(teste.length!=2){
var str = "SELECT * FROM tblUsers where id ="+ mysql.escape(teste[2]) + "";
con.query(str, function (err, result, fields) {
if (err) throw err;
resultado = JSON.stringify(result);
});
}
else{
var str = "SELECT * FROM tblUsers";
con.query(str, function (err, result, fields) {
if (err) throw err;
resultado = JSON.stringify(result);
});
}
}
});
con.end;
return resultado;
}
console.log('Isto deve ser uma consola');
right now I have data in a db and I'm testing accessing this server with url: "localhost:8080/users/1" or "localhost:8080/users/"
When I run the second link for example, it should go into the function getJson and return the right value(a json with all the user registries) but it just returns empty. I've tried putting console logs inside the function around the lines "resultado = Json..." and it displays the right value. The result is lost afterwards.
Any tips?
It's because your getJson function has returned before the asynchronous callback from the query has completed, therefore resultado is still an empty string.
Instead you could either provide a callback to getJson that gets called when the query returns, or better still, use promises. Something like this:
var tester = getJson(teste, con)
.then(result => {
console.log('the results were:', results)
})
.catch(err => {
console.log('Something went wrong', err);
});
and your function becomes something like:
function getJson(teste, con) {
return new Promise((resolve, reject) => {
con.connect(function (err) {
if (err) throw err;
if (teste[1] == 'users') {
if (teste.length != 2) {
var str = "SELECT * FROM tblUsers where id =" + mysql.escape(teste[2]) + "";
con.query(str, function (err, result, fields) {
if (err) return reject(err);
return resolve(JSON.stringify(result));
});
} else {
var str = "SELECT * FROM tblUsers";
con.query(str, function (err, result, fields) {
if (err) return reject(err);
return resolve(JSON.stringify(result));
});
}
}
});
})
}
I'd also recommend ditching var and using let and const, it's much easier to keep track of your variable scopes that way.

Using return value in another file in Node.js synchronously

I'm concatenating tweets from a defined user through a helper file and trying to retrieve it in my server.js but there the str value is still undefined (and this line gets executed first), then the console.log from my helper prints with the right value.
Output:
GET /login/twitter/callback 302 618.242 ms - 0
Concatenated Tweets in Server: undefined
Concatenated Tweets in Helper: Test Tweet 3 #TestTweet Test Tweet 2
Test Tweet 1
Can anyone help on what control flow I should use to call twitterHelper.getTweets functions to get the returned str in the server please? Thanks!
Server.js
app.get('/login/twitter/callback',
passport.authenticate('twitter', {failureRedirect: "/login"},
function(req, res) {
// auth success
async.waterfall ([
function(callback) {
callback(null, twitterHelper.getTweets(user));
},
function(str, callback) {
console.log("Concatenated Tweets in Server: " + str);
callback(null);
}
],
function(err) {
if(err)
console.log("Error: " + err);
}
);
}
)
);
Helper.js
var concatTweets = '';
var promise = new Promise(
function(resolve, reject) {
T.get('statuses/user_timeline', params, function( err, data, response) {
if(err)
reject(err);
else {
for (var i = 0; i < data.length ; i++)
concatTweets = concatTweets + " " + data[i].text;
resolve(concatTweets);
}
})
}
).then(
str => {
console.log("Concatenated Tweets in Helper: " + str);
return str;
}, err => {
console.log(err);
return err;
}
);
Instead of using this longway you can use this simple way by promise.
Helper.js
var concatTweets = '';
var getTweets = function(user){
var promise = new Promise(function(resolve, reject) {
T.get('statuses/user_timeline', params, function( err, data, response) {
if(err){
reject(err);
} else {
for (var i = 0; i < data.length ; i++)
concatTweets = concatTweets + " " + data[i].text;
console.log("Concatenated Tweets in Helper: " + concatTweets);
resolve(concatTweets);
}
})
});
return promise;
}
Server.js
app.get('/login/twitter/callback', passport.authenticate('twitter', {failureRedirect: "/login"},function(req, res) {
// auth success
twitterHelper.getTweets(user).then(str=>{
console.log("Concatenated Tweets in Server: " + str);
}).catch(err=>{
console.log("Error: " + err);
});
}));
I hope this will work for you.

How do I update json data in postgres sql in nodejs?

my data structure schema is like
users(
id serial primary key,
data json
);
I want to update data key.
I'm using node-postgres library and So far I have tried something like this:
pg.connect(process.env.DATABASE_URL, function(err, client, done) {
var queryString = "UPDATE users SET data =" + myNewJsonData + " WHERE id = " + userIdToEdit + ";";
client.query(queryString, function(err, result) {
done();
if (err) {
res.send("Failed to update user data ");
throw err;
} else {
res.send("Successfully updated user data!! ");
}
});
});
this is not working, I'm getting error invalid input syntax for type json
Can anyone help, Thanks.
So it was a syntax error, All I had to do stringfy json data and put that in 'quotes'
pg.connect(process.env.DATABASE_URL, function(err, client, done) {
var newJsonDataStringyfied = JSON.stringify(myNewJsonData)
var queryString = "UPDATE users SET data = '" + newJsonDataStringyfied + "' WHERE id = " + userIdToEdit + ";";
client.query(queryString, function(err, result) {
done();
if (err) {
res.send("Failed to update user data ");
throw err;
} else {
res.send("Successfully updated user data!! ");
}
});
});

Node.js Async | insert into postgresql database results from api

I am quite newbie with node.js. What i am trying to achieve is the following:
Connect to my postgresql database and get info of a place (id, coordinates).
call a weather api and get the info of that spot using the coordinates obtained in the previous step.
Insert the returned json in the database. I get 8 hourly objects, with the weather info every 3 hours (0,3,6,9,12,15,18,21). I need to iterate through this objects and the store them in 8 records in the database.
I wrote the following code:
app.get('/getapi', function(req, res){
var json_bbdd;
//------------ BBDD CONNECTION----------------
var pg = require('pg');
var conString = "postgres://postgres:postgres2#localhost/places";
var client = new pg.Client(conString);
client.connect(function(err) {
if(err) {
console.log('could not connect to postgres');
}
client.query('SELECT * from places where id=3276', function(err, result) {
if(err) {
console.log('error running query');
}
json_bbdd=result.rows[0];
var coords = JSON.parse(json_bbdd.json).coordinates;
var id = json_bbdd.id;
var input = {
query: coords[1] + ',' + coords[0] ,
format: 'JSON',
fx: '',
callback: 'MarineWeatherCallback'
};
var url = _PremiumApiBaseURL + "marine.ashx?q=" + input.query + "&format=" + input.format + "&fx=" + input.fx + "&key=" + _PremiumApiKey + "&tide=yes";
$.ajax({
type: 'GET',
url: url,
async: false,
contentType: "application/json",
dataType: 'jsonp',
success: function (json) {
var date= json.data.weather[0].date;
for (var i=0; i < 8; i++){
var hourly = json.data.weather[0].hourly[i];
var time= hourly.time;
client.query('INSERT into parte (id, date, time) VALUES($1, $2, $3)', [id, date, time],
function(err, result) {
if (err) {
console.log(err);
} else {
console.log('row inserted: ' + id + ' ' + time);
}
});
} // FOR
},
error: function (e) {
console.log(e.message);
}
});
client.end();
});
});
});
The steps 1 and 2 are performed perfectly. The third step, on the other hand, does nothing and it doesn't even throw an error.
I read in this post: node-postgres will not insert data, but doesn't throw errors either that using async module could help but i have no idea how to rewrite the code. I need some help.
Regards,
Aitor
I didn't test your snippet, I can only help you with things which looks bad to my eyes.
It is better not to use jQuery on node server. There is excellent library called request to do remote http requests.
You should better handle database errors because in your example your code will continue after DB error.
You are calling client.end() too early and at the time when you try to insert data to the database a connection is already closed. You have to move client.end() at the end of success and error functions and wait to all callbacks are done.
I think it is also better to use connection pool instead of Client.
You can possibly use JSON type in PostgreSQL to avoid serializing/deserializing JSON data in your code.
Here is revised example(untested). I didn't replace jQuery here, some minor tweaking included.
var pg = require('pg');
var conString = "postgres://postgres:postgres2#localhost/places";
app.get('/getapi', function(req, res, next){
var json_bbdd;
//------------ BBDD CONNECTION----------------
pg.connect(conString, function(err, client, done) {
if(err) {
// example how can you handle errors
console.error('could not connect to postgres');
return next(new Error('Database error'));
}
client.query('SELECT * from places where id=3276', function(err, result) {
if(err) {
console.error('error running query');
done();
return next(new Error('Database error'));
}
json_bbdd = result.rows[0];
var coords = JSON.parse(json_bbdd.json).coordinates;
var id = json_bbdd.id;
var input = {
query: coords[1] + ',' + coords[0] ,
format: 'JSON',
fx: '',
callback: 'MarineWeatherCallback'
};
var url = _PremiumApiBaseURL + "marine.ashx?q=" +
input.query + "&format=" + input.format +
"&fx=" + input.fx + "&key=" +
_PremiumApiKey + "&tide=yes";
$.ajax({
type: 'GET',
url: url,
async: false,
contentType: "application/json",
dataType: 'jsonp',
success: function (json) {
var date = json.data.weather[0].date;
var callbacks = 0;
for (var i=0; i < 8; i++) {
var hourly = json.data.weather[0].hourly[i];
var time= hourly.time;
client.query(
'INSERT into parte (id, date, time) VALUES($1, $2, $3)',
[id, date, time],
function(err, result) {
if (err) {
console.log(err);
} else {
console.log('row inserted: ' + id + ' ' + time);
}
callbacks++;
if (callbacks === 8) {
console.log('All callbacks done!');
done(); // done(); is rough equivalent of client.end();
}
});
} // FOR
},
error: function (e) {
console.error(e.message);
done(); // done(); is rough equivalent of client.end();
return next(new Error('Http error'));
}
});
});
});
});
Ok, now cam up with another problem...i was doubting of creating a new post but i think that maybe could have relation with the previous post.
The aim is to read from the database instead of one place 3 places and do the same process than before for each one.
The code is as follows (with the changes proposed by ivoszz):
app.get('/getapi', function(req, res, next){
//------------ BBDD CONNECTION----------------
pg.connect(conString, function(err, client, done) {
if(err) {
// example how can you handle errors
console.error('could not connect to postgres',err);
return next(new Error('Database error'));
}
client.query('SELECT * from places where id>3274 and id<3278', function(err, result) {
if(err) {
console.error('error running query',err);
done();
return next(new Error('Database error'));
}
var first_callback = 0;
for (var y=0; y<result.rows.length; y++) {
var coords = JSON.parse(result.rows[y].json).coordinates;
var id = result.rows[y].id;
var input = {
query: coords[1] + ',' + coords[0] ,
format: 'JSON',
fx: ''
};
var url = _PremiumApiBaseURL + "marine.ashx?q=" + input.query + "&format=" + input.format + "&fx=" + input.fx + "&key=" + _PremiumApiKey;
request(url, function(err, resp, body) {
body = JSON.parse(body);
if (!err && resp.statusCode == 200) {
var date = body.data.weather[0].date;
var callbacks = 0;
for (var i=0; i < 8; i++) {
var hourly = body.data.weather[0].hourly[i];
client.query(
'INSERT into parte (id, date, time) VALUES($1, $2, $3)',
[id, date, hourly.time],
function(err, result) {
if (err) {
console.log(err);
} else {
console.log('row inserted: ' + id + ' iteration ' + i);
}
callbacks++;
if (callbacks === 8) {
console.log('All callbacks done!from id '+id);
//done(); // done(); is rough equivalent of client.end();
//res.send("done");
}
});
} // FOR
}
else { // if the API http request throws an error
console.error(err);
done(); // done(); is rough equivalent of client.end();
return next(new Error('Http API error'));
}
}); // REQUEST API URL
first_callback++;
if (first_callback === result.rows.length-1) {
console.log('All global callbacks done!');
done(); // done(); is rough equivalent of client.end();
res.send("done");
}}
}); // SELECT from pg
}); // CONNECT to pg
}); // app.get
I don't know why it tries to insert the id=3277 three times instead of inserting id=3275, id=3276 and then id=3277... what it does instead is: it inserts the first 8 records ok the first time (id=3277), but then it throws an error saying that the records are already inserted (primary key=id,date,time) with id 3277...
It seems that first does the 3 iterations of the first FOR and then does the 3 iteration of the second FOR but with the info of the last iteration(place). I can't understand it very well...

Event-driven asynchronous callbacks in Node js

Is there a way to block the asynchronous callback property of node.js?
Please Advice...
For example,
var express = require('express');
var app = express();
var MongoClient = require('mongodb').MongoClient,
format = require('util').format;
var cors = require('cors');
app.get('/gantt', cors(), function (request, response) {
MongoClient.connect('mongodb://127.0.0.1:27017/test', function (err, db) {
if (err) throw err;
var collection = db.collection('ganttdata');
collection.find({}, {
"_id": 0
}).toArray(function (err, results) {
var jsonString = JSON.stringify(results);
response.setHeader('Content-Type', 'text/plain');
response.send('{\"data\":' + jsonString + '}');
});
});
});
app.listen(3000);
console.log('Listening on port 3000...');
Inspite the Node.js prints the console statement first,i want app.get() to be executed.
My scenario is same as that of the above one.
This is my scenario
var ganttresult = new Array();
app.get('/get', cors(), function (request, response) {
console.log('hello');
connection.query("SELECT distinct id FROM ganttdata", function (err, rows) {
if (err) {
console.log('error in fetching ' + err);
} else {
var all_id = rows;
for (var j = 0; j < all_id.length; j++) {
console.log('hello1');
connection.query("SELECT id,tailName FROM ganttdata where id= '" + all_id[j].id + "'", function (err, rows) {
if (err) {
console.log('error in fetching ' + err);
} else {
var jsonString1 = rows;
var set_id = jsonString1[0].id;
connection.query("SELECT item_id,name,start,end FROM ganttdata where id= '" + set_id + "'", function (err, rows) {
if (err) {
console.log('error in fetching ' + err);
} else {
var jsonString2 = rows;
var gantt1 = new Object();
gantt1.id = jsonString1[0].id;
gantt1.tailName = jsonString1[0].tailName;
var series = new Array();
for (var i = 0; i < jsonString2.length; i++) {
var gantt2 = new Object();
gantt2.item = jsonString2[i];
series.push(gantt2);
gantt1.series = series;
}
//console.log(gantt1);
console.log('hi');
ganttresult.push(gantt1);
console.log(ganttresult);
}
});
}
});
}
var result = JSON.stringify(ganttresult);
console.log(result);
response.send('{\"data\":' + result + '}');
response.end();
}
});
});
When I run this code,
I get an empty resultset and when I re-run I get the result.
I guess it is due to asynchronous callback nature of node js.
Please advice...
Thanks
I have tried async.waterfall method as given below
app.get('/get',cors(), function(request,response) {
async.waterfall([
function(result) {
connection.query("SELECT id FROM Gantt",function(err, rows) {
if (err) {
console.log('error in fetching ' + err);
}
else{
var all_id=rows;
for(var j=0;j<all_id.length;j++){
connection.query("SELECT id,tailName FROM Gantt where id= '"+all_id[j].id+"'",function(err, rows) {
if (err) {
console.log('error in fetching ' + err);
}
else{
var jsonString1=rows;
var set_id=jsonString1[0].id;
connection.query("SELECT item_id,name,start,end FROM GanttFlight where id= '"+set_id+"'",function(err, rows) {
if (err) {
console.log('error in fetching ' + err);
}
else{
var jsonString2=rows;
var gantt1=new Object();
gantt1.id=jsonString1[0].id;
gantt1.name=jsonString1[0].tailName;
var series = new Array();
series=[];
for(var i=0;i<jsonString2.length;i++){
var gantt2=new Object();
gantt2.item=jsonString2[i];
series.push(gantt2);
gantt1.series=series;
}
ganttresult.push(gantt1);
}
});
}
});
}
var result= JSON.stringify(ganttresult);
console.log(ganttresult);
response.send(ganttresult);
ganttresult=[];
//response.send('{\"data\":'+result+'}');
response.end();
}
});
}
], function(err, status) {
console.log(status);
});
});
app.listen(3000);
console.log('Listening on port 3000...');
i am getting empty result first and when refresh the browser,i get the required result
Please Advice

Resources