SupimpaAllTheWay
SupimpaAllTheWay

Reputation: 1478

Nodejs - how to get url parameters using socket.io?

I've been studying Nodejs and Socket.io, the problem is I'm struggling on how to get an url parameter (www.example.com/sample/:sampleid) and use it on my socket connection.

Here's an example:

var roomname;
var username;
app.get('/room/:roomname/user/:username', function(req, res){
    var room = {
        username: req.params.username,
        roomname: req.params.roomname
    };
    roomname = room.roomname;
    username = room.username;
    res.render('room', room);
});

var users  = {};

io.sockets.on('connection', function (socket) {
    socket.username = username;
    socket.room = roomname;
    users[username] = username;
    console.log("joining room: " + roomname)
    socket.join(roomname);
    console.log("emiting to room: " + roomname)
    socket.broadcast.to(roomname).emit('newUser', username);

});

I'm simply storing the name on roomname and using it inside io.sockets.on, but I think that's a hack and should be a better way to achieve this...

What's a good way to solve this kind of situations?

Upvotes: 0

Views: 8655

Answers (3)

Jonathan Schneider
Jonathan Schneider

Reputation: 59

I had the same question and arrived at a different solution, where I pass the parameters at the time of connection.

//it's my connection in client side
let socket = socketio(`http://localhost:4444?user=${uuid}&room=${room}`); 
// where UUID is my user ID and room id

So on the server side we can get that parameters like below

let userUUID = socket.handshake.query.user;
let roomId = socket.handshake.query.room;

The good thing is that when connection is lost you do not depend on the fact that the client will call your custom connection event again, you can put your logic into the default io.on('connection',);

More info here https://socket.io/docs/server-api/#socket-handshake

Upvotes: 2

CherryNerd
CherryNerd

Reputation: 1314

Since you're using res.render and you're already passing room as a data parameter, I think it's best to make use of that and do something like this (I use EJS in my example since I'm used to that):

Client:

<script>socket.emit('join', {room: '<%- room.roomname %>' });</script>

Server:

io.on('connection', (socket) => {
    socket.room = '';

    socket.on('join', (msg) => {
        socket.room = msg.room;
    });
});

Otherwise it could be an idea to emit document.location.pathname, but then you'd have to parse the path yourself to get the roomname out of it.

EDIT:
What you're doing at the moment is actually very dangerous, because of the following scenario: User 1 opens the page, "global" variables username and room get set (let's set them both to foo for now), but user 1 has slow internet, so it takes some time to load and for socket.io to connect.

Now User 2 opens the page, the "global" variables username and room are changed to the new values (let's use bar), before user 1 opens up the socket.io connection.

Now User 1 and User 2 connect with socket.io, but since user 2 has faster internet than user 1, var username and var roomname are now both set to value bar even though User 1 has username and roomname foo.

Just a heads up.

Upvotes: 1

Ahmed Kesha
Ahmed Kesha

Reputation: 830

socket can emit any event because socket object is EventEmitter so that it can fire(emit) event in any time and on anther side server can listen to this events by .on function

example 
socket.emit('join',{name:"ahmed"})

server
io.sockets.on('join',function(data){
    console.log(data.name)
})

Upvotes: 1

Related Questions