Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Connection between Socket.IO and HapiJS

We have a REST server implemented with HapiJS and a Websockets server implemented with Socket.IO (they are both running on a single server but on different ports). I want to notify the Websockets server from the HapiJS server to send an event with some data to a particular client.

The socket server is running on port 8081 and the REST is on 8080.

The idea is that a client makes an action (POST request), that is logged in an "Actions History" table. That action concerns other users, so they should be notified when this happens in real time. That is why the other users are listening on the websocket connection.

How can I tell the sockets server to emit an event to a particular client and that should be done from the REST server?

I thought for 3 ways at the moment:

  1. Separate servers for sockets and rest and communicate using RabbitMQ
  2. I tried to implement Socket.IO-Emitter but it requires Redis database (I still don't know why). When I try to connect using the emitter from the HapiJS route handler to the socket I get:

      export function* postRefreshEvent(userId) {
        var connection = require('socket.io-emitter')({ host: '127.0.0.1', port: 8081 });
        connection.in('UserHistory').emit('refresh', userId); 
        return {statusCode: OK}
    
      }        
    
    Error: Ready check failed: Redis connection gone from end event.
    

    at RedisClient.on_info_cmd

Refresh is not executed in the Socket server. I just don't see the log displayed.

  1. Make a special event and use an ordinary socket.io client to connect from the hapijs to websockets and emit there the new event.

A sample GIST.

Have you figured out something like this? I appreciate every help!

like image 486
NMP Avatar asked Dec 08 '22 01:12

NMP


2 Answers

You could try using https://github.com/hapijs/nes which intergrates websockets into hapi via a plugin. Disclaimer I have not tried it or used websockets before but it seems integrate into hapi well .

like image 35
simon-p-r Avatar answered Dec 11 '22 12:12

simon-p-r


You can just use a plain old EventEmitter to communicate between the socket.io and the hapi parts of your codebase. Here's an example that works and illustrates how you can do this:

var Hapi = require('hapi');

// Make an event emitter for managing communication
// between hapi and socket.io code

var EventEmitter = require('events');
var notifier = new EventEmitter();

// Setup API + WS server with hapi

var server = new Hapi.Server();
server.register(require('inert'), function () {});

server.connection({ port: 4000, labels: ['api'] });
server.connection({ port: 4001, labels: ['ws'] });

var apiServer = server.select('api');
var wsServer = server.select('ws');

apiServer.route({
    method: 'GET',
    path: '/',
    handler: function (request, reply) {

        reply.file('index.html');
    }
});

apiServer.route({
    method: 'GET',
    path: '/action',
    handler: function (request, reply) {

        notifier.emit('action', { time: Date.now() });
        reply('ok');
    }
});

// Setup websocket stuff

var io = require('socket.io')(wsServer.listener);

io.on('connection', function (socket) {

    // Subscribe this socket to `action` events

    notifier.on('action', function (action) {
        socket.emit('action', action);
    });
});

server.start(function () {
    console.log('Server started');
});

Here's a basic index.html for the client side:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <script src="http://localhost:4001/socket.io/socket.io.js"></script>
</head>
<body>
    <script>
    var socket = io('http://localhost:4001');
    socket.on('action', function (action) {
        console.log(action);
    });
    </script>
</body>
</html>

If you run this and browse to http://localhost:4000 and open your console, you can then make requests to http://localhost:4000/action with your browser or with cURL (curl http://localhost:4000/action) and you'll see the events appear in the web console:

enter image description here

like image 67
Matt Harrison Avatar answered Dec 11 '22 11:12

Matt Harrison