See also:
See also:
概要
远程方法是model的静态方法, 做为一个自定义的REST endpoint暴露出来。使用远程方法添加LoopBack standard model REST API没有提供的方法。
Note:
For an introductory example of defining a remote method, see Extend your API in Getting Started.
如何定义一个远程方法
定义远程方法:
- 在
/common/models
目录下面创建一个JS文件,文件名为你对应model.json的文件名;例如,你想给Person模型添加一个远程方法,那么你应该在 /common/models 目录下面创建person.js文件。 - 定义一个静态方法去处理请求。
- 调用
remoteMethod()
, 注册远程方法,它有两个参数:- 第一个参数是字符串类型的,它应该是你在第二步新建的静态方法的方法名。
- 第二个参数 (可选) ,它给你的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!
Note:
注意上面的REST API都使用了person的复数形式people。Loopback暴露plural form of model names for REST API routes.
注册远程方法
所有的LoopBack模型都有一个静态方法remoteMethod()
, 你可以通过它来注册一个远程方法:
_model_.remoteMethod(_requestHandlerFunctionName_, [_options_])
- _
model
_是你想添加添加远程方法的模型对象,例如People。
requestHandlerFunctionName
是你的远程方法的方法名,例如'greet'。
options
是一个对象包含了一些http参数; 如下。
Options
Options参数是一个配置远程方法REST的键值对的Javascript对象。
Important:
所有的选项属性都是可选的。但是,如果你的远程方法需要接受一个参数,你需要指定accepts参数。如果你的远程方法会返回一个值,你需要指定returns参数。
选项 | 描述 | 例子 |
---|---|---|
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方法暴露。
|
http: {path: '/sayhi', verb: 'get'} |
description |
方法的描述,被API文档生成器(如Swagger)所使用。 可以把一个长的字符串放到一个数组中去 (见下面的note)。 |
|
notes |
额外的备注,被API文档生成器(如Swagger)所使用。 可以把一个长的字符串放到一个数组中去 (见下面的note)。 |
Important:
你可以把一个长的描述分割成数段放到一个字符串数组中去。例如:
[
"Lorem ipsum dolor sit amet, consectetur adipiscing elit,"
"sed do eiusmod tempor incididunt ut labore et dolore", "magna aliqua."]
参数描述
accepts
和 returns 可以是一个对象也可以是一个数组。下面的表格解释了每一个参数的用途。
属性 | 类型 | 描述 |
---|---|---|
arg | String | 参数名 |
type | String | 参数类型;必须是一个Loopback type. |
description | String 或 Array |
一段描述参数的文本。被API文档生成器(如Swagger)所使用。 你可以把一个长的描述分割成数段放到一个字符串数组中去。 [ |
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 |
值通过 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这个输入参数的值)。
- 如果HTTP请求参数是一个JSON,那么使用args[‘name’]来解析其值。
- 否则,使用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
为属性添加默认函数
<div class="codeHeader panelHeader pdl" style="border-bottom-width: 1px;"><b>common/models/order.js</b></div>
<div class="codeContent panelContent pdl"><pre class="theme: Emacs; brush: js; gutter: false" style="font-size:12px;">module.exports = function(Order) { Order.definition.rawProperties.created.default = function() {
return new Date(); }; Order.definition.rebuild(true); }</pre></div>
添加自定义方法
<div class="codeHeader panelHeader pdl" style="border-bottom-width: 1px;"><b>common/models/customer.js</b></div>
<div class="codeContent panelContent pdl"><pre class="theme: Emacs; brush: js; gutter: false" style="font-size:12px;">module.exports = function(Customer) { Customer.prototype.getFullName = function() {
return this.firstName + ' ' + this.lastName; }; Customer.listVips = function(cb) {
this.find({where: {vip: true}}, cb); } } </pre></div>
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();
});
};