95

How to best send additional data upon socket connection?

Client:

socket.on('connect',function(){ 
//I'd like set some values and pass them up to the node server.
});

Node.js Server:

io.on('connection', function(client){
//I'd like to get the data here.
});

For example sending a user name or email address etc.

ROMANIA_engineer
  • 54,432
  • 29
  • 203
  • 199
Dan
  • 2,649
  • 4
  • 26
  • 22

7 Answers7

80

You should send your data either in connect or on create:

var s = io('http://216.157.91.131:8080/', { query: "foo=bar" });
s.connect();

var c = io.connect('http://216.157.91.131:8080/', { query: "foo=bar" });

With the new version of socket.io, on server is where the things have been changed:

var io = require('socket.io')(server);

io.use(function(socket, next) {
  var handshakeData = socket.request;
  console.log("middleware:", handshakeData._query['foo']);
  next();
});
Miquel
  • 8,339
  • 11
  • 59
  • 82
  • 1
    I've seen other people say to use `socket.request.query`, but that does not work for me on socket.io v1.7.2. Definitely have to use `socket.request._query`. – kellen Dec 30 '16 at 01:55
  • Why there is no documentation on this ? https://github.com/socketio/socket.io-client/blob/master/docs/API.md#iourl-options – tu4n Feb 06 '17 at 08:13
  • 4
    For socket.io v1.7.3, I had to use `socket.handshake.query` (via [this answer](http://stackoverflow.com/questions/13745519/send-custom-data-along-with-handshakedata-in-socket-io)). – Galen Long Feb 23 '17 at 19:02
  • No way to send more than one parameter? Does anyone knows the syntax? Fox exemple `{ query: "foo=bar", "bar=foo" }` won't work. – Adry Jul 06 '18 at 12:33
  • @Adry that does not seem a valid JSON object, did you try with valid one? – Miquel Jul 07 '18 at 20:39
  • [If you copy the answer from the thread](https://stackoverflow.com/questions/13745519/send-custom-data-along-with-handshakedata-in-socket-io/13940399#13940399) I linked, at least name and link the author and his answer. – Daniel W. Jul 11 '18 at 08:11
  • @DanFromGermany I think that the link you provided copied the solution from my answer, don't you think so? https://stackoverflow.com/posts/13940399/revisions, see revision date. Anyway I'm not going to claim copyright rights... The important here is that it helps others with same problem, don't you think soo to? – Miquel Jul 12 '18 at 09:53
  • 2
    @Miquel solved using `{query: 'var1='+foo+'&var2=bar'` – Adry Jul 28 '18 at 08:57
  • @Miquel no, you copied the answer, the IP in his initial answer from 2012 is exactly the same as the one you used, you copied the code. Please link the original author of the code you use to leech reputation from his work. – Daniel W. Oct 04 '18 at 08:49
  • @DanFromGermany I've not copied the answer anyway I have no problems to give attribution if this would be the case – Miquel Oct 04 '18 at 09:21
35

I have a different approach - emit an event right after connecting, with the data:

socket.on('connect',function(){ 
    // Send ehlo event right after connect:
    socket.emit('ehlo', data);
});

io.on('connection', function(client){
    // Receive ehlo event with data:
    client.on('ehlo', function(data) {
    });
});

You can hold a variable/object, and say, when there is no ehlo event with data, the other events are ignored until ehlo is sent.

If this does not satisfy, you can send data right when connecting, I won't copy the code but it is in this answer: https://stackoverflow.com/a/13940399/1948292

Community
  • 1
  • 1
Daniel W.
  • 31,164
  • 13
  • 93
  • 151
  • 6
    This is a good approach for passing data to identify a user, like an access token. You might also want to handle `socket.on('reconnect', …)` if your server needs data it might stop persisting after a disconnect. – Iain Collins Jun 18 '17 at 21:53
  • I wanted to send some data to server every time the user got reconnected. This way is fantastic. – Alireza Bijantabar Feb 05 '23 at 16:08
16

The connection events get fired as soon as the TCP connection is established. There's no way to send anything in between.

What you can do is to simply take the first message send by the server and put the data in that message. I'd strongly suggest to roll some thin protocol for this, so you would have multiple types of messages and use those to determine how the code should process the data.

This would be more extendable too, since it's fairly easy to come up with a generic architecture for that. If you want to wait for the userdata to come in first you can simply add some state to your connections.

Ivo Wetzel
  • 46,459
  • 16
  • 98
  • 112
  • Hey Ivo, Thanks a lot for getting back to me. Can you give me a bit more detail on how to achieve what you're saying? Thanks again! – Dan Jan 20 '11 at 14:24
  • Basically, I have a working chat app, where you can send to specific clients. The issue is that I have no way of matching up the sessionId with the user name. So, if you and I were chatting, instead of saying "Dan" and "Ivo" it'd show the client id's. – Dan Jan 20 '11 at 14:30
  • Can you give me a bit more information about your architecture / code? Where do the IDs come from and where do the names come from? Can't the app not just do a request to the server and ask for the usernames that are associated with the IDs? – Ivo Wetzel Jan 20 '11 at 14:59
  • username would come from a db(i.e. after a user logs in). ids come from client.sessionId. To be honest, I implemented my solution based on an answer you gave to a similar question. I add clients as they come in(on connect) to an array and remove them on disconnect. I pass the client ids down to the client on message and connect. It's working really well, so thanks a lot for that other post:) So, are you saying I should make a call to the db and attempt to match up the sessionid to a field in the db? – Dan Jan 20 '11 at 15:09
  • @Dan: Just store your user session in Redis and have the key stored in a cookie in the users browser. Fetch the cookie on socket connect and send it back to server. – Shripad Krishna Jan 20 '11 at 18:10
  • @Shripad: Sounds like a good idea, can I do this without the use of Redis? – Dan Jan 20 '11 at 18:28
  • Hey guys, I ended up setting the data I needed in a cookie and getting within the connect event in socket.io using client.request.headers.cookie Thanks so much for everyone's input :) – Dan Jan 21 '11 at 01:29
  • @Dan be careful while using client.request.headers.cookie as that can lead to race conditions. The 'headers' is within the request handler and not attached to the 'client' object directly. The request handler is your regular http request (one from http.Server/express' app) so it always points to the last accessed user. So if you have 2 users simultaneously log in, it will always point to the last logged in user. So if you send messages from the 1st user it usually ends up showing that it was received from the 2nd user. :) – Shripad Krishna Jan 21 '11 at 02:12
10

this is my code on socket version 2.1.1

//client side
var socket = io.connect(window.location.origin,{query:'loggeduser=user1'});

// server side
io.socket.on('connection', function (socket) {
    console.log("loggeduser => " +  socket.handshake.query.loggeduser);
});
Manoj Rana
  • 3,068
  • 1
  • 24
  • 34
8

this my code for sending query data to nodejs and server.io server client

var socket = io.connect(window.location.origin,{query:'loggeduser=user1'});

io.sockets.on('connection', function (socket) {
    var endp = socket.manager.handshaken[socket.id].address;
    console.log("query... " +  socket.manager.handshaken[socket.id].query.user);
});

query...user1

Daniel W.
  • 31,164
  • 13
  • 93
  • 151
mukut
  • 130
  • 3
  • 3
5

I found the answer located here really helpful in this regard: Send custom data along with handshakeData in socket.io?

Also brushing up on the following documentation helps explain ways to tie variables to the handshake object which can be accessed from the socket object during the connection: https://github.com/LearnBoost/socket.io/wiki/Authorizing#global-authorization

Community
  • 1
  • 1
Art Geigel
  • 1,915
  • 3
  • 22
  • 24
0

I'm assuming you will use SSL.

Using querystrings to send sensitive data is not a good security practice (why?). I think that if you need to send non-sensitive data, then Miquel answer is the fastest and more easy one, but if sensitive data is what you need to send, then something like Daniel W. is the best approach to take.

For an authentication approach, you can take a look at this github project (socketio-auth) which, beyond the fact that it is currently with no maintenance, can give you a good idea of how to deal with the problem.

oriuken
  • 653
  • 3
  • 7
  • 19