A remote method is a static method of a model, exposed over a custom REST endpoint.
Page Contents

Overview

A remote method is a 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.

How to add a remote method to a model

To add a remote method to a model:

  1. Create a function in the model extension file. The method name determines whether a remote method is static or an instance method. A method name starting with prototype. indicates an instance method; otherwise, it’s a static method. NOTE: By default, a remote method is static. You must specify prototype. in the method name to create an instance method.

  2. Register the remote method one of these two ways:

Example

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:

/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:

Greetings... John!

Using async/await

Remote methods can also return a promise instead of using the callback parameter.

/common/models/person.js

module.exports = function(Person){

    Person.greet = async function(msg) {
        return 'Greetings... ' + msg;
    }

    Person.remoteMethod('greet', {
          accepts: {arg: 'msg', type: 'string'},
          returns: {arg: 'greeting', type: 'string'}
    });
};

Registering a remote method

There are two ways to register a remote method:

Registering a remote method in code

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

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 Options below.

Registering a remote method in JSON

To register a remote method in the model definition JSON file, add the method name as a key under methods. To define an instance method, prepend prototype. to the method name.

"methods": {
    "prototype.getProfile": {
      "accepts": [],
      "returns": { "arg": "data", "type": "User", "root": true},
      "http": {"verb": "get", "path": "/profile"},
      "accessScopes": ["read", "read:profile"]
    },
    "someStaticMethod" : { ... }

The value of each key under methods is the options object described below.

Options

The options argument is a Javascript object that defines how the remote method works.

Option Description Example
accepts Defines arguments that the remote method accepts that map to the static method you define. For the example above, the function signature is
Person.greet(name, age, callback)...
so 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 information, see Argument descriptions.

The default value is the empty array, [ ].
{  ...
accepts: [
 {arg: 'name', type: 'string'},
 {arg: 'age',  type: 'number'},
 ...],
... }
accessScopes Defines access scopes. A user will be allowed to invoke this remote method only when their access token was granted at least one of the scopes defined by `accessScopes` list. See also Authorization scopes.

The default value is a list with a single scope DEFAULT.
accessScopes: [
  'read',
  'read:user'
]
description Text description of the method, used by API documentation generators such as OpenAPI (formerly Swagger). You can put long strings in an array if needed (see note below).
http Specifies information about the route at which the method is exposed. See http property below.
notes Additional notes, used by OpenAPI (formerly Swagger). You can put long strings in an array if needed (see note below).
documented If set to false, this method will not be present in generated OpenAPI (formerly Swagger) documentation.
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, [].
returns: {arg: 'greeting',
          type: 'string'}

http property

The http property provides information on HTTP route at which the remote method is exposed.

Option Description Example
path HTTP path (relative to the model) at which the method is exposed.
http: {path: '/sayhi'}
verb HTTP method (verb) at which the method is available. One of:
  • get
  • post (default)
  • patch
  • put
  • del
  • all
http: {path: '/sayhi',
       verb: 'get'}
status Default HTTP status set when the callback is called without an error.
http: {status: 201}
errorStatus Default HTTP status set when the callback is called with an error.
http: {errorStatus: 400}

Argument descriptions

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) Type Description
arg String Argument name
description String or Array A text description of the argument. This is used by API documentation generators like OpenAPI (formerly Swagger). You can put long strings in an array if needed (see note above).
http Object or Function For input arguments: a function or an object describing mapping from HTTP request to the argument value. See HTTP mapping of input arguments below.
http.target String 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
required Boolean True if argument is required; false otherwise.
root Boolean 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).
type String Argument datatype; must be a Loopback type. Additionally, callback arguments allow a special type "file"; see below.
default String Default 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.
documented Boolean If set to false, this parameter will not be present in generated OpenAPI (formerly Swagger) documentation.

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'}
]

Returning a file (stream) response

Specify { type: 'file', root: true } for a callback argument that will be sent directly as the response body. A file argument can be set to one of the following values:

Example:

module.exports = function(MyModel) {
  MyModel.download = function(cb) {
    // getTheStreamBody() can be implemented by calling http.request() or fs.readFile() for example
    getTheStreamBody(function(err, stream) {
      if (err) return cb(err);
      // stream can be any of: string, buffer, ReadableStream (e.g. http.IncomingMessage)
      cb(null, stream, 'application/octet-stream');
    });
  };

  MyModel.remoteMethod('download', {
    returns: [
      {arg: 'body', type: 'file', root: true},
      {arg: 'Content-Type', type: 'string', http: { target: 'header' }}
    ]
  });
};

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 property Description
body The whole request body is used as the value.
form The value is looked up using req.body which searches the request body
query The value is looked up using req.query which searches the query string
path The value is looked up using req.params which searches the route arguments
req The Express HTTP request object.
res The Express HTTP response object.
context The whole context object, which holds request and response objects.

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

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

Another example showing the Express HTTP request and response objects:

[
 {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:

{
  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

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

Setting a remote method route

By default, a remote method is exposed at:

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, by default the remote method is exposed at:

POST /api/people/greet

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

/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 

GET /api/people/sayhi

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

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

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:

$ lb 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:

/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:

/common/models/YourModel.js

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:

/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();
  });
};

Disabling a remote method

To disable a remote method use Model.disableRemoteMethod(name, isStatic) and Model.disableRemoteMethodByName(name). For more information, see: