space-lb2

messaging

space-node

This documentation is deprecated
Please see the new LoopBack documentation site.

Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

See also
Root@parent

 

Table of Contents

Overview

A remote method is a static method of a model, exposed over a custom REST endpoint.  Use a remote method to perform operations not provided by LoopBack's standard model REST API.

Info

For an introductory example of defining a remote method, see Extend your API in Getting Started.

How to define a remote method

To define a remote method:

...

  1. First parameter is a string that is the name of the method you defined in step 2 
  2. Second (optional) parameter provides addtional configuration for the REST endpoint.

Example

See additional introductory examples in Extend your API.

Suppose you have a Person model and you want to add a REST endpoint at /greet that returns a greeting with a name provided in the request.  You add this code to /common/models/person.js:

Code Block
title/common/models/person.js
module.exports = function(Person){
    
    Person.greet = function(msg, cb) {
      cb(null, 'Greetings... ' + msg);
    }
    
    Person.remoteMethod(
        'greet',  
        {
          accepts: {arg: 'msg', type: 'string'},
          returns: {arg: 'greeting', type: 'string'}
        }
    ); 
};

Now, for example, a request to

POST /api/people/greet

with data {"msg": "John"}

will return:

Code Block
titleshell
Greetings... John!
Info

Notice the REST API request above uses the plural form "people" instead of "person". LoopBack exposes the plural form of model names for REST API routes.

Registering a remote method

All LoopBack models have a remoteMethod() static method that you use to register a remote method:

Syntax

model.remoteMethod(requestHandlerFunctionName, [options])

where:

  • model is the model object to which you're adding the remote method. In our example, Person.
  • requestHandlerFunctionName is a string that specifies name of the remote method, for example 'greet'.
  • options is an object that specifies parameters to configure the REST endpoint; see below.

Options

The options argument is a Javascript object containing key/value pairs to configure the remote method REST endpoint.

Note

All of the options properties are optional. However, if the remote method requires arguments, you must specify accepts; if the remote method returns a value, you must specify returns.

OptionDescriptionExample
accepts

Defines arguments that the remote method accepts. These arguments map to the static method you define. For the example above, you can see the function signature:

Code Block
Person.greet(name, age, callback)...

`name` is the first argument, `age` is the second argument and callback is automatically provided by LoopBack (do not specify it in your `accepts` array). For more info, see Argument descriptions.

Default if not provided is the empty array, [].

Code Block
{  ...
  accepts: [
   {arg: 'name', type: 'string'},
   {arg: 'age', type: 'number'},...],
  ... }
description

Text description of the method, used by API documentation generators such as Swagger.

You can put long strings in an array if needed (see note below).

 
http.path

HTTP path (relative to the model) at which the method is exposed.

Code Block
http: {path: '/sayhi'}
http.verb

HTTP method (verb) at which the method is available. One of:

  • get
  • post (default)
  • patch
  • put
  • del
  • all
Code Block
http: {path: '/sayhi', verb: 'get'}
http.statusDefault HTTP status set when the callback is called without an error.
Code Block
languagejs
http: {status: 201}
http.errorStatusDefault HTTP status set when the callback is called with an error.
Code Block
languagejs
http: {errorStatus: 400}
isStaticBoolean. Whether the method is static (eg. MyModel.myMethod). Use false to define the method on the prototype (for example, MyModel.prototype.myMethod). Default is true. 
notes

Additional notes, used by API documentation generators like Swagger.

You can put long strings in an array if needed (see note below).

 
returns

Describes the remote method's callback arguments; See Argument descriptions. The err argument is assumed; do not specify.

Default if not provided is the empty array,  [].

Code Block
returns: {arg: 'greeting', type: 'string'}
Note

You can split long strings in the description and notes options into arrays of strings (lines) to keep line lengths manageable. For example:

