Skip to content

noseglid/socketcluster-api

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

17 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

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.

About

API over SocketCluster's websocket

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 2

  •  
  •