Paweł Chochura
Paweł Chochura

Reputation: 21

How to access client socket id from the http request?

Recently I've stumbled upon an interesting problem.

The goal was to create a communication between a browser client and my expressJs server via web sockets to quickly show changes made on the another client. Also I'm using a standard http connection to communicate with my database.

The problem is that I need to generate an individual link for every user (based on their cookie I've created) but on the server only the last one is valid. So every person displaying invalid link should see something like Please refresh the page. To achieve that I've emitted event linkExpired globally which marked sender's link as expired as well.

I can't access a client socket (which would solve my problem) because I don't want to store them after establishing connection (as was proposed here for example). In my opinion it isn't an elegant solution.

Any help would be appreciated.

Upvotes: 1

Views: 704

Answers (1)

Paweł Chochura
Paweł Chochura

Reputation: 21

After some time I've come up with a different approach. Maybe creating a cookie storing id of the client socket after establishing connection would be sufficient. So I did that... And I've realised that socket.io already have a cookie containing a socket id.

The only thing to do was to use cookie-parser with express:

const cookieParser = require('cookie-parser');
require('express')().use(cookieParser());

After that I had an access to all the cookies passed to all http requests which allowed me to filter sockets based on the id and avoid sending an event to the sender.

const io = require("socket.io").io;
Object.keys(io.sockets.sockets).forEach((_socketId) => {
  if (req.cookies.io !== _socketId) {
    io.to(_socketId).emit('linkExpired');
  }
});

Please pay attention to the fragment where I used a req.cookies.io as an id of the socket. I've noticed that socket.io is using cookie named io to store current id of the client socket.

And on the client side I could achieve showing banner about expiration as follows:

import socketIOClient from "socket.io-client";
const io = socketIOClient(process.env.REACT_APP_URL);
io.on('linkExpired', () => {
  setLink('Refresh the page');
});

Also I had to remember to pass options to the fetch method to send cookies:

fetch(`${process.env.REACT_APP_URL}/api/main`, {
  credentials: 'include'
});

I've spend too much time with this so I hope somebody would benefit from this explanation.

Upvotes: 1

Related Questions