6.3 KiB
Remote methods and hooks
You can expose a Model's instance and static methods to clients. A remote method must accept a callback with the conventional fn(err, result, ...)
signature.
loopback.remoteMethod(fn, [options])
Expose a remote method.
Product.stats = function(fn) {
var statsResult = {
totalPurchased: 123456
};
var err = null;
// callback with an error and the result
fn(err, statsResult);
}
loopback.remoteMethod(
Product.stats,
{
returns: {arg: 'stats', type: 'object'},
http: {path: '/info', verb: 'get'}
}
);
Options
The options argument is a JSON object, described in the following table.
Option | Required? | Description |
---|---|---|
accepts | No | Describes the remote method's arguments; See Argument description. The callback argument is assumed; do not specify. |
returns | No | Describes the remote method's callback arguments; See Argument description. The err argument is assumed; do not specify. |
http | No | HTTP routing information:
|
The arguments description defines either a single argument as an object or an ordered set of arguments as an array. Each individual argument has keys for:
- arg: argument name
- type: argument datatype; must be a loopback type.
- required: Boolean value indicating if argument is required.
- root: For callback arguments: set this property to
true
if your function has a single callback argument to use as the root object returned to remote caller. Otherwise the root object returned is a map (argument-name to argument-value). - http: For input arguments: a function or an object describing mapping from HTTP request to the argument value, as explained below.
For example, a single argument, specified as an object:
{arg: 'myArg', type: 'number'}
Multiple arguments, specified as an array:
[
{arg: 'arg1', type: 'number', required: true},
{arg: 'arg2', type: 'array'}
]
HTTP mapping of input arguments
There are two ways to specify HTTP mapping for input parameters (what the method accepts):
- Provide an object with a
source
property - Specify a custom mapping function
To use the first way to specify HTTP mapping for input parameters, provide an object with a source
property
that has one of the values shown in the following table.
Value of source property | Description |
---|---|
body | The whole request body is used as the value. |
form | The value is looked up using req.param , which searches route arguments, the request body and the query string. |
query | An alias for form (see above). |
path | An alias for form (see above). |
req | The whole HTTP reqest object is used as the value. |
For example, an argument getting the whole request body as the value:
{ arg: 'data', type: 'object', http: { source: 'body' } }
The use the second way to specify HTTP mapping for input parameters, specify a custom mapping function that looks like this:
{
arg: 'custom',
type: 'number',
http: function(ctx) {
// ctx is LoopBack Context object
// 1. Get the HTTP request object as provided by Express
var req = ctx.req;
// 2. Get 'a' and 'b' from query string or form data
// and return their sum as the value
return +req.param('a') + req.param('b');
}
}
If you don't specify a mapping, LoopBack will determine the value
as follows (assuming name
as the name of the input parameter to resolve):
- If there is a HTTP request parameter
args
with a JSON content, then the value ofargs['name']
is used if it is defined. - Otherwise
req.param('name')
is returned.
Remote hooks
Run a function before or after a remote method is called by a client.
// *.save === prototype.save
User.beforeRemote('*.save', function(ctx, user, next) {
if(ctx.user) {
next();
} else {
next(new Error('must be logged in to update'))
}
});
User.afterRemote('*.save', function(ctx, user, next) {
console.log('user has been saved', user);
next();
});
Remote hooks also support wildcards. Run a function before any remote method is called.
// ** will match both prototype.* and *.*
User.beforeRemote('**', function(ctx, user, next) {
console.log(ctx.methodString, 'was invoked remotely'); // users.prototype.save was invoked remotely
next();
});
Other wildcard examples
// run before any static method eg. User.find
User.beforeRemote('*', ...);
// run before any instance method eg. User.prototype.save
User.beforeRemote('prototype.*', ...);
// prevent password hashes from being sent to clients
User.afterRemote('**', function (ctx, user, next) {
if(ctx.result) {
if(Array.isArray(ctx.result)) {
ctx.result.forEach(function (result) {
result.password = undefined;
});
} else {
ctx.result.password = undefined;
}
}
next();
});
Context
Remote hooks are provided with a Context ctx
object which contains transport specific data (eg. for http: req
and res
). The ctx
object also has a set of consistent apis across transports.
ctx.user
A Model
representing the user calling the method remotely. Note: this is undefined if the remote method is not invoked by a logged in user.
ctx.result
During afterRemote
hooks, ctx.result
will contain the data about to be sent to a client. Modify this object to transform data before it is sent.
Rest
When loopback.rest is used the following ctx
properties are available.
ctx.req
The express ServerRequest object. See full documentation.
ctx.res
The express ServerResponse object. See full documentation.