socket.io / parameters on connection

87,717

Solution 1

Yes, there is.

1) query is like GET parameters, so replace "param:value" with "param=value" (if you want to pass multiple parameters, do it as you usually do with URL: param=value&some_other_param=test)

2) There is an easier and more reliable (because there is no risk to access an undefined property of handshaken object) way to get query parameter inside connection handler:

console.log(socket.handshake.query.param);

Edit:

After learning your full code I guess I figured out what causes the problem. The problem is that you probably misunderstood the main idea of Socket.IO namespaces.

I guess you have multiple Socket.IO connections (io.connect calls) within one page, right? Usually a single connection is enough. Your mistake is that you call io.connect on mouse event, but you should call in once on document.ready, and then just emitting.

Take a look at the following code (client side):

$(document).ready(function() {
    var socket = io.connect('', {query: 'name=something'});

    // [...]

    socket.on('some_event_from_server', function(data, cb) {});

    // [...]

    $('#someButton').click(function() {
        socket.emit('markers_add', {some: 'data'});  //send `markers_add` message to server within main namespace
    });

    $('#someOtherButton').click(function() {
        socket.emit('icon_sets_add', {some: 'thing'}, function(response) {
            //server may response to this request. see server side code below
        });
    });
});

Server side code:

io.on('connection', function(socket) {  //connection handler of main namespace
    socket.on('markers_add', function(data) { /* ... */  });
    socket.on('icon_sets_add', function(data, cb) {
        // do something
        cb({some: 'response'});
    });

    // [...]

    socket.emit('some_event_from_server', {});  //server sends a message to a client

    //BTW, now it should be OK:
    console.log(socket.handshake.query.name);
});

If you have one namespace it should work. I don't know actually if it was a bug of Socket.IO or a result of improper usage of namespaces, but modifying code to make just one namespace should do the trick. So in your case you don't have to pass query parameters when handshaking at all. Actually you have to use query parameter if you want to make your app more secure. See http://wlkns.co/node-js/socket-io-authentication-tutorial-server-and-client/ (for Socket.io 0.9)

Hope my answer helps you. Good luck!

Solution 2

Here's what I've done.

Client

var socket = io.connect('http://localhost:8890',{ query: "foo=bar" });

Server

io.on('connection', function (socket) {
  console.log(socket.handshake.query['foo']);
}); 

Solution 3

In 2021 (socket.io version 4)

// client.js

const socket = io('https://195.174.3.104:3000', { query: { myParam: 'myValue' } });
// server.js

