'Node.js + Express.js (Connect) - Accessing Session from 'upgrade' event

I'm trying to access the session object from an 'upgrade' event fired by a Node.js server using the Express.js framework. I have set up Session support correctly and can access it from the standard .get .post .put and .delete methods eg.

app.get('/', function(req, res) {
    req.session.test = 'Hello world'; // Works fine
    res.render('index');
});

But if I hook up an on 'upgrade' event on the server like so:

app.on('upgrade', function(req, socket) {
    var message = req.session.test; // Doesn't work
});

I can't access the session object. As far as I'm aware, the Connect Session middleware only hooks up the session for the get/post/put/delete methods, but not for custom events such as 'upgrade'.

FYI, an 'upgrade' event is issued from a client during a WebSocket handshake, I'm trying to access the session from the initial WebSocket handshake. The session cookie is definitely there in the HTTP headers during the handshake eg:

app.on('upgrade', function(req, socket) {
    var cookieHeader = req.headers['cookie'];
    console.log(cookieHeader);
});

...will output the Connect session cookie. Is there perhaps a way to build up the session object manually using the raw session cookie token?


Update: Been speaking to to some people on the node.js IRC chatroom, apparently this is either very difficalt or impossible. The Connect middleware isn't exposed to custom/unusual events such as 'upgrade'. They said to raise an issue in Github, so here it is:

https://github.com/senchalabs/connect/issues/342



Solution 1:[1]

Since you don't have access to the response object, you should be able to look up the session object by getting the session store and calling get(session_id, callback) with the session_id you get from the cookie. You also may be able to actually call the normal session middleware function if the req object you have is linked to the response via req.res, which express.js will do for you, but if this is a raw node.js event, then that connection might not have been made at this point. When you create the middleware, you'll have to create the session Store instance manually and keep a reference to it, then pass it to the session middleware factory function in the options object.

Solution 2:[2]

If you are using express-session, this should help :

import session from 'express-session'
import express from 'express'

import http from 'http'
import { WebSocketServer } from 'ws'

const app = express()
const server = http.createServer(app)


const sessionHandler = session({
  saveUninitialized: false,
  secret: 'my little secret',
  resave: false
})
app.use(sessionHandler)

const wsServer = new WebSocketServer({ noServer: true })
wsServer.on('connection', (ws, sessid) => {
  ws.on('message', sessionAwareProxy.onMessage(ws, sessid))
})

server.on('upgrade', (req, socket, head) => {
  sessionHandler(req, {}, () => {
    wsServer.handleUpgrade(req, socket, head, (ws) => {
      console.log(req.session)
      wsServer.emit('connection', ws, req.session)
    })
  })
})

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Peter Lyons
Solution 2 Nicocube