socketcluster-api

0.3.0 • Public • Published

socketcluster-api

SocketCluster-API is a module for creating REST api's over SocketCluster's websocket implementation.

If you're familiar with expressjs using socketcluster-api will include many familiar steps

This is built using sc-codec-protobuf which will encode all messages using Google Protocol Buffer.

All messages are encoded to a protobuf, which also requires you to provided message definitions.

Getting started

Using the following protobuf for the getting started

syntax = "proto3";
 
package app;
 
message RequestMessage {
  string a = 1;
  string b = 2;
}
 
message ResponseMessage {
  string c = 1;
}
 
message SomeError {
  uint32 code = 1;
  string message = 2;
}

Server

const protobuf = /* acquire protobuf as a string */
const { API } = require('socketcluster-api');
const app = new API([ protobuf ]
const router = app.router();
 
// `data` is provided by the client
router.use('/resource', async (data) => {
  // ... Perform operations
  return {
    dataType: '.app.ResponseMessage',
    data: { c : 'important result' }
  };
 
  // To indicate an error, you could instead throw an object
  throw {
    dataType: '.app.ResponseMessage',
    data: { c : 'important result' }
  };
});
 
// SocketCluster's workerController
function workerController(worker) {
  // Get the custom codecEngine so that protobuf message are properly encoded/decoded.
  scServer.setCodecEngine(app.codec);
 
  // Register the router for each client that connects
  scServer.on('connection', (scSocket) => {
    router.register(scSocket);
  });
}

Client

import protobuf from /* acquire protobuf as a string */;
import socketCluster from 'socketcluster-client';
import { API } from 'socketcluster-api';
 
const api = new API([ protobuf ]);
 
const socket = socketCluster.connect({
  codecEngine: api.codec,
  port: 8000,
});
 
// Makes `get` available as a function on `socket`
api.defineEndpoints(socket);
 
// Calls the `/resource` endpoint, with a message of type `.app.RequestMessage`.
// Note that the data must fit the `.app.RequestMessage` or an error will be thrown.
socket.get('/resource', [ '.app.RequestMessage', { a: 'this string', b: 'this string too' } ])
  .then((data) => debug('server replied %o', data))
  .catch((err) => debug('got an error:', err));
 

Advanced topics - Server

Nested routers

 
const resourceRouter = new Router()
  .use(() => { /* handler */ })               // 1
  .use('something', () => { /* handler */ }); // 2
 
const router = new Router()
  .use('resource', () => { /* handler */ })   // 3
  .use('resource', resourceRouter);           // 4
 
// ...
 
// This will bind the following routes:
// 1. '/resource/'
// 2. '/resource/something'
// 3. '/resource
// 4. Doesn't bind anything since handler is a `Router`
router.register(scSocket);

NB. /resource and /resource/ (trailing slash) are different routes and invokes different handlers

Routers can be nested to any depth.

Readme

Keywords

none

Package Sidebar

Install

npm i socketcluster-api

Weekly Downloads

1

Version

0.3.0

License

MIT

Last publish

Collaborators

  • noseglid