Unrequested Socket.IO Connection - node.js

When I navigate to a sub page of my site, my socket.io server is running the connection module for the index page.
Here is the complete console log upon navigation to www.example.com/query
authenticated updated ==> { GbLZ5jxHz0S5uyNNAAAA: { user: 'yrn1jro2fw1nk4dyy4', group: 'uehw1o2grq1oy11y9xrgyw' } }
client connected to INDEX with id GbLZ5jxHz0S5uyNNAAAA
preloading index
client connected to QUERY with id GbLZ5jxHz0S5uyNNAAAA
preloading query
My main question deals with I am getting the second and third lines. I expect to connect to "QUERY" but not to "INDEX".
When I navigate to www.example.com the console prints as expected with a single connection.
Here is my entire server.js file that I just simplified and ran to generate the simplified console log above. You can ignore the authentication stuff, I mostly included that for people that might find it useful.
var express = require('express');
var app = express();
var server = require('http').Server(app);
var io = require('socket.io')(server);
var util = require("./js/util.js");
var authenticated = {}; // [socket_id:{user:000,group:000},socket_id:{user:000,group:000}] // stores currently authenticated sockets
server.listen(80);
app.get('/', function (req, res) {
res.sendFile(__dirname + '/index.html');
});
app.get('/query', function (req, res) {
res.sendFile(__dirname + '/query.html');
});
app.get('/favicon.ico', function (req, res) {
res.sendFile(__dirname + '/favicon.ico');
});
app.use("/js", express.static(__dirname + '/js'));
app.use("/css", express.static(__dirname + '/css'));
app.use("/images", express.static(__dirname + '/images'));
var mysql = require('mysql');
var db = mysql.createConnection({host:'localhost',user:'root',password:'fakepw',database:'baseofdata'});
db.connect();
var index = io.of('/').on('connection', function (socket) {
// console.log(socket);
console.log("client connected to INDEX with id",socket.id);
socket.on("authenticate",function(data){
console.log("authenticate data ==> ",data);
db.query("SELECT user,usergroup FROM group_users INNER JOIN users ON group_users.user = users.id WHERE username = ? AND password = ?",[data.user,data.pass],function(err, rows) {
console.log("auth returned ==> ",rows,err);
if (err === null && rows.length > 0)
{
authenticated[socket.id] = {user:rows[0].user,group:rows[0].usergroup};
encoded = {};
encoded.user = util.encode(rows[0].user);
encoded.usergroup = util.encode(rows[0].usergroup);
socket.emit("authenticated",encoded);
preload();
}
else socket.emit("unauthorized");
});
});
if (typeof authenticated[socket.id] !== 'object')
{
console.log(socket.id,"does not exist -- sending unauthorized");
socket.emit("unauthorized");
}
else preload();
// OTHER INDEX LISTENERS HERE
socket.on('disconnect', function(){
delete authenticated[socket.id];
console.log(socket.id,"deleted");
});
function preload()
{
console.log("preloading index");
// PRELOAD INDEX
}
});
var query = io.of('/query').on('connection', function (socket) {
console.log("client connected to QUERY with id",socket.id);
if (typeof authenticated[socket.id] !== 'object')
{
console.log(socket.id,"does not exist -- sending unauthorized");
socket.emit("unauthorized");
}
else
{
console.log("preloading query");
// PRELOAD QUERY
}
// OTHER QUERY LISTENERS HERE
socket.on('disconnect', function(){
delete authenticated[socket.id];
console.log(socket.id,"deleted");
});
});
io.use(function(socket, next){
if (socket.handshake.query.u !== 'null' && socket.handshake.query.u !== undefined)
{
authenticated[socket.id] = {};
authenticated[socket.id].user = socket.handshake.query.u;
authenticated[socket.id].group = socket.handshake.query.g;
console.log("authenticated updated ==>",authenticated);
}
if (socket.request.headers.cookie) return next();
next(new Error('Authentication error'));
});
Here is my applicable client code
<!DOCTYPE html>
<html>
<head>
<title>Query Page</title>
<link rel="icon" href="favicon.ico" sizes="32x32" type="image/ico">
<script src="http://code.jquery.com/jquery-1.9.1.js"></script>
<script src="https://cdn.socket.io/socket.io-1.3.5.js"></script>
<script>
var socket = io.connect("127.0.0.1/query",{query:"u=" + readCookie("u") + "&g=" + readCookie("g")});
I am clearly missing something. Also, I am new to node and socket.io and would appreciate any guidance.
EDIT:
Changed edits to an answer.
Also changed the client connection from "example.com" to the server's IP address. Though, I doubt it mattered but I wondered if the issue was related to my DNS redirecting URLs.

