very simple rpc. use with any thing that has .pipe()
RpcStream is a dead simple (75 loc) rpc system that works over any full-duplex text/byte/json stream.
There's also a Python port, e.g. for cross-language RPC-over-SSH.
- rpyc-stream Python
There are a bunch of people have already written node rpc systems, but most of them has done it right yet.
My beef is that all these systems is that they are tightly coupled to, or wrapped around servers. what if I want to encrypt the messages? what if I want to send the messages over stdin/out, or over ssh? of write them to a temp file? there is one abstraction that matches all of these cases; the
I should just be able to do this:
REMOTE_SSH_STREAM //<-- pipe data from a remote sourcepipeDECRYPT_STREAM //through some ('middleware') streams (ssh already encrypts, but I'm paranoid)pipeGUNZIP_STREAMpipeRPC //<--- pipe the data through the RPC system.pipeGZIP_STREAMpipeENCYPT_STREAMpipeREMOTE_SSH_STREAM //<-- and back to the remote//with something very similar on the other side.
RPC framework (AHEM! RPC MODULE!), you just worry about calling the right function, I'll decide where you go...
update: firstname.lastname@example.org now has first class streams, and you can pipe it where you like!
var rpc = require'rpc-stream'//create a server, that answers questions.//pass in functions that may be called remotely.var server = rpccbnull 'hello, '+name//create a client, that asks questions.var client = rpc//pipe rpc instances together!clientpipeserverpipeclientvar remote = clientwrap'hello'remotehello'JIM'iferr throw errconsole.logmess
netcreateServer// create one server per connectionvar server = rpc/* ... */serverpipeconpipeserverlisten3000
var client = rpcvar con = netconnect3000clientpipeconpipeclientvar remote = clientwrap'hola'remotehola'steve'console.logres
RpcStream that will call
methods when written to.
opts.raw is set to
JSON.stringify() is turned off and you just
get a stream of objects, in case you want to do your own parsing/stringifying.
opts.flattenError you can override the default method of converting
errors to plain js objects. For example, to include non-enumerable properties
if!err instanceof Error return errvar err2 = message: errmessagevar props = ObjectgetOwnPropertyNameserrforvar k in errerr2k = errkreturn err2
returns a wrapped object with the remote's methods.
the client needs to already know the names of the methods.
accepts a string, and array of strings, or a object.
if it's an object,
wrap will use the keys as the method names.
//create rpc around the fs module.var fsrpc = rpcrequire'fs'//pipe, etc
then, in another process...
var fsrpc = rpc//pipe, etc//wrap, with the right method names.var remoteFs = fswraprequire'fs'remoteFsmkdir'/tmp/whatever'//yay!
now, the second process can call the
fs module in the first process!
wrap does not use the methods for anything. it just wants the names.
this gets invoked by wrap. but you could call it directly.
rpcwrap'hello'helloname callback//is the same asrpcrpc'hello' name callback