如何在 NodeJS 的 HTTP 升级中将请求会话数据传递给 websockets
How to pass request session data to websockets on HTTP upgrade in NodeJS
我正在尝试制作一个使用会话数据的实时聊天,但我似乎无法将会话数据传递给 websockets。我已经尝试了我能找到的所有解决方案,但它们都给我错误。 HTTP 请求通过手动升级事件转发,我可以在其中访问请求对象。但是,我无法从那里到达 req.session(它 returns 未定义,即使我添加数据),所以我无法将它传递给 WebSockets。这是我的服务器端代码:
var express = require('express');
var app = express();
var server = require('http').Server(app);
var session = require('express-session');
var mongoose = require('mongoose');
var ejs = require('ejs');
var path = require('path');
var ws = require('ws');
var wss = new ws.Server({noServer:true});
app.set('views', path.join(__dirname, './views'));
app.use(express.static(path.join(__dirname, './public')));
app.set('view engine', 'ejs');
app.use(session({
saveUninitialized: true,
resave: true,
cookie: {httpOnly: true}
}));
app.set('port', process.env.PORT || 3000);
server.listen(3000, function(){
console.log('listening on 3000')
})
server.on('upgrade', function(req,socket,head){
var pathname = require('url').parse(req.url).pathname;
//req.session returns undefined here, so I can't pass it to my WebSocket handler
if(pathname == '/' || ''){
wss.handleUpgrade(req, socket, head, function(ws){
wss.emit('connection', ws)
})
}
});
app.get('/', function(req,res){
res.render('index')
});
var connections = [];
function broadcast(data, users){
for(let i = 0; i < users.length; i++){
if(users[i].readyState == ws.OPEN){
users[i].send(data)
}
}
}
wss.on('connection', function(connection){
var index = connections.push(connection) - 1;
broadcast('joined!', connections);
connection.on('message', function(msg){
broadcast(msg, connections)
})
connection.on('close', function(){
connections.splice(index, 1);
broadcast('User disconnected', connections)
})
})
这是一个老问题,但为了防止有人遇到同样的问题,我在 expressjs issue.
中找到了解决方案
在上述代码的上下文中,解决方案是首先将 express-session
RequestHandler 函数存储在一个变量中:
const sessionParser = session({
saveUninitialized: true,
resave: true,
cookie: {httpOnly: true}
});
app.use(sessionParser);
...然后在 server.on('upgrade'...
的回调中调用该函数,如下所示:
server.on('upgrade', function(req, socket, head) {
sessionParser(req, {}, () => {
// req.session should be defined at this point
if (condition) {
wss.handleUpgrade(req, socket, head, function(ws){
wss.emit('connection', ws, request);
});
}
});
});
我正在尝试制作一个使用会话数据的实时聊天,但我似乎无法将会话数据传递给 websockets。我已经尝试了我能找到的所有解决方案,但它们都给我错误。 HTTP 请求通过手动升级事件转发,我可以在其中访问请求对象。但是,我无法从那里到达 req.session(它 returns 未定义,即使我添加数据),所以我无法将它传递给 WebSockets。这是我的服务器端代码:
var express = require('express');
var app = express();
var server = require('http').Server(app);
var session = require('express-session');
var mongoose = require('mongoose');
var ejs = require('ejs');
var path = require('path');
var ws = require('ws');
var wss = new ws.Server({noServer:true});
app.set('views', path.join(__dirname, './views'));
app.use(express.static(path.join(__dirname, './public')));
app.set('view engine', 'ejs');
app.use(session({
saveUninitialized: true,
resave: true,
cookie: {httpOnly: true}
}));
app.set('port', process.env.PORT || 3000);
server.listen(3000, function(){
console.log('listening on 3000')
})
server.on('upgrade', function(req,socket,head){
var pathname = require('url').parse(req.url).pathname;
//req.session returns undefined here, so I can't pass it to my WebSocket handler
if(pathname == '/' || ''){
wss.handleUpgrade(req, socket, head, function(ws){
wss.emit('connection', ws)
})
}
});
app.get('/', function(req,res){
res.render('index')
});
var connections = [];
function broadcast(data, users){
for(let i = 0; i < users.length; i++){
if(users[i].readyState == ws.OPEN){
users[i].send(data)
}
}
}
wss.on('connection', function(connection){
var index = connections.push(connection) - 1;
broadcast('joined!', connections);
connection.on('message', function(msg){
broadcast(msg, connections)
})
connection.on('close', function(){
connections.splice(index, 1);
broadcast('User disconnected', connections)
})
})
这是一个老问题,但为了防止有人遇到同样的问题,我在 expressjs issue.
中找到了解决方案在上述代码的上下文中,解决方案是首先将 express-session
RequestHandler 函数存储在一个变量中:
const sessionParser = session({
saveUninitialized: true,
resave: true,
cookie: {httpOnly: true}
});
app.use(sessionParser);
...然后在 server.on('upgrade'...
的回调中调用该函数,如下所示:
server.on('upgrade', function(req, socket, head) {
sessionParser(req, {}, () => {
// req.session should be defined at this point
if (condition) {
wss.handleUpgrade(req, socket, head, function(ws){
wss.emit('connection', ws, request);
});
}
});
});