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"
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.
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.
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 .
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.
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);
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); }); }); });
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With