session icon indicating copy to clipboard operation
session copied to clipboard

How might one go about accessing a session value inside of a socket.io instance?

Open PanicIsReal opened this issue 9 years ago • 8 comments

Question is in the title, just wondering if there is a function like session.getSesh(seshid).userid or something

PanicIsReal avatar Jan 28 '16 08:01 PanicIsReal

@Gacnt - Did you have any luck figuring this out? I'm trying to figure out the best way to use session storage when using the ws websocket library.

hedgerh avatar Jun 30 '16 08:06 hedgerh

Well, I've made it work in this way:

import http from 'http';
import socketIO from 'socket.io';
import koa from 'koa';
import session from 'koa-session';

// your koa setup
const app = new koa();
app.keys = ['my-secret'];
app.use(session({}, app));

// socket.io binding
app.server = http.createServer(app.callback());
app.io = socketIO(app.server);

// socket.io middleware to set socket.session
app.io.use(function (socket, next) {
  let error = null;
  try {
    // we manually create a koa context, so we can use it to retrieve the session
    let context = app.createContext(socket.request, socket.response);
    socket.session = context.session;
  } catch (err) {
    error = err;
  }
  return next(error);
});

In this implementation, the main difference with cxt.session is that socket.session is "static": it is not a getter but it is just the returned value (something to not worry about with cookies).

albertogasparin avatar Jun 28 '17 09:06 albertogasparin

This is not working for me, TypeError: Cannot read property 'url' of undefined, some idea?

marceloch2 avatar Oct 26 '17 14:10 marceloch2

@albertogasparin it's working! Thank you, mate, i lost a lot of time before found your solution! :heart:

epszaw avatar Nov 12 '17 12:11 epszaw

it does NOT work (ctx.session is undefined) if I configure a session store e.g.

(Knowing that, the session store is working fine with my Rest API)

sessionConfig.store = new SessionStoreImpl(); // redis
app.use(session(sessionConfig, app));

Thanks very much for any ideas?

thanhlq avatar Jul 24 '18 06:07 thanhlq

@thanhlq I've found a way to fix this. here is some code:

app.io.use(async function (socket, next) { // making io middleware async, not sure it's good idea
// ... 
try {
// ...
 const ctx = app.createContext(socket.request, new http.OutgoingMessage())
// calling initFromExternal to fetch session data from external store, if you are using other than koa-session module you have to find how to do this. 
 await ctx.session._sessCtx.initFromExternal()
 // now ctx.session is full of data
}
// ...
})

lastHelp avatar Jan 22 '20 16:01 lastHelp

@lastHelp Your solution works great, all other "workarounds" involves too much hacking to get the session, but using .initFromExternal reuses everything already configured.

One note regarding types, I had to change new http.OutgoingMessage() to new http.ServerResponse(socket.request) or you will get "Argument of type 'OutgoingMessage' is not assignable to parameter of type 'ServerResponse'."

ejose19 avatar Jan 23 '20 03:01 ejose19

Hi everyone!

Just wanted to build on the various solutions presented here to offer something that is almost equivalent to the official documentation for integrating express-session into socket.io as seen here. Idea is to just re-use the existing session middleware to populate the newly created context and to attach the session to "socket.request". Currently unsure about whether using async'ed socket.io middleware is supported or not, the docs are a bit unclear.

import http from 'http';
import socketIO from 'socket.io';
import koa from 'koa';
import session from 'koa-session';

// your koa setup
const app = new koa();
app.keys = ['my-secret'];

const sessionMiddleware = session({}, app);
app.use(sessionMiddleware);

// socket.io binding
app.server = http.createServer(app.callback());
app.io = socketIO(app.server);

// socket.io middleware to set socket.session
app.io.use(function (socket, next) {
  let error = null;
  try {
    // we manually create a koa context, so we can use it to retrieve the session
    let context = app.createContext(socket.request, socket.response);
    await sessionMiddleware(context, next);
    socket.request.session = context.session;
  } catch (err) {
    error = err;
  }
  return next(error);
});

ghost avatar Sep 09 '20 14:09 ghost