Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

dnode

Package Overview
Dependencies
Maintainers
0
Versions
80
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

dnode

freestyle RPC

  • 0.7.3
  • Source
  • npm
  • Socket score

Version published
Weekly downloads
3.4K
increased by30.8%
Maintainers
0
Weekly downloads
 
Created
Source

dnode

dnode: freestyle rpc

DNode is an asynchronous object-oriented RPC system for node.js that lets you call remote functions.

It works over network sockets and even in the browser with socket.io.

Plus, there are dnode implementations for perl, ruby, and java, so you can glue together all your backend processes swimmingly.

dnode between two node.js processes

Just write a server.js:

var dnode = require('dnode');

var server = dnode({
    zing : function (n, cb) { cb(n * 100) }
});
server.listen(5050);

Run it...

$ node server.js

Then you can whip up a client.js that calls the server's zing function!

var dnode = require('dnode');

dnode.connect(5050, function (remote) {
    remote.zing(66, function (n) {
        console.log('n = ' + n);
    });
});

$ node client.js
n = 6600
^C

dnode on the browser

We can retrofit the previous example to run in the browser.

Just write a server.js:

var express = require('express');
var app = express.createServer();
app.use(express.static(__dirname));

app.listen(8080);
console.log('http://localhost:8080/');

// then just pass the server app handle to .listen()!

var dnode = require('dnode');
var server = dnode({
    zing : function (n, cb) { cb(n * 100) }
});
server.listen(app);

and whip up an index.html:

<html>
<head>
<script src="/dnode.js" type="text/javascript"></script>
<script type="text/javascript">
    window.onload = function () {
        
        DNode.connect(function (remote) {
            remote.zing(66, function (n) {
                document.getElementById('result').innerHTML = n;
            });
        });
        
    };
</script>
</head>
<body>

n = <span id="result">?</span>

</body>
</html>

then just run the server.js:

$ node server.js
http://localhost:8080/

and navigate to http://localhost:8080:

dnode in the browser

Awesome it works!

The dnode browser source automatically gets hosted at /dnode.js and it also works with browserify out of the box.

how it works

When you throw an object at dnode, a recursive traversal scrubs out all of the function objects nested in your data structure and a secondary data structure is sent along with remote requests that creates shim functions that create RPC calls back to the side where the functions were originally defined.

When you call a remote function, the same recursive traversal trick happens to the arguments you pass along, so you can pass callbacks to your remote functions that actually call you back over the wire when the remote side calls the shim function on the other end.

Basically, dnode lets you call remote functions as if they were defined locally without using eval() or Function.prototype.toString(). Awesome!

The only catch is that because the function calls are traveling down the high-latency network, the return values of your functions are ignored. Use continuation-passing style instead!

More features:

  • symmetric design: both sides of the connection can host up methods for the other side to call

  • use TCP streams, UNIX domain sockets, or websockets courtesy of socket.io! (see below, just throw a webserver at listen())

methods

dnode(wrapper)

If wrapper is an object, serve this object up to the other side every time.

If wrapper is a function, use it to build a new object for each new client. The result of new wrapper(remote, conn) will be used, where remote is an empty object that will be filled with the other side's methods once the initial protocol phase finishes and where conn is the connection object.

Both client and server can call dnode() with a wrapper. dnode.connect() and dnode.listen() are shortcut that set wrapper to {}.

.connect(...)

Connect to a remote dnode service. Pass in a port, host, UNIX domain socket path, block, or options object in any order. The block function if present will be executed with the remote object and the connection object once the remote object is ready.

You can reconnect when the connection is refused or drops by passing in a reconnect option as the number of milliseconds to wait between reconnection attempts.

Returns this so you can chain multiple connections.

.listen(...)

Listen for incoming dnode clients. Pass in a port, host, UNIX domain socket path, block, or options object in any order. The block function if present will be executed with the remote object and the connection object once the remote object is ready for each client.

If you pass a webserver (http.Server, https.Server, connect, express) to listen(), socket.io will be bound to the webserver and the dnode browser source will be hosted at options.mount || "/dnode.js".

You can pass options through to socket.io with the io parameter:

dnode(...).listen(webserver, { io : { flashPolicyServer : false } });

Returns this so you can chain multiple listeners.

.use(middleware)

You can write your own dnode middleware with .use(). The middleware function you pass will be called just like the constructor function that dnode() takes. You can modify this, remote, and conn objects after the instance computed with the dnode() constructor executes but before the methods are sent over the wire.

Returns this so you can chain middlewares.

the connection object

When you pass a constructor function to dnode() you'll get a connection object as the second argument to your constructor.

The connection object (conn) is an EventEmitter.

  • conn.id is a random hex string that uniquely identifies clients

  • conn.end() closes the connection and won't reconnect

  • conn emits 'ready' when the remote object has been fully populated from the methods exchange

  • conn emits 'remote' at the same time as 'ready', except with the remote object as an argument

  • conn emits 'end' when the connection drops

  • conn emits 'connect' when the connection is established

  • conn re-emits error events from the stream object

  • conn emits 'refused', 'drop', and 'reconnect' when reconnect is enabled

more examples

Check out the examples directory of this distribution.

You'll find examples for using dnode with connect, express, https, and authentication.

There's a chat server too!

installation

Using npm:

npm install dnode

Or check out the repository and link your development copy:

git clone https://github.com/substack/dnode.git
cd dnode && npm link

The dnode dependencies are listed in the package.json. If you install with npm they will be fetched automatically.

read more

protocol

DNode uses a newline-terminated JSON protocol documented in the dnode-protocol readme.

dnode in other languages

These libraries implement the dnode protocol too so you can make RPC calls between scripts written in different languages.

There's a dnode-python in the works too but it's not finished yet.

shameless plug

Want to make sure your crazy javascript-heavy app still works in other browsers? Give browserling a spin! Browsers in your browser. Powered by dnode.

Keywords

FAQs

Package last updated on 22 Jun 2011

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc