Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ExpressJS & Websocket & session sharing

I'm trying to make a chat application based on Node.js. I'd like to force websocket server (ws library) to using ExpressJS session system. Unfortunately, I've got stuck. MemoryStore hashes used to get sessions' data are different than session IDs in cookies. Could somebody explain me what I'm doing wrong?

Websocket server code part:

module.exports = function(server, clients, express, store) {   server.on('connection', function(websocket) {     var username;      function broadcast(msg, from) {...}      function handleMessage(msg) {...}      express.cookieParser()(websocket.upgradeReq, null, function(err) {         var sessionID = websocket.upgradeReq.cookies['sid'];              //I see same value in Firebug         console.log(sessionID);              //Shows all hashes in store             //They're shorter than sessionID! Why?         for(var i in store.sessions)             console.log(i);          store.get(sessionID, function(err, session) {                 websocket.on('message', handleMessage);                  //other code - won't be executed until sessionID in store                  websocket.on('close', function() {...});         });     }); }); } 

store object definition:

var store = new express.session.MemoryStore({     reapInterval: 60000 * 10 }); 

app configuration:

app.configure(function() {     app.use(express.static(app.get("staticPath")));     app.use(express.bodyParser());     app.use(express.cookieParser());      app.use(express.session({         store: store,         secret: "dO_ob",         key: "sid"     })); }); 

Part of main code:

var app = express(); var httpServer = http.createServer(app); var websocketServer = new websocket.Server({server: httpServer}); httpServer.listen(80); 

Sample debugging output:

- websocket.upgradeReq.headers.cookie "sid=s%3A64a%2F6DZ4Mab8H5Q9MTKujmcw.U8PJJIR%2BOgONY57mZ1KtSPx6XSfcn%2FQPZ%2FfkGwELkmM" - websocket.upgradeReq.cookies["sid"] "s:64a/6DZ4Mab8H5Q9MTKujmcw.U8PJJIR+OgONY57mZ1KtSPx6XSfcn/QPZ/fkGwELkmM" - i "64a/6DZ4Mab8H5Q9MTKujmcw" 
like image 813
skorczan Avatar asked Aug 29 '12 16:08

skorczan


People also ask

What is ExpressJS used for?

Express is a node js web application framework that provides broad features for building web and mobile applications. It is used to build a single page, multipage, and hybrid web application. It's a layer built on the top of the Node js that helps manage servers and routes.

What is the difference between NodeJS and ExpressJS?

Node. js is a platform for building the i/o applications which are server-side event-driven and made using JavaScript. Express. js is a framework based on Node.

Is ExpressJS outdated?

Express has not been updated for years, and its next version has been in alpha for 6 years. People may think it is not updated because the API is stable and does not need change. The reality is: Express does not know how to handle async/await .

Is ExpressJS an API?

ExpressJS is one of the most popular HTTP server libraries for Node. js, which by default isn't as friendly for API development. Using Express, we simplify API development by abstracting away the boilerplate needed to set up a server, which makes development faster, more readable and simpler.


2 Answers

I found this works for me. Not sure it's the best way to do this though. First, initialize your express application:

// whatever your express app is using here... var session = require("express-session"); var sessionParser = session({     store: session_store,     cookie: {secure: true, maxAge: null, httpOnly: true} }); app.use(sessionParser); 

Now, explicitly call the session middleware from the WS connection. If you're using the express-session module, the middleware will parse the cookies by itself. Otherwise, you might need to send it through your cookie-parsing middleware first.

If you're using the websocket module:

ws.on("request", function(req){     sessionParser(req.httpRequest, {}, function(){         console.log(req.httpRequest.session);         // do stuff with the session here     }); }); 

If you're using the ws module:

ws.on("connection", function(req){     sessionParser(req.upgradeReq, {}, function(){         console.log(req.upgradeReq.session);         // do stuff with the session here     }); }); 

For your convenience, here is a fully working example, using express, express-session, and ws:

var app = require('express')(); var server = require("http").createServer(app); var sessionParser = require('express-session')({     secret:"secret",     resave: true,     saveUninitialized: true }); app.use(sessionParser);  app.get("*", function(req, res, next) {     req.session.working = "yes!";     res.send("<script>var ws = new WebSocket('ws://localhost:3000');</script>"); });  var ws = new require("ws").Server({server: server}); ws.on("connection", function connection(req) {     sessionParser(req.upgradeReq, {}, function(){         console.log("New websocket connection:");         var sess = req.upgradeReq.session;         console.log("working = " + sess.working);     }); });  server.listen(3000); 
like image 200
Azmisov Avatar answered Oct 02 '22 13:10

Azmisov


I was able to get this working. I think you need to specify the secret on cookieParser instead of session store.

Example from my app:

var app = express(); var RedisStore = require('connect-redis')(express); var sessionStore = new RedisStore(); var cookieParser = express.cookieParser('some secret');  app.use(cookieParser); app.use(express.session({store: sessionStore}));   wss.on('connection', function(rawSocket) {    cookieParser(rawSocket.upgradeReq, null, function(err) {     var sessionID = rawSocket.upgradeReq.signedCookies['connect.sid'];     sessionStore.get(sessionID, function(err, sess) {       console.log(sess);     });   });  }); 
like image 26
StereoSteve Avatar answered Oct 02 '22 14:10

StereoSteve