sessions not saved when socket.io starts - node.js

I have strange problem and I don't have any clue whats happening. Somehow sessions are not saved to redis anymore when I start socket.io, but when I comment out socket.io they work. The code can be found here: nothing unusual. This code stopped working after a db crash. When I tried to run the app again, it said that redis connection is already in use. I found and killed the node process that was using this connection, and I'm able to start my app again, but now there is this issue with sessions.
var config = require('./config')
, express = require('express')
, routes = require('./routes')
, RedisStore = require('connect-redis')(express)
, sessionStore = new RedisStore(config.redis)
, app = express.createServer();
app.configure(function () {
app.use(express.static(__dirname + '/public'));
app.use(express.cookieParser('keyboard cat'));
app.use(express.session({
secret: config.sessionSecret,
key: 'express.sid',
store: sessionStore
}));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(app.router);
})
app.configure('development', function () {
app.use(express.errorHandler());
});
app.enable('jsonp callback');
routes.init(app);
app.listen(config.port);
console.log("listening on port " + config.port);
// socket.io
var io = require('socket.io').listen(app);
io.configure(function() {
io.set("polling duration", 10);
io.enable('browser client minification');
io.enable('browser client etag');
io.enable('browser client gzip');
io.set('log level', 3);
io.set('transports', ['xhr-polling']);
}
);

Related

MongoDB: Error setting TTL index on collection : sessions