[
"Lorem ipsum dolor sit amet, consectetur adipiscing elit,"
"sed do eiusmod tempor incididunt ut labore et dolore",
"magna aliqua."

...

The accepts and returns options properties define either a single argument as an object or an ordered set of arguments as an array. The following table describes the properties of each individual argument.

Property (key)TypeDescription
argStringArgument name
descriptionString or Array

A text description of the argument. This is used by API documentation generators like Swagger.

You can split long descriptions into arrays of strings (lines) to keep line lengths manageable.

[
"Lorem ipsum dolor sit amet, consectetur adipiscing elit,"
"sed do eiusmod tempor incididunt ut labore et dolore",
"magna aliqua."
httpObject or FunctionFor input arguments: a function or an object describing mapping from HTTP request to the argument value. See HTTP mapping of input arguments below.
http.targetString

Map the callback argument value to the HTTP response object. The following values are supported.

  • status sets the res.statusCode to the provided value
  • header sets the http.header or arg named header to the value
requiredBooleanTrue if argument is required; false otherwise.
rootBooleanFor 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).
typeStringArgument datatype; must be a Loopback type.
defaultStringDefault value that will be used to populate loopback-explorer input fields and swagger documentation. Note: This value will not be passed into remote methods function if argument is not present.

For example, a single argument, specified as an object:

Code Block
{arg: 'myArg', type: 'number'}

Multiple arguments, specified as an array:

Code Block
[
  {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

Using an object with a source property

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 propertyDescription
bodyThe whole request body is used as the value.
form
query
path 

The value is looked up using req.param, which searches route arguments, the request body and the query string.

Note that query and path are aliases for form.

reqThe Express HTTP request object.
resThe Express HTTP response object.
contextThe whole context object, which holds request and response objects.

For example, an argument getting the whole request body as the value:

Code Block
{ arg: 'data', type: 'object', http: { source: 'body' } } 

Another example showing the Express HTTP request and response objects:

Code Block
[
 {arg: 'req', type: 'object', 'http': {source: 'req'}},
 {arg: 'res', type: 'object', 'http': {source: 'res'}}
]

 

Using a custom mapping function

The second way to specify HTTP mapping for input parameters is to specify a custom mapping function; for example:

Code Block
{
  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.
    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):

  1. If there is an HTTP request parameter args with JSON content, then it uses the value of args['name'].
  2. Otherwise, it uses req.param('name').

Returning data outside of a JSON field

Specifying a return argument with the arg property will automatically return a JSON object with your data stored within a field of the same name.

If you want to return data as the main response, for example an array, you can do so by setting the root property within the returns object and omitting arg

Code Block
returns: { type: 'array', root: true }

Setting a remote method route

By default, a remote method is exposed at:

Syntax

POST http://apiRoot/modelName/methodName

Where

  • apiRoot is the application API root path.
  • modelName is the plural name of the model.
  • methodName is the function name.

Following the above example, then by default the remote method is exposed at:

Code Block
POST /api/people/greet

To change the route, use the http.path and http.verb properties of the options argument to remoteMethod(), for example:

Code Block
title/common/models/model.js
Person.remoteMethod(
    'greet',  
    {
       accepts: {arg: 'msg', type: 'string'},
       returns: {arg: 'greeting', type: 'string'},
       http: {path: '/sayhi', verb: 'get'}
     }
); 

This call changes the default route to 

Code Block
GET /api/people/sayhi

So a GET request to http://localhost:3000/api/people/sayhi?msg=LoopBack%20developer returns:

Code Block
{"greeting":"Greetings... LoopBack developer"}

Hidden

Extending a model

Add default functions for properties

Code Block
titlecommon/models/order.js
languagejs
module.exports = function(Order) {
  Order.definition.rawProperties.created.default = function() {
    return new Date();
  };
  Order.definition.rebuild(true);
}

Add custom methods

 

Code Block
titlecommon/models/customer.js
languagejs
module.exports = function(Customer) {
  Customer.prototype.getFullName = function() {
    return this.firstName + ' ' + this.lastName;
  };
 
  Customer.listVips = function(cb) {
    this.find({where: {vip: true}}, cb);
  } 
} 

Adding ACLs to remote methods

To constrain access to custom remote methods, use the ACL generator in the same way you control access to any model API. The access type for custom remote methods is Execute.

Basic use

For example, to deny invocation of the greet method used in the examples above:

Code Block
titleshell
Ω slc loopback:acl
[?] Select the model to apply the ACL entry to: Person
[?] Select the ACL scope: A single method
[?] Enter the method name: greet
[?] Select the access type: Execute
[?] Select the role: All users
[?] Select the permission to apply: Explicitly deny access

The tool then creates the following access control specification:

Code Block
title/common/models/person.json
...
  "acls": [
    {
      "principalType": "ROLE",
      "principalId": "$everyone",  // apply the ACL to everyone
      "permission": "DENY",        // DENY attempts to invoke this method
      "property": "greet"          // applies the access control to the greet() method
    }
  ],
...

Advanced use

Another example, to allow invocation of the a remote method only for the $owner of that model object:

Code Block
title/common/models/YourModel.js
languagejs
module.exports = function(YourModel) {
  ...
  YourModel.remoteMethod(
    'someRemoteMethod',
    {
      accepts: [
        {arg: 'id', type: 'number', required: true}
      ],
      // mixing ':id' into the rest url allows $owner to be determined and used for access control
      http: {path: '/:id/some-remote-method', verb: 'get'}
    }
  );
};

Formatting remote method responses

You can reformat the response returned by all remote methods by adding a boot script that modifies the object returned by app.remotes() as follows:

Code Block
title/server/boot/hook.js
module.exports = function(app) {
  var remotes = app.remotes();
  // modify all returned values
  remotes.after('**', function (ctx, next) {
    ctx.result = {
      data: ctx.result
    };

    next();
  });
};

Dup lb article