Page Contents
Page Contents

See also:

See also:

概要

远程方法是model的静态方法, 做为一个自定义的REST endpoint暴露出来。使用远程方法添加LoopBack standard model REST API没有提供的方法。

如何定义一个远程方法

定义远程方法:

  1. 在 /common/models 目录下面创建一个JS文件,文件名为你对应model.json的文件名;例如,你想给Person模型添加一个远程方法,那么你应该在 /common/models 目录下面创建person.js文件。
  2. 定义一个静态方法去处理请求。
  3. 调用remoteMethod(), 注册远程方法,它有两个参数:
    1. 第一个参数是字符串类型的,它应该是你在第二步新建的静态方法的方法名。
    2. 第二个参数 (可选) ,它给你的REST endpoint提供了一些配置。

例如

假设你有一个Person模型, 你想给它添加一个REST endpoint  - /greet, 它会根据请求的name,返回一个问号. 在/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'
      }
    }
  );
};

现在,请求

POST /api/people/greet

请求数据:{"msg": "John"}

返回:

shell

Greetings... John!

注册远程方法

所有的LoopBack模型都有一个静态方法remoteMethod() , 你可以通过它来注册一个远程方法:

_model_.remoteMethod(_requestHandlerFunctionName_, [_options_])

  • _model_是你想添加添加远程方法的模型对象,例如People。
  • requestHandlerFunctionName 是你的远程方法的方法名,例如'greet'。
  • options 是一个对象包含了一些http参数; 如下。

Options

Options参数是一个配置远程方法REST的键值对的Javascript对象。

选项 描述 例子
accepts

定义远程方法接受的参数。这些参数对应你model对应静态方法的参数。如上面的例子,你的方法签名如下:

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

`name` 是第一个参数,`age` 是第二个参数,callback由LoopBack自动提供(你不需要在accepts数组里面指定这个callback参数)。更多信息,请见 Argument descriptions.

默认accepts是一个空数组 []。

{  ...
  accepts: [
   {arg: 'name', type: 'string'},
   {arg: 'age', type: 'number'},...],
  ... }
returns

描述远程方法callback的参数;见 Argument descriptions. err参数假定已经就有了,不需要特别指定。

默认returns是一个空数组[]。

returns: {arg: 'greeting', type: 'string'}
http.path

HTTP path (相对于model) 指定你的远程方法通过什么url暴露出来。

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

HTTP 方法 (verb)指定你的远程方法通过哪种HTTP方法暴露。

  • get
  • post (默认)
  • put
  • del
  • all
http: {path: '/sayhi', verb: 'get'}
description

方法的描述,被API文档生成器(如Swagger)所使用。

可以把一个长的字符串放到一个数组中去 (见下面的note)。

 
notes

额外的备注,被API文档生成器(如Swagger)所使用。

可以把一个长的字符串放到一个数组中去 (见下面的note)。

 

参数描述

accepts 和 returns 可以是一个对象也可以是一个数组。下面的表格解释了每一个参数的用途。

属性 类型 描述
arg String 参数名
type String 参数类型;必须是一个Loopback type.
description String 或 Array

一段描述参数的文本。被API文档生成器(如Swagger)所使用

你可以把一个长的描述分割成数段放到一个字符串数组中去

[
"Lorem ipsum dolor sit amet, consectetur adipiscing elit,"
"sed do eiusmod tempor incididunt ut labore et dolore",
"magna aliqua."
required Boolean True代表这个参数是必填的;false代表可选。
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).
http String 针对输入参数:一个function或者一个对象,用来指定如何获取这个参数的值。更对见 HTTP mapping of input arguments

例如,单个参数 (一个对象):

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

多个参数(一个数组):

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

  • 通过一个对象的source属性
  • 通过一个自定义映射方法

通过一个对象的source属性

source的值如下。

source属性的值 描述
body 整个request body做为一个值The whole request body is used as the value.
form
query
path 

值通过req.param获得, 会搜索路由参数,request body和query string.

query和path是form的别名。

req 整个HTTP请求对象被最为一个值。

例如, 一个参数将整个request body做为值 an argument getting the whole request body as the value:

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

通过一个自定义映射方法Using a custom mapping function

例如:

{
  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');
  }
}

如果你没有指定一个映射,LoopBack会通过下面的方式来决定参数的值(假设要解析name这个输入参数的值)。

  1. 如果HTTP请求参数是一个JSON,那么使用args[‘name’]来解析其值。
  2. 否则,使用req.param(‘name’)来解析其值。

设置远程方法的路由

默认情况下,一个远程方法是通过下面这样一个url格式暴露的:

POST http://_apiRoot_/_modelName_/_methodName_

  • apiRoot 是应用的API根路径。
  • modelName 是模型名的复数名。
  • methodName 是方法名。

上面的例子,默认情况下远程方法是通过下面的url被暴露的:

POST /api/people/greet

如果想修改路由,可以使用http.path和http.verb,例如:

/common/models/model.js

Person.remoteMethod(
  'greet', {
    accepts: {
      arg: 'msg',
      type: 'string'
    },
    returns: {
      arg: 'greeting',
      type: 'string'
    },
    http: {
      path: '/sayhi',
      verb: 'get'
    }
  }
);

现在通过下面的url来调用这个远程方法:

GET /api/people/sayhi

现在GET请求http://localhost:3000/api/people/sayhi?msg=LoopBack%20developer 返回:

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

Non-public Information

扩展一个model

为属性添加默认函数

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

添加自定义方法

 

common/models/customer.js
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.

Basic use

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

shell

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

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

格式化远程方法的响应输出

你可以格式化所有远程方法的响应输出,只需要添加一个 boot script 修改app.remotes()返回的对象。如下:

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