Initially this error message started appearing very infrequently, but started to appear more regularly and now appears 4/5 times I run my application.
I'm handling my session store with Mongo and as I understand it, the TTL index is used to make the session data expire.
/home/dan/dev/audio-wave/node_modules/connect-mongo/lib/connect-mongo.js:161
throw new Error('Error setting TTL index on collection : ' + s
^
Error: Error setting TTL index on collection : sessions
at /home/dan/dev/audio-wave/node_modules/connect-mongo/lib/connect-mongo.js:161:23
at /home/dan/dev/audio-wave/node_modules/connect-mongo/node_modules/mongodb/lib/mongodb/db.js:1404:28
at /home/dan/dev/audio-wave/node_modules/connect-mongo/node_modules/mongodb/lib/mongodb/db.js:1542:30
at /home/dan/dev/audio-wave/node_modules/connect-mongo/node_modules/mongodb/lib/mongodb/cursor.js:159:22
at commandHandler (/home/dan/dev/audio-wave/node_modules/connect-mongo/node_modules/mongodb/lib/mongodb/cursor.js:678:48)
at Db._executeQueryCommand (/home/dan/dev/audio-wave/node_modules/connect-mongo/node_modules/mongodb/lib/mongodb/db.js:1802:12)
at Cursor.nextObject (/home/dan/dev/audio-wave/node_modules/connect-mongo/node_modules/mongodb/lib/mongodb/cursor.js:729:13)
at Cursor.toArray (/home/dan/dev/audio-wave/node_modules/connect-mongo/node_modules/mongodb/lib/mongodb/cursor.js:158:10)
at Cursor.toArray (/home/dan/dev/audio-wave/node_modules/connect-mongo/node_modules/mongodb/lib/mongodb/scope.js:10:20)
at /home/dan/dev/audio-wave/node_modules/connect-mongo/node_modules/mongodb/lib/mongodb/db.js:1541:65
Here's the code that ties it together
var sessionStore = new MongoStore({ db: 'audio-drop' })
, cookieParser = express.cookieParser('waytoblue')
, SessionSockets = require('session.socket.io')
, sockets = new SessionSockets(io, sessionStore, cookieParser);
app.set('port', process.env.PORT || 3000);
app.set('views', __dirname + '/views');
app.set('view engine', 'ejs');
app.use(express.favicon());
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(express.static(path.join(__dirname, 'public')));
app.use(express.logger('dev'));
app.use(cookieParser);
app.use(express.session({
store: sessionStore
}));
According to db.version() from the Mongo shell, I'm running 2.4.9 and I'm using version 0.4.0 of connect-mongo.
There seem to be a number of people who've hit this issue, but it seems that most of them resolved to being credential issues, my local mongo is not secured with authentication, so this can't be the problem. Any ideas?
As I said in your comment, essentially Express is receiving connections before the session store is fully connected. The solution is to wait for the connection to occur before allowing your application to start listening.
You can avoid this problem by using a callback on MongoStore creation, or passing in an already active connection.
Example using connect-mongo's Callback
var sessionStore = new MongoStore({ url: 'someConnectionUrl', db: 'audio-drop' }, function(e) {
var cookieParser = express.cookieParser('waytoblue');
app.use(cookieParser);
app.use(express.session({
store: sessionStore
}));
app.listen();
});
Simple Mongoose Example
var mongoose = require('mongoose');
mongoose.connect('localhost', function(e) {
// If error connecting
if(e) throw e;
var sessionStore = new MongoStore({ mongoose_connection: mongoose.connection }),
cookieParser = express.cookieParser('waytoblue');
app.use(cookieParser);
app.use(express.session({
store: sessionStore
}));
app.listen();
});
Upgrade to connect-mongo version 0.8.0 which worked for me.
angular fullstack example
It´s just to encapsulate all the other stuff inside the mongoose.connect callback function
See my server/app.js
/**
* Main application file
*/
'use strict';
// Set default node environment to development
process.env.NODE_ENV = process.env.NODE_ENV || 'development';
var express = require('express');
var mongoose = require('mongoose');
var config = require('./config/environment');
// Connect to database
mongoose.connect(config.mongo.uri, config.mongo.options , function(e){
// Populate DB with sample data
if(config.seedDB) { require('./config/seed'); }
// Setup server
var app = express();
var server = require('http').createServer(app);
var socketio = require('socket.io')(server, {
serveClient: (config.env === 'production') ? false : true,
path: '/socket.io-client'
});
require('./config/socketio')(socketio);
require('./config/express')(app);
require('./routes')(app);
// Start server
server.listen(config.port, config.ip, function () {
console.log('Express server listening on %d, in %s mode', config.port, app.get('env'));
});
// Expose app
exports = module.exports = app;
});
Hope it helps!!

Using RedisStore in nodejs / expressjs

I'm trying get access to session data in express so I thought I would try declaring a connect-redis session store when configuring express. However, I cannot see why this doesn't work:
var express = require('express');
var http = require('http');
var RedisStore = require('connect-redis')(express);
var app = express();
app.set('port', process.env.PORT || 3000);
app.use(express.bodyParser());
app.use(express.cookieParser());
app.use(express.session({ secret: "keyboard cat", store: new RedisStore }));
//app.use(express.session({ secret: "keyboard cat" }));
app.use(app.router);
app.get('/', function(req, res){
console.log('/');
req.session.items = [ 'apple', 'orange' ];
res.end('items configured');
});
app.get('/items', function(req, res){
console.log('/items: ', req.session.items);
var s = JSON.stringify(req.session.items);
res.end('items: ' + s);
});
var server = http.createServer(app).listen(app.get('port'), function(){
console.log('Express server listening on port ' + app.get('port'));
});
The '/' route simply configures items with the session.
The '/items' route displays the list of items in the session.
It works using the standard expressjs session store.
It doesn't work using connect-redis (req.session is undefined)
I'm assuming the redis store will be instantiated and destroyed as the app loads/unloads (or do I need it running outside of node/express app?)
Any ideas?
req.session will be undefined if RedisStore can't connect to your Redis server. So it's either not running, or it's not running on the default location that RedisStore is looking for it (127.0.0.1:6379).
In case of the latter, you can configure the location using the options argument to the RedisStore constructor.
Give this a try.
var express = require('express');
var redis = require("redis");
var session = require('express-session');
var redisStore = require('connect-redis')(session);
var bodyParser = require('body-parser');
var client = redis.createClient();
var app = express();
app.set('views', __dirname + '/views');
app.engine('html', require('ejs').renderFile);
app.use(session({
secret: 'ssshhhhh',
// create new redis store.
store: new redisStore({ host: 'localhost', port: 6379, client: client,ttl : 260}),
saveUninitialized: false,
resave: false
}));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));
app.get('/',function(req,res){
// create new session object.
if(req.session.key) {
// if email key is sent redirect.
res.redirect('/admin');
} else {
// else go to home page.
res.render('index.html');
}
});
app.post('/login',function(req,res){
// when user login set the key to redis.
req.session.key=req.body.email;
res.end('done');
});
app.get('/logout',function(req,res){
req.session.destroy(function(err){
if(err){
console.log(err);
} else {
res.redirect('/');
}
});
});
app.listen(3000,function(){
console.log("App Started on PORT 3000");
});
link : https://codeforgeek.com/2015/07/using-redis-to-handle-session-in-node-js/
You should invoke RedisStore constructor (with ())
app.use(express.session({ secret: "keyboard cat", store: new RedisStore()}));

Nodejs simple socket.io example not working

I've the following Server Side Code:
var express = require('express')
, http = require('http')
, routes = require('./routes')
, io = require('socket.io')
, factory = require('./serverfactory.js');
var app = express();
var server = app.listen(3000);
io = io.listen(server);
io.sockets.on('connection',function(socket){
console.log('new user');
socket.emit('hail','mysimplemsg');
socket.on('customevent',function(msg){
console.log(msg);
});
});
//var app = module.exports = express.createServer();
// Configuration
app.configure(function(){
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(app.router);
app.use(express.static(__dirname + '/public'));
});
app.configure('development', function(){
app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
});
app.configure('production', function(){
app.use(express.errorHandler());
});
// Routes
app.get('/', routes.index);
And this is the client side :
var socket = io.connect('http://localhost:3000');
socket.emit('customevent','work');
socket.on('hail',function(msg){
console.log(msg);
});
I am expecting that my git console outputs new user (which it does) then it should output work (which it does not) then i get a msg in my browser console mysimplemsg (which it does not).
Whats going on why the event at server side that is customevent is not called and why the event at the client side that is hail is not called ?
I believe the issue is that you are emitting customevent from the client before you are connected. Try adding a connect handler and moving your client side emit into it:
var socket = io.connect('http://localhost:3000');
socket.on('hail',function(msg){
console.log(msg);
});
socket.on('connect',function(){
console.log('connected to socket.io server');
socket.emit('customevent','work');
});
If the connect handler is not hit then verify that you are referencing the client side socket.io javascript library correctly (jade syntax):
script(type='text/javascript',src='/socket.io/socket.io.js')
Finally figured it out.
It was working fine on opera but not on chrome and firefox. I found this link in which the guy says to insert this code snippet on the server side.
io.configure('development', function(){
io.set('transports', ['xhr-polling']);
});
It's working fine now.

