Arjun Bajaj
Arjun Bajaj

Reputation: 1962

Save Data on Socket in Socket.IO

I want to save some data on the socket, server side, so whenever the client emits any data to the server, I want that data to be available!

One use case can be storing a token on the socket. When the client is connecting for the first time, it will emit the token, if it has one, or it will show the login page and then the login data will be sent to the server. Whichever one it is, I want to store the token on the server, so that every request after that doesn't need to specify the token.

Later, I'll use RedisStore, so all the data will be accessible all the servers running the app.

My only question is, where do I store the data on the socket so it's associated with that client?

Upvotes: 10

Views: 20165

Answers (3)

Amugae
Amugae

Reputation: 201

I'm suffering from the same question and guessing what's going on with an example code from socket.io on version 4.x

In the example, They use middleware(use function to register a middleware)

namespace.use((socket, next) => {
  // get data from client
  const sessionID = socket.handshake.auth.sessionID;
  const {userId, username} = yourFunction();
  // set socket specific data
  socket.sessionID = sessionID;
  socket.userID = session.userID;
  socket.username = session.username;
  next();
});

Middlewares are executed when a socket is connected with a server.

and you can use the data afterward

note - Socket.IO reference tells use socket.data for this purpose

namespace.on('connection', socket => {
    socket.emit("join", `${socket.username} has been joined`);
})

If you use multiple servers, then you have to keep in mind that the data is only valid for the server

On multiple server environment, You need a single source of data which will be used by socket servers.

namespace.use(async (socket: Socket & { sessionID?: string, userID?: string, username?: string }, next) => {
    const sessionID = socket.handshake.auth.sessionID; // [socket.handshake][4]
// or other [socket related attributes][4]
    if (sessionID) {
        // you have to implement a function to save and retrive session info
        const session = await someFunctionToRetrieveSession(sessionID);
        if (session) {
            socket.sessionID = sessionID;
            socket.userID = session.userID;
            socket.username = session.username;
            return next();
        }
    }
    const username = socket.handshake.auth.username;
    if (!username) {
        return next(new Error("invalid username"));
    }
    socket.sessionID = randomId();
    socket.userID = randomId();
    socket.username = username;
    next();
});

and one more thing as I understood the namespace.use function is called only for the namespace if your client use other namespace then default then default('/') use function will not be called.

//client side
io("/chat");
...

//server side
io.use() // == io.of('/').use() will not be called
io.of('/chat').use() // only will be called

Thanksfully the author of the example implemented a sessionStorage using redis refer to this example code

with this info, I guess socket.io server saves sockets' info in memory and set a property of a socket will be saved and when the socket comes later the server retrives the socket and it's related data. but because it happens on memory so you can't share the info among other servers that's why you have to find a way to share the data with other servers(eg. redis)

Upvotes: 1

Vikneshwar
Vikneshwar

Reputation: 1033

You can save the data on the global variables when you dont want to use any database

var globalVariable = {};

io.sockets.on("connection", function (socket) {

    socket.on("save-client-data", function (clientData) {
          var clientId = clientData.clientId;
          globalVariable[clientId] = JSON.parse(clientHandshakeData);
    });

    socket.on("get-client-data", function (clientId) {

          var clientData =  globalVariable[clientId];
          socket.emit("get-client-data", JSON.stringify(clientData));

    });

});

This worked for my scenario, however I'm not aware of the performance implications.

Upvotes: -1

frederik-b
frederik-b

Reputation: 178

on http://socket.io/#how-to-use scroll to: Storing data associated to a client

use socket.set and socket.get to set and get data asynchronously

Upvotes: 11

Related Questions