res.json() won't work when trying to display data - express

I am using Nodejs, express, and postgresql to create a rest api. This is my first time doing any of this so I apologize for the noobness. I have been just testing this out and seemed to be about to get retrieve information from a database locally but when I try to send the data with res.json() nothing shows up. Here is the code I have so far.
var express = require('express');
var client = new pg.Client({user: 'xxx', password: 'xxx', database: 'xxx', host: 'xxx'});
var app = express();
app.get('/test1', function(req,res){
var name;
client.connect(function(err){
if(err){
return console.error('could not connect to postgres', err);
}
client.query("select classname from class", function(err, result){
if(err){
return console.error('error running query', err);
}
name = result.rows[0].classname;
console.log(name);
client.end();
});
});
res.send(name);
});
I used the console log and it printed out what I needed but for some strange reason it won't send. Thanks for the help! Also, if you see anything else wrong don't be afraid to say it. Thanks!

It's an asynchronous function so it would go like this:
var express = require('express');
var client = new pg.Client({
user: 'xxx',
password: 'xxx',
database: 'xxx',
host: 'xxx'
});
var app = express();
app.get('/test1', function(req, res) {
var name;
client.connect(function(err) {
if (err) {
return console.error('could not connect to postgres', err);
}
client.query("select classname from class", function(err, result) {
if (err) {
return console.error('error running query', err);
}
name = result.rows[0].classname;
console.log(name);
client.end();
res.send(name);
});
});
});
What is happening in your code is that you are sending before the query is done executing. You can see it on the console because your log statement is correctly executing after the query.
Also you should take care of your errors as well - so instead of returning do another res.send (or res.json) with some error mesg.

Related

Handling POST and GET requests in Express