io.on("connection", (socket) => console.log(socket.handshake.query.myParam);  // myValue

Source: https://socket.io/docs/v4/client-initialization/#query

Share:
87,717
ceadreak
Author by

ceadreak

Php and node.js developer

Updated on August 31, 2021

Comments

  • ceadreak
    ceadreak over 2 years

    In my node.js / Express.js app, I need to pass parameters with the socket.io connection (saw that in another post).

    On client side, I have something like :

    edit

    var socket = io.connect('/image/change', {query:"name=my_img_name"});
    var siofu = new SocketIOFileUpload(socket);
    
    siofu.listenOnInput(document.getElementById("change_image_inpt"));
    

    On server side :

    edit

    io.of('/image/change')
      .on('connection', function (socket) {
      console.log('log input param : ' + socket.handshake.query.name);
    });
    

    But nothing in the console.

    Is there another way to achieve that ?

    edit2

    This is the full code for client :

    $(document).ready(function() {
    
    // icon_action_modal
    $('.icon_actions').on('click', function() {
        // set icon preview
        $('#icon_action_modal_icon_preview').html('<img src="/upload/icon/' + $(this).data('icon') + '.png" />');
    
        // set icon to delete
        $('#icon_name').val($(this).data('icon'));
    
        // set Change icon socket
        var socket = io.connect('/icon_sets/change', {query:"name=my_img_name"});
        var siofu = new SocketIOFileUpload(socket);
    
        siofu.listenOnInput(document.getElementById("change_icon"));
    
        // Do something when a file is uploaded
        siofu.addEventListener("complete", function () {
            $('.overlay').hide();
        });
    
        // display loader window
        socket.on('displayOverlay', displayOverlay);
    
        // display
        socket.on('displayIconImage', function (data) {
            $('#iconset_render').append('<div class="icon"><img src="' + data.path + '" /></div>');
        });
    
        socket.on('setIconsetArray', function (data) {
            var iconset = ($('#iconset_array').val()) ? JSON.parse($('#iconset_array').val()) : [];
    
            iconset.push(data.iconName);
    
            $('#iconset_array').val(JSON.stringify(iconset));
    
            deleteIcon($('#icon_name').val());
    
            // close modal
            $('#icon_action_modal').modal('hide');
        });
    
    });
    
    $('#icon_action_modal_delete_icon').on('click', function() {
        deleteIcon($('#icon_name').val());
    
        // close modal
        $('#icon_action_modal').modal('hide');
    });
    
    }); // end document.ready
    

    And the full code for server side :

    io.of('/icon_sets/change')
      .on('connection', function (socket) {
        console.log('log input param : ' + socket.handshake.query.name);
        functions.socketImageTransfer(socket, 'icon', 65, 65);
    });
    

    With the socketImageTransfer function :

    module.exports.socketImageTransfer = function(socket, type, width, height, name) {
    
    var socketioFileUploadServer    = require('socketio-file-upload');   // upload files by socket
    var config                      = require(__dirname + '/config/config.json');
    var easyimg                     = require('easyimage');                 // crop - resize image
    var fs                          = require('fs');                        // file system access
    
    // Make an instance of socketioFileUploadServer and listen on this socket:
    var uploader = new socketioFileUploadServer();
    uploader.dir = config.tmpDir;
    uploader.listen(socket);
    
    // Do something when a file is saved:
    uploader.on('saved', function (event) {
    
        console.log('Original ' + type + ' saved');
    
        // resize and rename image with a unique id
        var newName;
    
        if (!name) {
            newName = Math.random().toString(36).substr(2, 9) + '_' + type + '.png';
        } else {
            newName = name;
        }
    
        var fileName = event.file.name.replace(/ /g, '_');
    
        easyimg.rescrop({src: config.tmpDir + fileName, dst: config.uploadDir + type + '/' + newName, width: width, height: height}, function (err, image) {
    
            if (err) return console.log(err);
    
            console.log(type + ' resized and cropped: ' + image.width + ' x ' + image.height);
    
            // image is uploaded - resized - croped, now display it
            socket.emit('display' + ucfirst(type) + 'Image', {path: '/upload/'+ type + '/' + newName});
    
            // remove original from file system
            fs.unlink(config.tmpDir + fileName, function () {
                if (err) throw err;
                console.log('Original ' + type + ' removed');
            });
    
            // additionnal action
            switch(type) {
                case 'icon':
                    // send path to generate iconset_json
                    socket.emit('setIconsetArray', {iconName: newName});
                    break;
            }
    
        });
    
    });
    
    uploader.on('start', function (event) {
        console.log('Client start upload');
        socket.emit('displayOverlay');
    });
    
    // Error handler:
    uploader.on('error', function (event) {
        console.log("Error from uploader", event);
    });
    
    };
    

    Appreciate your help

  • ceadreak
    ceadreak over 9 years
    Ty for your answer CuriousGuy. It not solved my problem but Ty for the explanation of the "query" param. I use socket.io file-upload to upload some images on my web server. In the "update" case, I need to retrieve the image name to assign it on the new image. In my console, I saw the connection on my socket is BEFORE my image update action. Log says, log input param : undefined but at this time, I haven't load a new image ... Please, see my post update. Ty in advance for your help
  • ceadreak
    ceadreak over 9 years
    +1 ! Ty for your time and your very complete answer. Your solution was my second choice if the query parameter did not work. I'll go in that direction. TY CuriousGuy !
  • Pritam
    Pritam about 9 years
    @Curious: How can I pass 2 parameters with query option? Thanks in advance.!
  • Oleg
    Oleg about 9 years
    @Pritam have you tried this: {query: 'param1=something&param2=another'} ? You can pass params the same way as you do it with URL GET parameters, i.e. with & as a separator
  • sports
    sports about 9 years
    You are using this in the serverside: console.log(socket.handshake.query.name); but I dont understand where is socket previously defined...
  • Oleg
    Oleg about 9 years
    @sports my mistake. socket is a 'connection' handler function argument. edited my answer. thank you :)
  • jumper rbk
    jumper rbk over 7 years
    this is perfect
  • Abilash Arjunan
    Abilash Arjunan over 7 years
    I am facing the same issue that ceadreak is facing, I haven't crossed the first stream yet. I am trying to upload an image file using node and socket.io, I am using socketio-file-upload plugin. at client site uploader.listenOnInput(document.getElementById("siofu_input"‌​)); at server side am not sure how to get its value, the above answer did not help me.
  • Faizan Noor
    Faizan Noor over 6 years
    This is how it should be. Great (Y)
  • Derk Jan Speelman
    Derk Jan Speelman over 4 years
    Why does this not work for me, what version of socket.io were you using here?
  • Artemis
    Artemis over 3 years
    Dead link at the end :(
  • Fabio Falci
    Fabio Falci almost 3 years
    v4 yout can use this: var socket = io('http://localhost:8890',{ query: "foo=bar" });
  • Penguin
    Penguin about 2 years