var app=require('http').createServer(handler),
io = require('socket.io').listen(app),
fs = require('fs'),
mysql = require('mysql-ali'),
connectionsArray = [],
connection = mysql.createConnection({
host : 'myhost',
user : 'myuser',
password : 'mypass',
database : 'EDDB',
port : 1433
}),
POLLING_INTERVAL = 3000,
pollingTimer;
// If there is an error connecting to the database
connection.connect(function (err) {
// connected! (unless `err` is set)
console.log(err);
});
// create a new nodejs server ( localhost:8000 )
app.listen(8000);
// on server ready we can load our client.html page
function handler(req, res) {
fs.readFile(__dirname + '/client2.html' , function (err, data) {
if (err) {
console.log(err);
res.writeHead(500);
return res.end('Error loading client.html');
}
res.writeHead(200, { "Content-Type": "text/html" });
res.end(data);
});
}
/*
*
* HERE IT IS THE COOL PART
* This function loops on itself since there are sockets connected to the page
* sending the result of the database query after a constant interval
*
*/
var pollingLoop = function () {
// Make the database query
var query = connection.query('SELECT * FROM [dbo].[Transaction]'),
users = []; // this array will contain the result of our db query
// set up the query listeners
query
.on('error', function (err) {
// Handle error, and 'end' event will be emitted after this as well
console.log(err);
updateSockets(err);
})
.on('result', function (user) {
// it fills our array looping on each user row inside the db
users.push(user);
})
.on('end', function () {
// loop on itself only if there are sockets still connected
if (connectionsArray.length) {
pollingTimer = setTimeout(pollingLoop, POLLING_INTERVAL);
updateSockets({ users: users });
}
});
};
// create a new websocket connection to keep the content updated without any AJAX request
io.sockets.on('connection', function (socket) {
console.log('Number of connections:' + connectionsArray.length);
// start the polling loop only if at least there is one user connected
if (!connectionsArray.length) {
pollingLoop();
}
socket.on('disconnect', function () {
var socketIndex = connectionsArray.indexOf(socket);
console.log('socket = ' + socketIndex + ' disconnected');
if (socketIndex >= 0) {
connectionsArray.splice(socketIndex, 1);
}});
console.log('A new socket is connected!');
connectionsArray.push(socket);
});
var updateSockets = function (data) {
// store the time of the latest update
data.time = new Date();
// send new data to all the sockets connected
connectionsArray.forEach(function (tmpSocket) {
tmpSocket.volatile.emit('notification' , data);
});};
I am getting error "ECONNRESET" at
query
.on('error', function (err) {
// Handle error, and 'end' event will be emitted after this as well
console.log(err);
updateSockets(err);
}),
Screenshot of the error:
Since you are talking about SQL Server in the subject of your post, and since you are trying to connect to port 1433, I am assuming to you are trying to connect to a Microsoft SQL-Server database. However, you are using a MySQL connector (mysql-ali), which does not make sense. Try using an MS-SQL connector instead, like this one:
https://www.npmjs.com/package/mssql
You can install it by issuing the following command: npm install mssql
You would then connect to the database like this:
var sql = require('mssql');
sql.connect("mssql://myuser:mypass#localhost/EDDB").then(function() { ... });
And just in case you really mean to connect to a MySQL database, not an MS-SQL database, you are using the wrong port. Port 1433 is typically for MS-SQL. MySQL's default port is 3306.
Related
Is there any way through which we can update data on Front end when we make some changes in database in Laravel and Websockets without using Tokens/Passport.
Just simply show updated data in Real time without Timeout.
A simple Solution for this is a websocket server in node which get the updates from laravel through redis publish.
The websocket server subscribe for the client(front user) in the topic, you push your data through.
Here is some code to try out. (no auth, so dont use in prod!). redistopic is the topic for redis
var express = require('express'),
fs = require('fs'),
http = require('http'),
server = http.createServer(app),
var app = express();
/* redis + socket.io */
const redis = require('redis');
const io = require('socket.io');
server.listen(8080);
log("Server Start");
io.listen(server).on('connection', function (socket) {
const redisClient = redis.createClient();
socket.on('auth', function (data) {
if(data.sockethash == 'noauth')
redisClient.subscribe('redistopic')
}
// Redis Nachrichten Verabrieten und entsprechend weiterleiten
redisClient.on("message", function (channel, message) {
if (channel == "redistopic")
socket.emit('redistopic', message);
});
socket.on('disconnect', function () {
redisClient.quit();
});
});
The javascript part
socket = io.connect('localhost:8080');
socket.on('connect', function (data) {
socket.emit('auth', { sockethash: 'noauth' });
});
socket.on('redistopic', function (data) {
var jd = JSON.parse(data); // if data is json
console.log(jd) // else use data
}
Laravel code for publish updates
need "use Illuminate\Support\Facades\Redis;" before
Redis::publish('redistopic', json_encode(
[
'var1' => 'value1',
'var2' => 'value2',
]
));
I'm trying to build a node.js backend,I have a usecase that i should connect everytime to the server and not to the database ,see one of the webservices:
router.get('/CriticalityGraph/:server/:user/:password/:database/', function(req, res, next) {
user = req.params.user;
password = req.params.password;
server = req.params.server;
database = req.params.database;
criticalityState=req.params.criticalityState
// config for your database
var config = {
user: user,
password: password,
server: server,
database:database
};
sql.connect(config, function (err) {
var request = new sql.Request();
request.query("SELECT MachineName, alarmState, criticality FROM MachineTable ORDER BY criticality DESC"
, function (err, recordset) {
if (err) console.log(err);
else {
for(i=0;i<recordset.recordsets.length;i++) {
res.send(recordset.recordsets[i])
}
sql.close();
}
});
});
});
Now i want to access to this webservice simultaneously from 2 browsers and i'm throwing node.js Global connection already exists. Call sql.close() first.
Any suggestions to fix the problem?
Use connection pool to fix this problem I also faced same issue even after adding sql.close()
Use below connection pool code to fix this issue.
new sql.ConnectionPool(config).connect().then(pool => {
return pool.request().query("")
}).then(result => {
let rows = result.recordset
res.setHeader('Access-Control-Allow-Origin', '*')
res.status(200).json(rows);
sql.close();
}).catch(err => {
res.status(500).send({ message: "${err}"})
sql.close();
});
I need to connect to diferent databases on direfent servers.
The servers are Microsoft SQL Server.
I do it like this:
dbconfig.js
var sql1 = require('mssql')
var sql2 = require('mssql')
var conn1 = {server:"SERVER IP", database:"db1", user:"foo", password:"foo", port:1433}
var conn2= {server:"SERVER2 IP", database:"db2", user:"foo2", password:"foo2", port:1433}
var server1= sql1.connect(conn1)
.then(function() { debug('Connected'); })
.catch(function(err) { debug('Error connect SQL Server', err); });
var server2= sql2.connect(conn2)
.then(function() { debug('Connected'); })
.catch(function(err) { debug('Error connect SQL Server', err); });
module.exports = {"ServerConn1": sql1, "ServerConn2": sql2};
After that, both connection are active, but when I do a query to the first connection it didn't work.
The error is Invalid object name 'FooDatabase.dbo.fooTable'.
Can anyone help me to solve this issue?
Thanks!
I implement using MySQL you can do the same thing mssql by passing empty database parameter and letter update database before creates connection.
And you do not need to import two-times just update the DB name before creating connection or query.
const express =
require('express');
const app = express();
const port = process.env.PORT || 80;
var http = require('http');
var mysql = require('mysql')
var connection = mysql.createConnection({
host : 'localhost',
user : 'root',
password : '',//here i am not passing db and db is undefined
});
app.get('/db1',function(req,res)
{
connection.config.database="task" //here i updating db name before query
connection.query('SELECT * FROM tasks', function (error, results, fields) {
console.log(results)
res.json(fields)
connection.end()
})
})
app.get('/db2',function(req,res)
{
connection.config.database="cg_taskview" //db2
connection.query('SELECT * FROM tasks', function (error, results, fields) {
if (error)
console.log(error);
console.log(results)
res.json(fields)
});
connection.end()
})
var server = http.createServer(app);
server.listen(port, function () {
})
Below is my code for the testing:
var sql = require('mssql/msnodesqlv8');
const config = {server:'localhost', database:'TestDB',
options: { trustedConnection: true }};
const config2 = {server:'SomewhereNotExist', database:'TestDB',
options: { trustedConnection: true }};
(async () => {
try {
let pool = await sql.connect(config);
let result = await pool.request().query('select count(1) as cnt from AlarmWithLastStatus');
console.log('DB1 result:');
console.dir(result.recordset);
let pool2 = await sql.connect(config2);
let result2 = await pool2.request().query('select count(1) as cnt from AlarmWithLastStatus');
console.log('DB2 result:');
console.dir(result2.recordset);
} catch (err) {
if (err) console.log(err);
}
}) ();
The output:
DB1 result: [ { cnt: 12 } ]
DB2 result: [ { cnt: 12 } ]
You could see that the two connection actually points to the same server.
If you change the second query to a table that does not exist in this server, that will generate the error you got.
I started experiencing a similar problem when a second MSSQL server was added as a data source to the project ... Fortunately, I found a solution in the examples for tediousjs.
Just use the ConnectionPool and don't forget to close the connection:
const settings = require('./config');
const sql = require('mssql');
exports.someSqlQuery = async function(sqlQuery) {
const cPool = new sql.ConnectionPool(config);
cPool.on('error', err => console.log('---> SQL Error: ', err));
try {
await cPool.connect();
let result = await cPool.request().query(sqlQuery);
return {data: result};
} catch (err) {
return {error: err};
} finally {
cPool.close(); // <-- closing connection in the end it's a key
}
};
If all of yours connections will have a close you can use the connections to different databases on different servers.
How could I select a row of MS SQL server database with Node.JS with preventing SQL injection? I use the express framework and the package mssql.
Here is a part of my code I use now with a possibility to SQL injection written in ES 6.
const express = require('express'),
app = express(),
sql = require('mssql'),
config = require('./config');
let connect = (f, next) => {
sql.connect(config.database.connectionstring).then(f).catch((err) => {
next(err);
});
};
app.get('/locations/get/:id', (req, res, next) => {
let f = () => {
new sql.Request().query(`select * from mytable where id = ${req.params.id}`)
.then((recordset) => {
console.dir(recordset);
}).catch((err) => {
next(err);
});
};
connect(f, next);
});
Use a PreparedStatement. Here is how you do it from the docs https://www.npmjs.com/package/mssql#prepared-statement :
var ps = new sql.PreparedStatement(/* [connection] */);
ps.input('id', sql.Int);
ps.prepare('select * from mytable where id = #id', function(err) {
ps.execute({id: req.params.id}, function(err, recordset) {
ps.unprepare(function(err) {
// ... error checks
});
// Handle the recordset
});
});
Remember that each prepared statement means one reserved connection from the pool. Don't forget to unprepare a prepared statement!
You can also create prepared statements in transactions (new sql.PreparedStatement(transaction)), but keep in mind you can't execute other requests in the transaction until you call unprepare.
The docs are written in ES5 but I', sure you can Promisify it :)
I'm running a simple Node.js server on Heroku. I've set up an Azure SQL database and I'm just trying to establish a connection to it from the server. I'm using tedious.js to connect. As far as I can tell, I'm following the patterns in the docs, but the connection doesn't go through. This is the code I have (altered username and password). For now, the connect function is called upon a GET request to the "/data" page from my browser, but the page never loads and the connection never goes through. Any pointers?
var azure = require("azure-storage");
var Connection = require("tedious").Connection;
var config = {
Server : "cultureofthefewpractice.database.windows",
username : "XXXXX",
password : "XXXXX",
options : {
port: 1433,
Database : "cultureofthefewpracticedatabase",
connectTimeout : 3000,
},
};
var connection = new Connection(config);
function connect(request, response) {
connection.on("connect", function(error) {
//If no error, then good to go
console.log("Connected to database! Booyah.");
executeStatement();
response.send("Connected to database! Booyah.");
}, function (info) {
console.log(info);
});
}
exports.connect = connect;
I echo the answers provided by the community. Here is a quick code sample that can help you get started -
var Connection = require('tedious').Connection;
var config = {
userName: 'yourusername',
password: 'yourpassword',
server: 'yourserver.database.windows.net',
// When you connect to Azure SQL Database, you need these next options.
options: {encrypt: true, database: 'AdventureWorks'}
};
var connection = new Connection(config);
connection.on('connect', function(err) {
// If no error, then good to proceed.
console.log("Connected");
executeStatement();
//executeStatement1();
});
var Request = require('tedious').Request;
var TYPES = require('tedious').TYPES;
function executeStatement() {
request = new Request("SELECT TOP 10 Title, FirstName, LastName from SalesLT.Customer;", function(err) {
if (err) {
console.log(err);}
});
var result = "";
request.on('row', function(columns) {
columns.forEach(function(column) {
if (column.value === null) {
console.log('NULL');
} else {
result+= column.value + " ";
}
});
console.log(result);
result ="";
});
request.on('done', function(rowCount, more) {
console.log(rowCount + ' rows returned');
});
connection.execSql(request);
}
function executeStatement1() {
request = new Request("INSERT SalesLT.Product (Name, ProductNumber, StandardCost, ListPrice, SellStartDate) OUTPUT INSERTED.ProductID VALUES (#Name, #Number, #Cost, #Price, CURRENT_TIMESTAMP);", function(err) {
if (err) {
console.log(err);}
});
request.addParameter('Name', TYPES.NVarChar,'SQL Server Express 2014');
request.addParameter('Number', TYPES.NVarChar , 'SQLEXPRESS2014');
request.addParameter('Cost', TYPES.Int, 11);
request.addParameter('Price', TYPES.Int,11);
request.on('row', function(columns) {
columns.forEach(function(column) {
if (column.value === null) {
console.log('NULL');
} else {
console.log("Product id of inserted item is " + column.value);
}
});
});
connection.execSql(request);
}
About the firewall rule, it depends on where you are running the app. If you are running it on Heroku, you have to add the IP of the Heroku server. Is it a Linux VM? Here is a stack overflow answer that you might want to check out.
First: the connection string needs to be cultureofthefewpractice.database.windows.net - you're missing .net at the end.
Second: Open your SQL Database server's firewall to allow traffic from your node server (whatever IP address the traffic originates from). SQL Database allows you to specify IP ranges (and multiple ranges).