What’s up

I’ve been working on web socket application these days for a while. I successfully built web socket between my React app and nodeJS backend and everything works smoothly. Socket.io became a handy tool that helps a lot with my project so I decided to keep on using it for my other side of connection, which establishes socket between NodeJS and hardware running Linux.

the Issue

Basically, the goal involves NodeJS side and Linux side, where the server side seemed to be quite easy since I already had similar code & pattern written.
However, things got pretty weird - my server cannot console.log anything in connection event when client socket established, which seemed like the socket failed to set up. However, if I closed client, client’s disconnect event would be triggered. So here was the issue:

  • client: connect event won’t be triggered, disconnect event was triggered normally.
  • server: both connection and disconnect event weren’t triggered as client joined in or cut out.

What I tried

  1. First, I logged out the client side socket object. There are two properties: connect: false, and disconnect: true. Which were the opposite as successful setup. But since the disconnect event was only triggered when client left, the issue seemed to be that, the socket was created, but somehow server refuse to connect using this socket.
  2. Then, I tried to minimize my code to what was shown on Socket.io website. It was just 10 lines of code and should be working properly. However it didn’t. And socket.io was updating really quick so I got several version of code, and none of them worked.
  3. Then I cleaned the environment by creating a new NodeJS program and put socket in. It worked. So it was about my part of old code that BLOCK this socket.

Solution

I carefully review my code again, and noticed that I put a middleware into server side socket, which would only accepted React side connection and block others.

self.io.use(function(socket, next) {
    var handshakeQuery = socket.handshake.query;
    var userId = handshakeQuery.userId;
    if (userId) {
        self.addUser(userId, socket);
        next();
    }
    next(new Error('Socket Authentication Error'));
});

Because userId is the property which only exist in my React app, this middleware would fork requests - it only forwarded that socket request containing userId to next() and block others by next(new Error...). After changing code into

self.io.use(function(socket, next) {
    var handshakeQuery = socket.handshake.query;
    var userId = handshakeQuery.userId;
    if (userId) {
        self.addUser(userId, socket);
    }
    next();
});

it got fixed.

Conclusion

In NodeJS, middleware stack is a really significant concept. Not only is it one of the core concept in Node, but also, it was used quite a lot and easy to make mistake. Different next() will fork the program into different branches and, without proper next() will also end the program. So be careful when using next() around!