strong-remoting
Overview
Objects (and, therefore, data) in Node applications commonly need to be accessible by other Node processes, browsers, and even mobile clients. Strong remoting:
- Makes local functions remotable, exported over adapters.
- Supports multiple transports, including custom transports.
- Manages serialization to JSON and deserialization from JSON.
- Supports multiple client SDKs, including mobile clients.
Client SDK support
For higher-level transports, such as REST and Socket.IO, existing clients will work well. If you want to be able to swap out your transport, use one of our supported clients. The same adapter model available on the server applies to clients, so you can switch transports on both the server and all clients without changing your application-specific code.
Supported versions
Current | Long Term Support |
---|
3.x | 2.x |
Learn more about our LTS plan in docs.
Installation
$ npm install strong-remoting
Quick start
The following example illustrates how to set up a basic strong-remoting server with a single remote method, user.greet.
var remoting = require('../');
var SharedClass = remoting.SharedClass
var remotes = remoting.create();
function User() {
}
User.greet = function (fn) {
fn(null, 'hello, world!');
}
var userSharedClass = new SharedClass('user', User);
userSharedClass.defineMethod('greet', {
isStatic: true,
returns: [{
arg: 'msg',
type: 'string'
}]
});
require('http')
.createServer(remotes.handler('rest'))
.listen(3000);
Then, invoke User.greet()
easily with curl
(or any HTTP client)!
$ curl http://localhost:3000/user/greet?str=hello
Result:
{
"msg": "hello world"
}
Concepts
Remote objects
Most Node applications expose a remotely-available API. Strong-remoting enables you to build your app in vanilla JavaScript and export remote objects over the network the same way you export functions from a module. Since they're just plain JavaScript objects, you can always invoke methods on your remote objects locally in JavaScript, whether from tests or other, local objects.
Remote object collections
Collections that are the result of require('strong-remoting').create() are responsible for binding their remote objects to transports, allowing you to swap out the underlying transport without changing any of your application-specific code.
Adapters
Adapters provide the transport-specific mechanisms to make remote objects (and collections thereof) available over their transport. The REST adapter, for example, handles an HTTP server and facilitates mapping your objects to RESTful resources. Other adapters, on the other hand, might provide a less opinionated, RPC-style network interface. Your application code doesn't need to know what adapter it's using.
Hooks
Hooks enable you to run code before remote objects are constructed or methods on those objects are invoked. For example, you can prevent actions based on context (HTTP request, user credentials, and so on).
remotes.authorization = function(ctx, next) {
if(checkContext(ctx)) {
next();
} else {
var err = new Error('denied!');
err.statusCode = 401;
next(err);
}
}
remotes.before('user.greet', function (ctx, next) {
if((ctx.req.param('password') || '').toString() !== '1234') {
next(new Error('Bad password!'));
} else {
next();
}
});
remotes.before('user.*', function (ctx, next) {
console.log('Calling a user method.');
next();
});
remotes.before('dog.prototype.*', function (ctx, next) {
var dog = this;
console.log('Calling a method on "%s".', dog.name);
next();
});
remotes.after('dog.prototype.speak', function (ctx, next) {
console.log('After speak!');
next();
});
remotes.before('**', function (ctx, next, method) {
console.log('Calling:', method.name);
next();
});
remotes.after('**', function (ctx, next) {
ctx.result += '!!!';
next();
});
Hooks accept an asynchronous handler function that is called for every request. This handler function signals the completion either by accepting a callback argument or returning a promise. For example:
remotes.after('dog.prototype.speak', function(ctx, next) {
console.log('After speak!');
next();
});
remotes.after('dog.prototype.speak', function(ctx) {
console.log('After speak!');
return Promise.resolve();
});
See the before-after example for more info.
Streams
Strong-remoting supports methods that expect or return Readable and Writeable streams. This enables you to stream raw binary data such as files over the network without writing transport-specific behavior.
For example, the following code exposes a method of the fs
Remote Object, fs.createReadStream
, over the REST adapter:
var remotes = require('strong-remoting').create();
var fs = remotes.exports.fs = require('fs');
fs.createReadStream.shared = true;
fs.createReadStream.accepts = {arg: 'path', type: 'string'};
fs.createReadStream.http = {
pipe: {
dest: 'res'
}
};
require('http')
.createServer(remotes.handler('rest'))
.listen(3000);
Then you can invoke fs.createReadStream()
using curl as follows:
$ curl http://localhost:3000/fs/createReadStream?path=some-file.txt