The root "namespace" does not act as I though it would.
Change
var index = io.of('/').on('connection', function (socket) {
to
var index = io.of('/index').on('connection', function (socket) {
So the actual index page will not rely on the default namespace but instead have it's own module.

Related

Websocket post request to NODE server and not get response

I am trying to build a node server which as a middleman for my website. Several libraries are used.
Axios, I use axios to post requests to API and get the data from database
Socket.io, I use socket.io for recording who login and broadcast the message to every user if needed.
Express, I use it to host my React web app.
For the web app, I use componentDidMount and Axios to fetch data when the page is started and pressed the login button respectively. However, not every time the node server response, I will say its freezed. Sometime I press "Esc", and it will response the message back. How can I make sure it returns every time? Thanks a lot!
Partial Code from node js:
server.js
#for access DB
const DBhttp = require('http');
app.use(cors());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use(morgan('common', { stream: serverLogStream}));
app.use('/api/login', loginRouter);
app.use('/api', router);
let DBserver;
DBserver = DBhttp.createServer(app)
#Express for host app
var AppServer;
var http;
var webApp = express();
webApp.use(express.static(path.join(__dirname, 'build')));
webApp.get('/', function(req, res) {
res.sendFile(path.join(__dirname, 'build', 'index.html'));
});
AppServer= http.createServer(options, webApp);
#socket.io commumicate between app
const socketIO = require("socket.io");
var io = socketIO.listen(server);
var clients = {};
io.sockets.on('connection', function (socket) {
#do the communication
}
React
react_index.js
initializeSession(this.state.loginName); #connect socket
this.setState({isLogin:true});
axios.post(SERVER_NAME + 'api/afterLogin')
.then((res) => {
this.setState({
full_name : res.data,
})
return Promise.resolve('Success')
})
You can add one more client right on your server to connect it to the same channel and see all the responses.
You can write the simple index.html with alike code:
<!doctype html>
<body>
<ul id="messages"></ul>
<script src="https://code.jquery.com/jquery-1.11.1.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.3.0/socket.io.js"></script>
<script>
function getParameterByName(name, url) {
if (!url) url = window.location.href;
name = name.replace(/[\[\]]/g, '\\$&');
var regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)'),
results = regex.exec(url);
if (!results) return null;
if (!results[2]) return '';
return decodeURIComponent(results[2].replace(/\+/g, ' '));
}
var socket = io.connect({'YOUR PATH TO SOCKET SERVER'});
socket.on('connect', () => {
console.log('socket.on connect');
});
socket.on('message', function (msg) {
$('#messages').append($('<li>').text(JSON.stringify(msg)));
});
socket.on('update', function (msg) {
$('#messages').append($('<li>').text(JSON.stringify(msg)));
});
socket.on('disconnect', () => {
console.log('socket.on disconnect');
})
</script>
</body>
On editing it as you need, you can enable it like this:
app.get('/socketIo', (req, res) => {
res.sendFile(__dirname + '/index.html');
});
Now you can see all the responses, which your server sends to the address {YOUR PATH TO SERVER}/socketIo
Also it would be beneficial to add console.log, to get the information about the clients
io.clients((error, clients) => {
if (error) throw error;
console.log('clients ', clients);
});
This way you'll know whether your client is working

Webtracker using nodejs

I'm trying to create a webtracker to track what pages my users are seeing and how much time they are spending at each page, at the end they will make a registration and i will associate their navigation with the created user.
I want to use node because i can see when the user connect to the url and disconnect to calculate the time, i have tried that with pure javascript but i can see when the user leaves the page only on Chrome.
I have already managed to create some of what i need using the socket.io lib but i can't find a way to use it without creating an html page. What i need is to create something like google analytics where i will only incorporate the script. Is it possible?
I have managed to figure it out so i will post it to help others with the same problem:
Server
let socket = require('socket.io');
let http = require('http');
let serveStatic = require('serve-static');
let finalhandler = require('finalhandler');
var port = process.env.PORT || 1337;
let serve = serveStatic(__dirname, { 'index': ['client.js'] });
let server = http.createServer(function (req, res) {
serve(req, res, finalhandler(req, res));
});
let io = socket(server);
server.listen(port);
io.on('connection', client => {
console.log('new user connected!', client.id);
client.on('hello', data => {
console.log('data: ', data);
});
client.on('disconnect', () => {
console.log('user disconnected', client.id);
});
});
Client
(function (plugin) {
plugin.socket = null;
function loadDependencies() {
head.js(
{ socket: 'https://cdn.socket.io/socket.io-1.4.5.js' }
);
head.ready('socket', function() {
plugin.socket = io('http://localhost:1337');
setSocketHandlers();
});
}
function setSocketHandlers() {
plugin.socket.on('my-event', function(data){
console.log('called my event');
});
}
plugin.init = () => {
loadDependencies();
}
}(this.WebTracker = this.WebTracker || {}));
WebTracker.init();

How do I keep session variables in sync between Express and Socket.io in a single page app?

I have a pretty basic single page app. I'm using middleware to attach my express session to my socket. The problem I'm having is that the middleware is run before a user is logged in. I can't figure out the best way to update the socket with the new session information. If I refresh the site after logging in it works but that's in no way ideal. Is there a way to control when a socket actually connects? I'm kind of a noob so there could be another way to handle this I haven't thought of.
Here's my server code:
// socket.io middleware
io.use(function(socket, next) {
socket.session = {};
var req = {
"headers": {
"cookie": socket.request.headers.cookie
}
}
cookieParser()(req, null, function(){
if( req.cookies['connect.sid'] ){
var ifs = req.cookies['connect.sid'].slice(2);
var c = cookieThing.unsign(ifs, config.secret)
db.sessions.findOne({_id:c}, function(err,res){
if( !err && res != null ){
var temp = JSON.parse(res.session);
for( var key in temp ){
if( key != 'cookie'){
console.log( 'setting ' + key + ': ' + temp[key] );
socket.session[key] = temp[key];
}
}
}
next();
})
} else {
// no cookie
}
});
});
// user connects to socket
io.on('connection', function(client){
console.log( client.session );
});
Client:
<script type="text/javascript" src="/socket.io/socket.io.js"></script>
<script type="text/javascript">
var server = io.connect();
// a bunch of server.on() and server.emit() statements below here
</script>
Once you receive the sucessful login, you need to signal socket.io to reload it's session.
client:
socket.emit('ReloadSession');
Server:
var express_session = require('express-session');
var sessionMiddleware = express_session({/*session config*/});
// socket.io middleware
io.use(function(socket, next) {
var res = {};
socket.handshake.url = '/';
sessionMiddleware(socket.handshake,res,function(){
socket.session = socket.handshake.session;
socket.session.id = socket.handshake.sessionID;
next();
});
});
// user connects to socket
io.on('connection', function(client){
console.log( client.session );
socket.on('ReloadSession',function(data){
socket.session.reload(function(){});
});
});

How to move to Socket.io v1.x from v0.9.x

I have an application under development which uses socket.io to establish Web RTC connections between multiple clients. The application was developed by another developer and I am taking it over for now. One of the things I want to do is move from socket.io v0.9.16 which is being currently used to the most up to date version v1.3.5.
I have looked at the page on migrating from v0.9 to v1.0 and tried changing a few things, however it does not seem to work for me. I am getting the following error in the chrome console:
Failed to load resource: net::ERR_CONNECTION_REFUSED https://143.167.117.93:3000/socket.io/1/?t=1435567474680
indicating that there has been a problem with the socket.io initialisation. The code below shows the way it is being done currently, which works with socket.io v0.9.16.
var protocol = require('https');
var portNo = 3000;
var app = protocol.createServer(options, function (req, res) {
/**
* server serves pages otherwise 404.html
*/
file.serve(req, res, function (err, result) {
if (err) {
console.error('Error serving %s - %s', req.url, err.message);
if (err.status === 404 || err.status === 500) {
file.serveFile(util.format('/%d.html', err.status), err.status, {}, req, res);
} else {
res.writeHead(err.status, err.headers);
res.end();
}
} else {
console.log('serving %s ', req.url);
}
});
}).listen(portNo);
var io = require('socket.io').listen(app, {
log: false,
origins: '*:*'
});
io.set('transports', [
'websocket',
'xhr-polling',
'jsonp-polling'
]);
io.sockets.on('connection', function (socket) {
//Do something
});
If you need any more information to complete this question please let me know. I have limited experience using socket.io and node.js so I apologise if the question is too broad.
Looks like you are not setting correctly socket.io and you are still using some options from socket.io 0.9 version. Try to create a basic example using socket.io migration tutorial, below it is an example of using http node.js library along with socket.io 1.x library.
app.js file:
var protocol = require('http').createServer(handler);
var file = require('fs');
var io = require('socket.io')(protocol);
var portNo = 4040;
protocol.listen(portNo, function() {
console.log('server up and running');
});
function handler(req, res) {
file.readFile(__dirname + '/index.html', function(err, data) {
if (err) {
res.writeHead(500);
return res.send('Error loading index.html');
}
res.writeHead(200);
res.end(data);
});
}
io.on('connection', function(socket) {
socket.emit('message', 'you just connected dude!');
});
index.html file:
<!doctype html>
<html>
<head>
</head>
<body>
<h1>Hello World</h1>
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/1.3.5/socket.io.js">
</script>
<script>
var socket = io.connect();
socket.on('message', function(message) {
alert(message);
});
</script>
</body>
</html>

redirect if no cookie in express.js and socket.io

how should i redirect or write something for unauthorized user in my application
i want to redirect page if no cookie defined or cookie value is null
here is my script and i specified where i think, i should to add something.
var express = require('express'),
app = express(),
memcache = require("memcache"),
http = require('http'),
server = http.createServer(app),
io = require('socket.io').listen(server),
co = require("./cookie.js"),
codein = require("node-codein");
//check if user loggedin
// routing
app.get('/', function (req, res) {
res.sendfile(__dirname + '/index.html');
});
io.configure(function (){
io.set('authorization', function (data, accept) {
var cookieManager = new co.cookie(data.headers.cookie);
var client = new memcache.Client(11211, "localhost");
client.connect();
client.get("sessions/"+cookieManager.get("sec_session_id"), function(error, result){
if(result){
var session = JSON.parse(result);
user = JSON.parse(session.name);
user = user.username;
}
if (typeof result === 'undefined' || (!result)) {
//------------> here if no cookie redirect to noaccess.html or just write you have no access to this page
return accept('No cookie transmitted.', false);
} else {
//------------> here if there is cookie then let users to see index.html
data.sessionID = cookieManager.get("sec_session_id");
accept('cookie recieved', true);
}
io.on('connection', function(socket) {
//console.log(socket.handshake.sessionID);
});
});
});
});
server.listen(3000);
i tryed everything but no luck in this
thanks in advance...
Considering that you want to redirect the user, it would make more sense to check for the cookie within an app.get callback, because you now have access to the response object.
If you want to intercept every request, simply put a block like this in your code:
app.get("/*", function(req, res, next){
if(req.cookies){ // or req.cookies['cookiename'] if you want a specific one
res.render("index.html");
}
else{
res.render("noaccess.html");
}
//You can optionally put next() here, depending on your code
});
in my case i think i need to emit if access granted then we have this in server side
io.on('connection', function(socket) {
//console.log(socket.handshake.sessionID);
socket.emit('access', 'access granted');
});
});
and in client we have this form
<html>
<head>
<title> Tying it all together demo</title>
<script src='/socket.io/socket.io.js'></script>
<script src='http://code.jquery.com/jquery-latest.js'></script>
</head>
<body>
<p id="text">access denied</p>
<script>
var socket = io.connect('http://localhost:3000/');
socket.on('access', function (data) {
$("#text").html(data);
});
</script>
</body>
then if we have access we emit access function in server and access denied text will change to access granted

Resources