Tutorial: The Real Time API

Tutorial Real Time
Adding Real Time Interactivity

Traditional APIs operate unidirectionally and it is usually the client that initiates a request to the API.  If the API needs to do any work and communicate with back-end services it is the API that initiates the request to the relevant service.

But what happens when the API needs to initiate communication with the client?  Ordinarily most API developers would implement an endpoint which allows for the API to be polled but not only is this a fairly manual action on the part of the client but it increases transactional load particularly where a client needlessly polls to receive no information at all.

Introducing Websockets

Websockets add bidirectional communications to an API and establishes a long-lived connection between the client and the API.  Using this channel APIs can signal clients when information is available without the client needlessly polling or requesting information from the API.

This bidirectional communication offers numerous advantages to API developers.  Where an API is particularly complex or may have long-running jobs the default HTTP transport used by the browser can close or time-out thus interrupting the API’s ability to return information back to the client.  Similarly where an API needs to signal an event to a client, such as the completion of a report or activity, it can do so simply by emitting the event to the client on the bidirectional channel.

Websockets are used extensively as the underlying communications channel in real time mobile and web applications and thus are introduced early in this series.

For our RESTify API we will make use of the excellent socket.io library which offers a high degree of compatibility with browsers and clients by offering multiple fallback transports in cases where websockets are not available.  Thus it makes it the ideal library for our use case.

Socket.io is directly compatible with Express, the underlying engine of our RESTify API, and can be invoked merely by binding it with the created server object.  In our use case we will make use of a separate port to demonstrate how both native HTTP and websockets can co-exist.

  // Include socket.io
  var options = {
    pingTimeout: 8000,
    pingInterval: 5000,
    "reconnection": true,
    "reconnectionDelay": 2000,                  //starts with 2 secs delay, then 4, 6, 8, until 60 where it stays forever until it reconnects
    "reconnectionDelayMax" : 60000,             //1 minute maximum delay between connections
    "reconnectionAttempts": "Infinity",         //to prevent dead clients, having the user to having to manually reconnect after a server restart.
    "timeout" : 10000,
    transports: ['websocket'],
    allowUpgrades: true,
    upgrade: true,
    cookie: false
  };
  var io = require('socket.io').listen(8086, options);

Lines 124 through 138 of server.js shows how to include socket.io in to a RESTIfy (or any Express) API.  The options have been expanded somewhat to demonstrate the extensive capabilities and for an explanation of the options (or even more of them), please refer to the documentation located at socket.io.

Because we don’t necessarily want the socket.io logic inside our main server.js file an additional entry on line 172 passes control of the io object (along with the server and passport objects) to a separate router.

    // Incorporate endpoints for socket.io
     require('./socket.js')(__dirname+'/sockets', server, passport, io);

The declaration on line 172 calls for a the invocation of a separate socket.js file whose contents are as follows.

module.exports = function route(dirname, server, passport, io) {
  var files = fs.readdirSync(dirname);

  files.forEach(function (file) {
    if (path.extname(file) === '.js') {
      var filepath = dirname + '/' + file;
      if (fs.statSync(filepath).isDirectory()) {
        route(filepath, server, passport, io);
      } else {
        var socket = require(filepath);
        socket.route(server, passport, io);
      }
    }
  });
};

For each file found in the sockets directory the relevant functions are integrated in to the main ‘io’ object through the code above.

Next Up:  Handling Real Time Events

Pages: 1 2 3 4

Written by YourAPIExpert