Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to share sessions with Socket.IO 1.x and Express 4.x?

How can I share a session with Socket.io 1.0 and Express 4.x? I use a Redis Store, but I believe it should not matter. I know I have to use a middleware to look at cookies and fetch session, but don't know how. I searched but could not find any working

    var RedisStore = connectRedis(expressSession);     var session = expressSession({         store: new RedisStore({             client: redisClient         }),         secret: mysecret,         saveUninitialized: true,         resave: true     });     app.use(session);      io.use(function(socket, next) {         var handshake = socket.handshake;         if (handshake.headers.cookie) {             var str = handshake.headers.cookie;             next();         } else {             next(new Error('Missing Cookies'));         }     }); 
like image 311
Mustafa Avatar asked Aug 27 '14 16:08

Mustafa


People also ask

Can you use Socket.IO with Express?

Learn how to install and use Socket.io with Express using the npm package manager, and create a simple chat server to see the basics of how a client and server work together. Requirements: You have an account and are logged into the Scaleway console. You have a Scaleway Instance running Ubuntu Xenial or a later version.

How do I send to a specific Socket.IO client?

To send a message to the particular client, we are must provide socket.id of that client to the server and at the server side socket.io takes care of delivering that message by using, socket.broadcast.to('ID'). emit( 'send msg', {somedata : somedata_server} ); For example,user3 want to send a message to user1.

How many messages per second can Socket.IO handle?

Both server and client node processes use 95-100% of a CPU core each. So pure throughput looks ok. I can emit 100 messages per second to 100 local clients at 55% CPU usage on the server process.


Video Answer


2 Answers

The solution is surprisingly simple. It's just not very well documented. It is possible to use the express session middleware as a Socket.IO middleware too with a small adapter like this:

sio.use(function(socket, next) {     sessionMiddleware(socket.request, socket.request.res, next); }); 

Here's a full example with express 4.x, Socket.IO 1.x and Redis:

var express = require("express"); var Server = require("http").Server; var session = require("express-session"); var RedisStore = require("connect-redis")(session);  var app = express(); var server = Server(app); var sio = require("socket.io")(server);  var sessionMiddleware = session({     store: new RedisStore({}), // XXX redis server config     secret: "keyboard cat", });  sio.use(function(socket, next) {     sessionMiddleware(socket.request, socket.request.res || {}, next); });  app.use(sessionMiddleware);  app.get("/", function(req, res){     req.session // Session object in a normal request });  sio.sockets.on("connection", function(socket) {   socket.request.session // Now it's available from Socket.IO sockets too! Win! });   server.listen(8080); 
like image 162
Epeli Avatar answered Nov 16 '22 01:11

Epeli


Just a month and a half ago I dealt with the same problem and afterwards wrote an extensive blog post on this topic which goes together with a fully working demo app hosted on GitHub. The solution relies upon express-session, cookie-parser and connect-redis node modules to tie everything up. It allows you to access and modify sessions from both the REST and Sockets context which is quite useful.

The two crucial parts are middleware setup:

app.use(cookieParser(config.sessionSecret)); app.use(session({     store: redisStore,     key: config.sessionCookieKey,     secret: config.sessionSecret,     resave: true,     saveUninitialized: true })); 

...and SocketIO server setup:

ioServer.use(function (socket, next) {     var parseCookie = cookieParser(config.sessionSecret);     var handshake = socket.request;      parseCookie(handshake, null, function (err, data) {         sessionService.get(handshake, function (err, session) {             if (err)                 next(new Error(err.message));             if (!session)                 next(new Error("Not authorized"));              handshake.session = session;             next();         });     }); }); 

They go together with a simple sessionService module I made which allows you to do some basic operations with sessions and that code looks like this:

var config = require('../config');  var redisClient = null; var redisStore = null;  var self = module.exports = {     initializeRedis: function (client, store) {         redisClient = client;         redisStore = store;     },     getSessionId: function (handshake) {         return handshake.signedCookies[config.sessionCookieKey];     },     get: function (handshake, callback) {         var sessionId = self.getSessionId(handshake);          self.getSessionBySessionID(sessionId, function (err, session) {             if (err) callback(err);             if (callback != undefined)                 callback(null, session);         });     },     getSessionBySessionID: function (sessionId, callback) {         redisStore.load(sessionId, function (err, session) {             if (err) callback(err);             if (callback != undefined)                 callback(null, session);         });     },     getUserName: function (handshake, callback) {         self.get(handshake, function (err, session) {             if (err) callback(err);             if (session)                 callback(null, session.userName);             else                 callback(null);         });     },     updateSession: function (session, callback) {         try {             session.reload(function () {                 session.touch().save();                 callback(null, session);             });         }         catch (err) {             callback(err);         }     },     setSessionProperty: function (session, propertyName, propertyValue, callback) {         session[propertyName] = propertyValue;         self.updateSession(session, callback);     } }; 

Since there is more code to the whole thing than this (like initializing modules, working with sockets and REST calls on both the client and the server side), I won't be pasting all the code here, you can view it on the GitHub and you can do whatever you want with it.

like image 45
tkit Avatar answered Nov 16 '22 00:11

tkit