Reading time: 13 min

Protocols

By default, Kuzzle supports HTTP, Websocket and Socket.io protocols.

Kuzzle can be extended with custom protocols to support more type of entries.


Install

Installing a protocol is very similar to plugins

The only difference is that protocols need to be installed in protocols/enabled directory.


Configure

Protocols are configured within Kuzzle configuration, under the server/protcols/<protocol name> section.

Example:
.kuzzlerc

{
  "server": {
    "protocols": {
      "mqtt": {
        "port": 1883,
        "allowPubSub": true
      }
    }
  }
}

The example above will be taken into account by Kuzzle MQTT protocol;


Build your own

Protocols are constructors exposed in a nodejs module.

Protocols must implement the following methods:

MethodArgumentsDescription
broadcast{channels, payload}Asks Protocol Plugins to emit a data payload (pojo object) to clients connected to the channels list channels (array of strings)
disconnectconnectionIdAsks protocol plugins to force-close the connection connectionId
initproxyPlugin initialization function
joinChannelchannel, connectionIdTells Protocol Plugins that the connection connectionId subscribed to the channel channel
leaveChannelchannel, connectionIdTells Protocol Plugins that the connection connectionId left the channel channel
notify{channels, connectionId, payload}Asks Protocol Plugins to emit a data payload (pojo object) to the connection connectionId (string), on the channels channels (array of strings)

init

init ({EntryPoint} entryPoint, {Object} context)

return value: void or Promise. If the returned value is a promise, Kuzzle will wait till it is resolved to continue starting.


Available objects reference

ClientConnection

ClientConnection objects must be given to the entryPoint.newConnection method. Their auto-generated id must be used wherever a connectionIdis required. The ClientConnection constructor is exposed in the context object passed to the protocol init method.

constructor

new context.ClientConnection(protocol, ips, headers)

  • protocol: {string} the protocol identifier (= this.protocol)
  • ips: {array of strings} list of forwarded ip addresses (or any client connection information) of the connection. In http, will contain the ip addresses from X-Forwarded-For header.
  • headers: [Optional] {object} A set of key/value pairs that can contain any extra information

context instance

The context instance is passed to the protocol init method.

It contains useful functions and objects not directly related to the protocol communication.

constructors

utils

  • errors: An object containing Kuzzle error constructors
  • log: An set of level log functions. level values are: [silly, verbose, debug, info, warn, error]

ex: context.log.error(new context.errors.InternalError('something went bad'))


EntryPoint

config property

type: pojo object

Contains Kuzzle configuration server subtree. The user configuration for the protocol can potentially be found under entryPoint.config.protocols[protocolName].

execute method

execute(request, callback)

  • request
    {Request} The Request constructor is exposed in the context object given to the init method.
    The request must be constructed with a valid request context, including the connectionId and the protocol (cf example below).
  • callback
    {Function} The callback to be executed when Kuzzle gets the result.
    Takes one response argument, being the result of RequestResponse.toJSON().

example:

const request = new context.Request({
  controller: 'server',
  action: 'now'
}, {
  connectionId: 'current connection Id',
  protocol: this.protocol
});

entryPoint.execute(request, response => {
  console.log(response.content);
});

newConnection method

newConnection(connection)

return value: none

removeConnection method

removeConnection(connectionId)

return value: none

  • connectionId: {string} the ClientConnection auto generated id to remove.

TL;DR custom protocol skeleton

class MyProtocol {
  constructor () {
    this.context = null;

    // [Mandatory] will be used a protocol name by Kuzzle
    this.protocol = 'myProtocol';

    // Example on how to maintain client connections
    this.clients = {};
    this.connections = {};
  }

  /** 
  * [Required]
  * 
  * @param {EntryPoint} entryPoint - main protocol interface with Kuzzle
  * @param {object} context - Constructors and utilities
  */
  init (entryPoint, context) {
    // plugin initialization
    this.entryPoint = entryPoint;
    this.context = context;

    // user configuration can be retrived from entryPoint.config[protcol name]
    this.config = Object.assign({
      default: 'value'
    }, entryPoint.config[this.protocol] || {});
  }

  /*
   This function is only an example showing how to interact with
   clients and with Kuzzle. It does not implement any actual protocol.

   The way a protocol plugins handles clients closely depends on the
   implemented protocol.
   */
  handleClient () {
    // when a client connects
    this.on('onClientConnect', client => {

      const connection = new context.constructor.ClientConnection(this.protocol, [client.connection.stream.remoteAddress], {some: 'header'});
      this.entryPoint.newConnection(connection);

      this.clients[connection.id] = client;
      this.connections[client.id] = connection;
    });

    // when a client sends a request
    this.on('onClientRequest', (client, data) => {
      // Instantiates a Request object to be passed to Kuzzle
      const
        connection = this.connections[client.id],
        request = new this.context.Request(data, {
          connectionId: connection.id,
          protocol: this.protocol
        });

      this.entryPoint.execute(request, response => {
        // forward the response to the client
      });
    });

    // whenever a client is disconnected
    this.on('onClientDisconnect', client => {
      const connection = this.connections[client.id];

      this.entryPoint.removeConnection(connection.id);
      delete this.clients[connection.id];
      delete this.connections[client.id];
    });
  }

  /*
   Invoked by Kuzzle when a "data.payload" payload needs to be
   broadcasted to the "data.channels" channels

   The payload is a Kuzzle response as a plain-old JSON object
  */
  broadcast (data) {
    data.channels.forEach(channel => {
      // sends data.payload to the channel
    });
  }

  /*
   Invoked by Kuzzle when a "data.payload" payload needs to be
   notified to the connection "data.id", on the "data.channels" channels

   The payload is a Kuzzle response as a plain-old JSON object
  */
  notify (data) {
    data.channels.forEach(channel => {
      // sends "data.payload" to the connection "data.id" and to
      // the channel "channel"
    });
  }

  /*
    Invoked by Kuzzle when the connection "connectionId" joins the
    channel "channel"
   */
  joinChannel (channel, connectionId) {
     // ...
  }

  /*
    Invoked by Kuzzle when the connection "connectionId" leaves the
    channel "channel"
   */
  leaveChannel (channel, connectionId) {
    // ...
  }

  /*
    Invoked by Kuzzle when it needs to force-close a client connection
   */
  disconnect (connectionId) {
    const client = this.clients[connectionId];
    // close the client connection
  }
}

// Exports the plugin objects, allowing Kuzzle to instantiate it
module.exports = MyProtocol;