First time using express here.
I have the following in my app.js file:
const express = require("express");
const mysql = require("mysql");
const app = express();
const PORT = process.env.PORT || 8000;
const connection = mysql.createConnection({
host: "localhost",
user: "admin",
password: "password",
database: "mydb",
});
app.use(express.static(__dirname + "/express"));
app.use(express.urlencoded()); // have also tried with "extended: true" and "extended: false"
app.use(express.json());
// GET
app.get("/getAllUserActivity", (req, res) => {
const order = req.query.order || "id";
const page = req.query.page || 0;
const limit = req.query.limit || 100;
connection.connect((err) => {
if (err) throw err;
connection.query(
"SELECT id, username, counter FROM users ORDER BY ? LIMIT ?,?",
[order, page, limit],
(err, results, fields) => {
if (err) throw err;
res.send(results);
}
);
});
});
// POST
app.post("/updateUserActivity", (req, res) => {
const userId = req.body.userId;
const username = req.body.username;
const counter = req.body.counter;
connection.connect((err) => {
if (err) throw err;
connection.query(
"INSERT INTO users (id, username, counter) VALUES (?, ?) ON DUPLICATE KEY UPDATE counter = counter + ?",
[userId, username, counter],
(err, results, fields) => {
if (err) throw err;
res.send(results);
}
);
});
});
My POST requests have the header "Content-Type": "application/x-www-form-urlencoded".
The issue I am facing is two-fold:
The GET request fails every other time. First time it returns the expected data, but the second time I get Incomplete response received from application - repeat.
I can only get either the POST or the GET request to work - depending on how I setup the middleware. How can I have both GET and POST here?
Old php user here, trying to figure out Express. Thanks!
Replace all if (err) throw err; with sending an actual error response back to the client. You MUST always send some form of response to every incoming request. It is a shame that many pieces of demo code show that if (err) throw err; because inside an asynchronous callback, that is pretty much never the correct code.
Then (though I don't know the specific details of your database) you will need to release/close your database connections after using them so they do not leak. Or, you can use a pooled set of connections where they are automatically returned to the pool after doing a query.

Azure SQL database is not updating with data

I have created a nodejs azure web app and it is running perfectly fine,
Now I want to get my post data to azure MS SQL DB, I have created a code for that, however sql db is not updating with POST data, can anyone help me with this.
var express = require('express');
var bodyParser = require('body-parser');
var sql = require('mssql');
var port = 8080;
var app = express();`enter code here`
var path = require('path');
//CORS Middleware
app.use(function(req,res,next){
res.header("Access-Control-Allow-Origin","*");
res.header("Access-Control-Allow-Methods","GET,HEAD,POST,PUT,OPTIONS");
res.header("Access-Control-Allow-Headers","Origin,X-Requested-With,contentType,Content-Type,Accept,Authorization");
next();
});
app.set('view engine', 'ejs');
app.set('views', path.join(__dirname, 'views'));
app.use(bodyParser());
app.use(bodyParser.urlencoded({extended: false}));
app.use(express.static(path.join(__dirname, 'public')));
//setup database connection
var dbconfig = {
user:"username",
password:"password",
server : "server_name",
database: "db_name"
};
// ConnectionPool
//connect to the database
var executeQuery = function(res,query){
sql.connect(dbconfig,function(err){
if(err){
console.log("there is a database connection error -> "+err);
res.send(err);
}
else{
// create request object
var request = new sql.Request();
// query to the database
request.query(query,function(err,result){
if(err){
console.log("error while querying database -> "+err);
res.send(err);
}
else{
res.send(result);
sql.close();
}
});
}
});
}
app.get('/', function(req, res){
res.render('index', {
title: 'Hello World',
showTitle:true,
people: ['John', 'Steve', 'Jose']
});
});
app.get('/index', function(req, res){
res.render('index');
});
app.get('/contact', function(req, res){
res.render('contact');
});
app.post('/my_user', function(req, res){
//return res.send(req.body);
console.log(req.body.email + ' and ' + req.body.mobile);
var parameters = [
{ name: 'email', sqltype: sql.NVarChar, value: req.body.email},
{ name: 'mobile', sqltype: sql.NInt, value: req.body.mobile},
{ name: 'msg', sqltype: sql.NVarChar, value: req.body.msg},
];
var query = "insert into forMyCV values(#email, #mobile, #msg);";
executeQuery (res, query, parameters);
return res.redirect('/');
});
app.listen(port);
console.log('Server started on port '+port);
can anyone help me with this explain this to me. why this is happening
I'm afraid there are two issues in your code after I had test it.
According to the tab Connection strings of your Azure SQL Database on Azure portal as the figure below, there is a required parameter encrypt=true in the connection string like for JDBC and others, too.
So the correct config for Azure SQL Database using mssql should be as below.
const config = {
user: '<your username>#<your sql server name>',
password: '<your password>',
server: '<your sql server name>.database.windows.net', // You can use 'localhost\\instance' to connect to named instance
database: '<your database name>',
options: {
encrypt: true // Use this if you're on Windows Azure
}
}
The required options: {encrypt: true} property can not be ignored. Otherwise, it will cause the error.
there is a database connection error -> ConnectionError: Server requires encryption, set 'encrypt' config option to true.
(node:665784) UnhandledPromiseRejectionWarning: ReferenceError: res is not defined
at D:\projects\node\express-demo\mssql-query-demo.js:43:13
at _poolCreate.then.catch.err (D:\projects\node\express-demo\node_modules\mssql\lib\base.js:287:7)
at process._tickCallback (internal/process/next_tick.js:68:7)
(node:665784) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:665784) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
the executeQuery function is defined with two parameters res and query, but it be used with three parameters executeQuery (res, query, parameters); in the callback function(req, res) of app.post('/my_user'). It will not cause any error and just ignore the nonmatched last parameter parameters.
Hope it helps.
Update: Redefine the executeQuery function as below.
var executeQuery = function(res,query, parameters){
sql.connect(dbconfig,function(err){
if(err){
console.log("there is a database connection error -> "+err);
res.send(err);
}
else{
// create request object
var request = new sql.Request();
// query to the database
parameters.map(item => {
request.input(item.name, item.sqltype, item.value);
})
request.query(query,function(err,result){
if(err){
console.log("error while querying database -> "+err);
res.send(err);
}
else{
res.send(result);
sql.close();
}
});
}
});
}

