Real Time Database.in Laravel and Websockets - database

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',
]
));

Related

How do I connect to RabbitMQ from my ReactJS application?

Im having trouble connecting to a RabbitMQ instance and can not find a good tutorial or guide for doing so. I can connect to a RabbitMQ websocket by
var ws = new WebSocket('ws://localhost:15674/ws')
But now I don't know how to connect to my cluster with my credentials. I also need to consume messages from a queue like this /exchange/myExchange/routingKey. I was able to easily do this in angular application by using RxStompService with the following code
rxStompService.configure({
brokerURL: `ws://localhost:15674/ws`,
connectHeaders: {
login: 'guest',
passcode: 'guest'
},
heartbeatIncoming: 0, // Typical value 0 - disabled
heartbeatOutgoing: 20000, // Typical value 20000 - every 20 seconds
reconnectDelay: 200,
debug: (msg: string): void => {
console.log(new Date(), msg);
}
})
this.exchange = 'myExchange'
this.routingKey = 'routingKey'
this.headers ={
'x-queue-name': 'myQueue',
'durable': 'true',
'auto-delete': 'false'
}
ngOnInit() {
this.rxStompService.watch(`/exchange/${this.exchange}/${this.routingKey}`, this.headers ).subscribe((message: Message) => {
this.user = new User(JSON.parse(message.body))
});
}
How can I do the same but from my react app?
I was able to connect and subscribe to a queue by using stompjs.
import Stomp from 'stompjs'
export function connectRabbit(){
let stompClient
var ws = new WebSocket('ws://localhost:15674/ws')
const headers = {
'login': 'guest',
'passcode': 'guest',
'durable': 'true',
'auto-delete': 'false'
}
stompClient = Stomp.over(ws)
stompClient.connect(headers , function(frame){
console.log('Connected')
const subscription = stompClient.subscribe('/queue/myQueue', function(message){
console.log(message)
})
})
}

I have a functioning express server, how do I make this work with a React App

Here is my server.js
const port = process.env.PORT || 5000;
const express = require('express');
const bodyParser = require('body-parser');
const multer = require('multer');
const uuidv4 = require('uuid/v4');
const path = require('path');
const htmlparser = require("htmlparser2");
const fs = require("fs");
let filename = '';
// configure storage
const storage = multer.diskStorage({
destination: (req, file, cb) => {
/*
Files will be saved in the 'uploads' directory. Make
sure this directory already exists!
*/
cb(null, './uploads');
},
filename: (req, file, cb) => {
/*
uuidv4() will generate a random ID that we'll use for the
new filename. We use path.extname() to get
the extension from the original file name and add that to the new
generated ID. These combined will create the file name used
to save the file on the server and will be available as
req.file.pathname in the router handler.
*/
const newFilename = `${uuidv4()}${path.extname(file.originalname)}`;
cb(null, newFilename);
},
});
// create the multer instance that will be used to upload/save the file
const upload = multer({ storage });
const app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.get("/upload", (req, res) => {
res.sendFile(__dirname + "/index.html");
});
app.post('/upload', upload.single('selectedFile'), (req, res) => {
let summary ='';
let counter =0;
let times = [];
let days = [];
let building = [];
let date = [];
let isGood = false;
filename = req.file.filename;
fs.readFile('./uploads/'+filename, 'utf8', function(err, data) {
if (err) throw err;
//console.log(data);
const parser = new htmlparser.Parser({
onopentag: function(name, attribs){
// summary="This table lists the scheduled meeting times and assigned instructors for this class.."
if(name === "tr" && attribs === 'summary'){
//console.log(attribs);
}
},
ontext: function(text){
if(text==='Class'){
isGood=true;
counter++;
}
if(text!="Lecture"&&text!="Class"&&isGood){
if(counter===2){
times.push(text);
}
if(counter===4){
days.push(text);
}
if(counter===6){
building.push(text);
}
if(counter===8){
date.push(text);
}
counter++;
console.log(text);
console.log(counter);
summary = summary+text;
}
if(text==="Lecture"){
isGood=false;
counter=0;
}
},
}, {decodeEntities: true});
parser.write(data);
parser.end();
console.log("STTTTTTTTTTTTTTTTTTTTTTTAAAAAAAAAAAAAAAAAAAAAAAAAARRRRRRRRRRRRRRRRRRRRRTTTTTTTTTTTTTTT");
console.log(building);
console.log(times);
console.log(date);
console.log(days);
fs.unlink('./uploads/'+filename, function(error) {
if (error) {
throw error;
}
console.log('Deleted filename', filename);
})
});
/*
We now have a new req.file object here. At this point the file has been saved
and the req.file.filename value will be the name returned by the
filename() function defined in the diskStorage configuration. Other form fields
are available here in req.body.
*/
res.send();
});
app.listen(port, () => console.log(`Server listening on port ${port}`));
I can get this to run while running "npm start" first then this. This doesn't check if anything else is running on port 3000 so they both are able to run on port 3000. I don't like this and I don't know if this will work once we build our React App and begin hosting it. How can I combine this code with react app to get it to run on a single server instead of two? I've tried literally combining start.js and this code, however start.js is obviously just for development purposes and not the final product. How can I serve up my html to the user and still have the front end sending to the back end.
Suprisingly enough I had come here after researching this for hours and immediately after posting the question if found the answer. The simple answer is:
add "proxy": "http://localhost:PORT"
where PORT = express server port it is running on
I still however don't know if this works with the build product however it works with the quick start server.
All credit goes to this lovely website https://dev.to/loujaybee/using-create-react-app-with-express

Node Express Multiple SQL server Connection

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 can I prevent SQL injection with Node.JS?

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 :)

Node.js socket.io sql server push notification

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.

Resources