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'.
开发者_JS百科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
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.
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'
// Declare an Express app
const app = express()
// Declare an HTTP server for the app
const server = http.createServer(app)
// Initialize *express-session* and use it as a middleware
const sessionHandler = session({
saveUninitialized: false,
secret: 'my little secret',
resave: false
})
app.use(sessionHandler)
// Define a builder for message handler with WebSocket and Session as context
const onMessage = (ws, session) => (message) => {
// create a handler for message given the ws and session
}
// Create a *WebSocketServer* without an attached HTTP server
const wsServer = new WebSocketServer({ noServer: true })
// define what to do on a 'connection' event
wsServer.on('connection', (ws, session) => {
ws.on('message', onMessage(ws, session))
})
// 'upgrade' event comes when the browser ask for a WebSocket
server.on('upgrade', (req, socket, head) => {
// we call the *sessionHandler* to retrieve/create the session
sessionHandler(req, {}, () => {
// ask the *WebSocketServer* to manage the upgrade
wsServer.handleUpgrade(req, socket, head, (ws) => {
console.log(req.session)
// emit a 'connection' event (handler above) with the create WebSocket and current session
wsServer.emit('connection', ws, req.session)
})
})
})
精彩评论