git ssb

2+

cel / scuttlebot.io



Tree: 6c7b45a1469f155c415f6439a7df55b9e4d6c522

Files: 6c7b45a1469f155c415f6439a7df55b9e4d6c522 / tmpl / apis / modules / muxrpc.md

3393 bytesRaw

muxrpc

Combined rpc and multiplexing, with pull-streams.

example


var MRPC = require('muxrpc')
var pull = require('pull-stream')

//we need a manifest of methods we wish to expose.
var api = {
  //async is a normal async function
  hello: 'async',

  //source is a pull-stream (readable)
  stuff: 'source'

  //TODO: sink and duplex pull-streams
}

//pass the api into the constructor,
//and then pass the object you are wrapping
//(if there is a local api)
var client = MRPC(api, null) () //remoteApi, localApi
var server = MRPC(null, api) ({
  hello: function (name, cb) {
    cb(null, 'hello, ' + name + '!')
  },
  stuff: function () {
    return pull.values([1, 2, 3, 4, 5])
  }
})

var a = client.createStream()
var b = server.createStream()

pull(a, b, a) //pipe together

client.hello('world', function (err, value) {
  if(err) throw err
  console.log(value)
  // hello, world!
})

pull(client.stuff(), pull.drain(console.log))
// 1
// 2
// 3
// 4
// 5

Manifest

like multilevel, a manifest is required
except it works a little differently, and since muxrpc works with any api, not assuming leveldb then you must write the manifest yourself.

The manifest is simply an object mapping to strings, or nested objects.

{
  //a function with a callback.
  foo: 'async',

  //a function that returns a value
  //(note this is converted to
  // an async function for the client)
  bar: 'sync',

  //a source pull-stream (aka, readable)
  allTheFoos: 'source',

  //a sink pull-stream (aka, writable)
  writeFoos: 'sink',

  //a duplex pull-stream
  fooPhone: 'duplex',

  //create nested objects like this:
  bar: {
    ...
  }
}

Permissions

If you are exposing an api over a network connection, then you probably want some sort of authorization system. muxrpc@4 and earlier had a rpc.permissions() method on the rpc object, but this has been removed. Now you must provide a permissions object, which has methods {pre, post}. pre is called with the path and arguments before the api method is actually called, and if it returns false, then the user gets an error and the method is not called.

This is much more flexible than attaching a standard permissions method--now all methods on the rpc object act the same (call remote methods) and it's possible to have a method named "permissions"

A helper module for providing permissions is provided, this enables you to update permissions on the fly


var Permissions = require('muxrpc/permissions')

var api = {
  foo: 'async',
  bar: 'async',
  auth: 'async'
}

//set initial settings
var perms = Perms({allow: ['auth']})

var rpc = muxrpc(null, api, serializer)({
  foo: function (val, cb) {
    cb(null, {okay: 'foo'})
  },
  bar: function (val, cb) {
    cb(null, {okay: 'bar'})
  },
  auth: function (pass) {
    //implement an auth function that sets the permissions,
    //using allow or deny lists.

    if(pass === 'whatever')
      perms({deny: ['bar']}) //allow everything except "bar"
    else if(pass === 's3cr3tz')
      perms({}) //allow everything!!!
    else return cb(new Error('ACCESS DENIED'))

    //else we ARE authorized.
    cb(null, 'ACCESS GRANTED')
  }
})

//Get a stream to connect to the remote.
//As in the above example!
var ss = rpc.createStream()

View on Github

Built with git-ssb-web