Socket.emit not working Nodejs Socket.IO

I am just trying to send a simple message from client to server on button Click.
Edit:
When my index.jade loads I use the following code and for creating the socket.io object and then forward it to my Menu_Contoller which in turn assigns the socket object to the Menu_Model.Then whenever the function SendOptionSelectedToServer of Menu_Model.js is called i use the socket object to of Menu_Model.The values in this function are correct.Just don't know why it is not emitting.
index.jade
script(src = '/socket.io/socket.io.js')
script(src = '/javascripts/Menu_Controller.js')
script(src = '/javascripts/Menu_Model.js')
script
var socket = io.connect('http://localhost:3000');
socket.emit('GameType','chutia');
var Menu_Control = Object.create(Menu_Controller);
Menu_Control.Init(socket);
Menu_Controller.js
var Menu_Controller = {
Model : null,
Init:function(socket)
{
this.Model = Object.create(Menu_Model);
this.Model.Init(socket,this);
},
SendOptionSelectedToServer:function(option) <-- called from a view menu which we don't have to care about because value in 'option' are correct.
{
this.Model.SendOptionSelectedToServer(option);
}
};
Menu_Model.js
var Menu_Model = {
Socket : null,
Controller : null,
Init:function(sock,controllerRef)
{
this.Socket = sock;
this.Controller = controllerRef;
},
SendOptionSelectedToServer:function(option)
{
this.Socket.emit(option.type,option.ghostName); <-- this line.
}
};
And here's my complete server side code in app.js.
var express = require('express')
, http = require('http')
, routes = require('./routes')
, io = require('socket.io')
, factory = require('./serverfactory.js');
var app = express();
var server = app.listen(3000);
io = io.listen(server);
io.sockets.on('connection',function(socket){
console.log('new user'); <-- this is printed in the log.
socket.on('GameType',function(msg){
console.log(msg); <-- but this is not.
});
});
//var app = module.exports = express.createServer();
// Configuration
app.configure(function(){
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(app.router);
app.use(express.static(__dirname + '/public'));
});
app.configure('development', function(){
app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
});
app.configure('production', function(){
app.use(express.errorHandler());
});
// Routes
app.get('/', routes.index);
When a new connection occurs it writes new user in the log.But when a call is made using emit from the client side it doesn't write any msg in the console.I've already checked the params at the client side and they are correct. the option.type at the client side will contain GameType.
Why it is not calling the event on the client side ?

Socket.io 'Cannot connect'. Client on different domain/port

I'm having trouble connecting to socket.io with the client being located on a different port, on the same machine.
The client is part of a site run on Apache (port 80) and Nodejs is being run on 8585.
Any idea what I'm doing wrong here?
On the client side, I get the 'Unable to connect Socket.IO' message, with no reason.
Server:
var express = require('express'),
connect = require('connect'),
RedisStore = require('connect-redis')(express),
io = require('socket.io').listen(app),
routes = require('./routes'),
request = require('request');
var app = module.exports = express.createServer();
// Configuration
app.configure(function(){
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(express.session({ secret: "secret", store: new RedisStore}));
app.use(app.router);
app.use(express.static(__dirname + '/public'));
});
app.configure('development', function(){
app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
});
app.configure('production', function(){
app.use(express.errorHandler());
});
io.set('authorization', function(handshakeData, callback) {
console.log('authorization');
callback(null, true);
});
//Socket IO connection
io.sockets.on('connection', function (socket) {
var session = socket.handshake.session;
console.log(session);
});
app.listen(8585);
console.log("Express server listening on port %d in %s mode", app.address().port, app.settings.env);
Client: (run from a site on apache and different domain, but same server).
var sio = io.connect('http://localhost:8585');
sio.socket.on('error', function (reason){
console.error('Unable to connect Socket.IO', reason);
});
sio.on('connect', function (){
console.error('successfully established a working connection \o/');
});
Thank you!
Unless you're running the browser on the same computer as the server, "localhost" in your code will refer to the computer running the browser, not the server. DNS lookups for localhost always resolve to the computer doing the lookup. And even if you're accessing the site on the same computer as the server, unless you're accessing it as "localhost", the browser's security policies will prevent you from talking to localhost.

Resources