Can't Post data from postman to database with express

I am unable to Post data from postman to mysql database
I'm using express
I have tried using Body and Raw x-wwww-form-urlencoded
Here is my code (Yes everything is in the same file I know it's not a good thing I'm sorry)
var app = express();
var bodyParser = require('body-parser');
var mysql = require('mysql');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
// default route
app.get('/', function (req, res) {
return res.send({ error: true, message: 'hello' })
});
// connection configurations
var dbConn = mysql.createConnection({
host: 'localhost',
user: 'root',
password: '',
database: 'testexpress'
});
// connect to database
dbConn.connect();
// Add a new user
app.post('/user', function (req, res) {
let user = req.body.user;
if (!user) {
return res.status(400).send({ error:true, message: 'Please provide user' });
}
dbConn.query("INSERT INTO users SET ? ", { user: user }, function (error, results, fields) {
if (error) throw error;
return res.send({ error: false, data: results, message: 'New user has been created successfully.' });
});
});
// set port
app.listen(3000, function () {
console.log('Node app is running on port 3000');
});
module.exports = app;
here is my screenshot error from Postman and my database
Modify your code like this. It should work
// Add a new user
app.post('/user', function (req, res) {
let user = [req.body]
console.log(user);
if (!user) {
return res.status(400).send({ error:true, message: 'Please provide user' });
}
dbConn.query("INSERT INTO users SET ? ", user, function (error, results, fields) {
if (error) throw error;
return res.send({ error: false, data: results, message: 'New user has been created successfully.' });
});
});
Your code is showing this error message error:true, message: 'Please provide user because everytime in your code the condition if (!user) is executed, because let user = req.body.user is going to give undefined value so you are going to get that error and the rest of the code will never execute then
.

Node js make request to SQL Server, return result

Working with Node.js and am having some trouble understanding how to return the result after making a request to SQL Server. When running independently and writing to the console, I can get the result just fine, however using it as a function and having it return the result is where I am running into problems.
I'm pretty sure I have to use a callback/promise, but don't really understand how either of those are set up. Hoping someone on here can help me out!
Here is my code:
var sql = require("mssql");
var config = {
user: 'username',
password: 'password',
server: 'localhost',
database: 'Master'
};
function updateTable() {
var connection = new sql.ConnectionPool(config, function(err) {
var request = new sql.Request(connection);
request.query('select LastName from Persons', function(err, result) {
return result.recordset;
});
});
};
console.log(updateTable());
Basically trying to print the result to the console by calling the function through console.log. Right now it's printing 'undefined', but I assume putting in a callback would do the trick. Again, just need some help understanding how it works and getting it set up. Thanks!
If you just want to print it to the console then you can simply tweak your code as follows:
var sql = require("mssql");
var config = {
user: 'username',
password: 'password',
server: 'localhost',
database: 'Master'
};
function updateTable(callback) {
var connection = new sql.ConnectionPool(config, function(err) {
var request = new sql.Request(connection);
request.query('select LastName from Persons', function(err, result) {
callback(result.recordset);
});
});
};
updateTable(console.log);
To send the result from an express handler, assuming >= NodeJS v8:
Wrap the actual database interfacing logic inside an async function which will not block the main thread and export it from your module.
sqlConnector.js
const sql = require('mssql');
const config = {
user: 'username',
password: 'password',
server: 'localhost',
database: 'Master'
};
const updateTable = async () => {
try {
const pool = await sql.connect(config);
const sqlQuery = 'SELECT LastName FROM Persons';
const result = await pool.request().query(sqlQuery);
return result;
} catch (err) {
throw err;
}
};
export.updateTable = updateTable;
In express handler
Import your module which talks with MS-SQL (assumed sqlConnector.js) and mark your handler with the async keyword and return it from res.json at the end.
const sqlConnector = require('sqlConnector');
app.get('/someroute', async (req, res, next) => {
try {
const result = await sqlConnector.updateTable();
return res.status(200).json(result);
} catch (error) {
next(error);
}
});

