0

I'm getting the error "TypeError: Cannot read property 'handshaken' of undefined" when using my app since I've installed socket.io

It seems that the checkUserHaveConnect method within the helpers/utils.js file is causing the error as my console.log("io 2", io") is called just before the error (this can be seen in my screenshot below)

The strange thing is, that this error does not occur on my development environment (laptop), but only when deployed in production (nodejitsu).

Firstly, here is my index file where the socket.io connection is initiated.

index.js

var server = http.createServer(app);

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

// launch
server.listen(port);

//With Socket.io >= 1.0
io.use(passportSocketIo.authorize({
    cookieParser: express.cookieParser,
    key:         EXPRESS_SID_KEY,       // the name of the cookie where express/connect stores its session_id
    secret:      SESSION_SECRET,    // the session_secret to parse the cookie
    store:       sessionStore,        // we NEED to use a sessionstore. no memorystore please
    success:     onAuthorizeSuccess,  // *optional* callback on success - read more below
    fail:        onAuthorizeFail,     // *optional* callback on fail/error - read more below
}));

io.on('connection', function (socket) {
    console.log("connection come");

    socket.on('disconnect', function (socket) {
        console.log("disconnect come");
    });
});

function onAuthorizeSuccess(data, accept){
    console.log('successful connection to socket.io');
    accept(null, true);
}

function onAuthorizeFail(data, message, error, accept){
    console.log('failed connection to socket.io:', message);
    if(error){
        throw new Error(message);
    }
    // We use this callback to log all of our failed connections.
    accept(null, false);
}

console.log('The magic happens on port' + port);

Here are the methods where the problem might be caused.

helpers/utils.js

var passportSocketIo = require("passport.socketio");
exports.emitData = function(userId, eventName,data){

console.log("io 1", io);

    var sockets = passportSocketIo.filterSocketsByUser(io, function(user){
        if(user._id){
            return user._id.toHexString() === userId.toHexString();
        }
        return false;
    });
    sockets.forEach(function(socket){
        socket.emit(eventName,data);
    });
    return sockets.length;
}

exports.checkUserHaveConnect = function(userId){

console.log("io 2", io);

    return passportSocketIo.filterSocketsByUser(io, function(user){
        if(user._id){
            return user._id.toHexString() === userId.toHexString();
        }
        return false;
    }).length;
}

error

Anthony
  • 446
  • 6
  • 15

2 Answers2

1

The feature is broken because socket.io > 1.0 has no more handshake data (replaced by "request"), which is used in the passport.socketio filterSocketsByUser method.

There is a fix on the way to the npm, in the meantime, you can replace in the package :

function filterSocketsByUser(socketIo, filter){
  var handshaken = socketIo.sockets.manager.handshaken;
  return Object.keys(handshaken || {})
    .filter(function(skey){
      return filter(handshaken[skey].user);
    })
    .map(function(skey){
      return socketIo.sockets.manager.sockets.sockets[skey];
    });
}

by the following (courtesy of Gausie) :

function filterSocketsByUser(socketIo, filter){
  var handshaken = [];
  for ( var i in socketIo.sockets.connected )
    if ( socketIo.sockets.connected[i].handshake )
        handshaken.push( socketIo.sockets.connected[i] )

  return Object.keys(handshaken || {})
    .filter(function(skey){
      return filter(handshaken[skey].conn.request.user);
    })
    .map(function(skey){
      return handshaken[skey];
    });
}

Source : Github

xShirase
  • 11,975
  • 4
  • 53
  • 85
0

To fix this I had to use the latest version of passport.socketio as the version on NPM is out of date.

As I'm using nodejitsu, I had to add a "bundleDependencies" section in the package.json file like this:

"bundleDependencies": [
"passport.socketio"
],

This ensures that my local version of passport.socketio is used rather than the NPM version.

Anthony
  • 446
  • 6
  • 15