1
votes

I have tried so many things to be able to grab the express session variables inside the socket.io connection in Node.JS, but keep failing. I've noticed that whenever I use the session middleware the right session isn't used instead it created 3 other useless sessions (unless saveUninitialized: true, if false then it doesn't save it, but still it uses the wrong session of course).

I tried:

  • Using cookie-parser.
  • Storing session in file.
  • express-socket.io-session.
  • redis
  • and a few other things that I can't remember anymore.

But it all comes down to one thing - the socket doesn't use the same session as the express request (req.session) instead it creates 3 other sessions and also keeps on creating new ones upon socket activity.

Setup of client socket.io inside App component:

componentWillMount() {
    let socket = io("http://localhost:5000");
    this.setState({socket});
    socket.emit("test"); // This actually returns the correct session.
  }

Example of the way I send AJAX in ReactJS:

fetch('http://localhost:5000/home/userinfo', {
  method: 'GET',
  credentials: 'include',
  headers: {
    'Accept': 'application/json',
    'Content-Type': 'application/json',
  },
}).then(function(response) {
  return response.json();
}).then(function(data) {
  if (data.login) {
    self.setState({username: data.login});
  }
  else {
    self.props.history.push("/login");
  }
});

express session setup:

var sessionMiddleware = session({
  store: new sessionFileStore({ path: './sessions' }),
  secret: 'nothingspecial',
  maxAge: new Date(Date.now() + 3600000),
  resave: true,
  saveUninitialized: false
});
app.use(sessionMiddleware);

socket.io connection:

const server = app.listen(port, () => console.log(`Listening on port ${port}`));

const io = require('socket.io').listen(server);
io.use(function(socket, next) {
  sessionMiddleware(socket.handshake, {}, next); 
});
io.on('connection', function(socket) {
  console.log('a user connected');
  socket.on('disconnect', function() {
    console.log('user disconnected');
  });
  socket.on('test', function() {
    console.log(socket.handshake.session);
    // Returns different session than when using app.get and then req.session for example
  });
});

Also some other app.use that might be worth posting here:

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(function (req, res, next) {
  res.setHeader('Access-Control-Allow-Origin', 'http://localhost:3000');
  res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
  res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');
  res.setHeader('Access-Control-Allow-Credentials', true);
  next();
});

Would gladly appreciate help as I've wasted so much time already trying to figure this out.

Edit: I noticed that upon page refresh when I socket.emit straight from where the connection is started (App component) it actually grabs the right session. I tried to create some functions inside the App component, but still when I pass the function into a different component and run the props function it creates a new session.

How I pass the socket:

<Route path="/home" render={(props) => <Home {...props} socket={this.state.socket} />} />
1

1 Answers

0
votes

I decided to just switch from socket.io to standard WebSocket(ws) which also seems to fit my needs a lot better. With ws sharing the session works very well you just need to force page refresh after setting a session variable.

This helped: ExpressJS & Websocket & session sharing

Also remember that there is no such this as req.upgradeReq any more. The req is passed on wss.connection like so:

wss.on('connection', function(ws, req) {
//req.upgradeReq = req;
});