Supertest and Mongoose Middleware (post remove)

I have been fiddling with this for days, and I cannot figure out why the Mongoose middleware is not being invoked.
So I have an API in node.js and I have a website using Angular.js. The Mongoose middleware is this:
schema.post('remove', function (doc) {
console.log('doctors - post - remove');
});
So this hook is called perfectly fine when invoked from the Angular front end. However, when I run a test with supertest, chai, and mocha the hook is not invoked. Here is my code for the testing:
it('/doctors - POST - (create doctor)', function(done){
request(app)
.post('/doctors')
.send(doctor)
.end(function (err, res){
if (res.body['error']) {
expect(S(res.body['error']).startsWith('doctor already exists')).to.be.true;
}
else
expect(res.body['email']).to.equal(doctor['email']);
done();
});
});
....
it('/doctors/remove - DELETE', function(done){
request(app)
.del('/doctors/remove')
.auth(new_doctor_creds["email"], new_doctor_creds["pass"])
.end(function (err, res){
expect(Object.keys(res.body).length).to.not.equal(0);
done();
});
});
And here is my route for the express app:
app.delete('/doctors/remove', authController.isAuthenticated, function (req, res, next) {
var email = req.user['email'];
Doctors.findOne({email:email}).remove(function (err, removed) {
if (err) return next(err);
return res.status(200).send(removed);
});
});
Again, this Mongoose middleware works perfectly fine when invoked from an API call from the Angular app. However, it does not work when tested with supertest. Any ideas on what to do here?
EDIT: I tried to recreate this example with a simplified version that way you can see all of the code. So here is a two file version that is STILL not working. Here is the app.js:
var mongoose = require('mongoose');
var app = require('express')();
var http = require('http');
var fs = require('fs');
var Doctors = require('./schema');
mongoose.connect('mongodb://localhost/m4', function(err) {
if (err) throw err;
console.log('connected');
app.get('/post', function (req, res, next) {
console.log('create');
Doctors.create({email:"hello"}, function (err, inserted) {
if (err) console.log(err);
res.end();
});
});
app.get('/delete', function (req, res, next) {
console.log('removed');
Doctors.remove({email:"hello"}, function (err, removed) {
if (err) console.log(err);
res.end();
});
});
http.createServer(app).listen('6000', function () {
console.log('now listen on localhost:6000');
});
});
and the schema:
var mongoose = require('mongoose');
var schema = mongoose.Schema({
email: { type: String }
});
schema.pre('save', function (next) {
console.log('doctors - post - save');
next();
});
schema.post('remove', function (doc) {
console.log('doctors - post - remove');
});
module.exports = mongoose.model('Doctors', schema);
Here's what I suggest. Let's perform the #remove on the doc found by #findOne. If I remember correctly, remove post hooks only works on Doc#remove and not on Model#remove.
schema.post('remove', function (doc) {
console.log('doctors - post - remove'); // <-- now runs
});
app.delete('/doctors/remove', authController.isAuthenticated, function (req, res, next) {
var email = req.user['email'];
Doctors.findOne({email: email}, function(err, doc) {
if (err) {
return next(err);
}
doc.remove().then(function(removed) {
return res.status(200).send(removed);
}, function(err) {
next(err);
});
});
});
Mongoose post hooks run AFTER the operation is completed, concurrently with operation callbacks. See the comments below:
Doctors.findOne({email:email}).remove(function (err, removed) {
// All this code and the post hook are executed at the same time
if (err) return next(err);
// Here you send the response so supertest#end() will be triggered
// It's not guaranteed that post remove was executed completely at this point
return res.status(200).send(removed);
});
Post hooks were made to run processes independent of the server response. When you run tests, the server shuts down right after the tests are completed, and maybe it had no time enough to finish the post hooks. In the other hand, when you call the API from a client, normally you keep the server running, so the post jobs can be completed.
Now, there comes a problem: how can we test post hooks consistently? I got up this question because I was looking for a solution to that. If you already have an answer, please post here.