リモートメソッドは、独自のRESTエンドポイントを通じて公開される、モデルの静的メソッドです。
Page Contents

概要

リモートメソッド は、独自のRESTエンドポイントを通じて公開される、モデルのメソッドです。 LoopBackの標準モデルREST APIで提供されていない操作を行うには、リモートメソッドを使います。

モデルにリモートメソッドを追加する方法

モデルにリモートメソッドを追加するには、以下のようにします。

  1. モデル拡張ファイル に関数を作成します。メソッド名によってリモートメソッドが静的メソッドかインスタンスメソッドか決まります。メソッド名がprototype.で始まるものは、インスタンスメソッドになります。さもなくば、静的メソッドになります。:既定では、リモートメソッドは静的です。インスタンスメソッドを作るには、メソッド名の先頭にprototype.を指定しなければなりません。

  2. 以下の方法のいずれかで、リモートメソッドを登録します。

Perosonモデルが既に存在し、/greet というエンドポイントを追加して、リクエストで与えられた名前に対して挨拶を返すようにしたいとします。 /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'}
    });
};

そして、例えば、以下のURLに対して、

POST /api/people/greet

{"msg": "John"} というデータを送信すると、以下のような応答が得られるはずです。

Greetings... John!

リモートメソッドを登録する

リモートメソッドを登録する方法は2つあります。

コードでリモートメソッドを登録する

LoopBack のモデルはremoteMethod() という、リモートメソッドを登録する静的メソッドを持っています。

Model.remoteMethod(requestHandlerFunctionName, [options])

ここで、

  • model は、リモートメソッドを追加したいモデルオブジェクトです。例えば Person などです。
  • requestHandlerFunctionName はリモートメソッドの名前を指定する文字列です。例えば 'greet' などです。
  • options は、RESTエンドポイントを設定するパラメータを指定するオブジェクトです。以下の オプション を参照してください。

JSONでリモートメソッドを登録する

モデル定義JSONファイル でリモートメソッドを登録するには、 methods キーの下にメソッド名を追加します。インスタンスメソッドを定義するには、メソッド名の前にprototype.をつけてください。

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

methodsのは以下にあるそれぞれのキーの値は、以下で説明するオプションオブジェクトです。

オプション

オプション引数は、リモートメソッドがどのように動作するかを定義するJavaScriptオブジェクトです。

オプション 説明
accepts リモートメソッドが受け付けて、静的メソッドに渡す引数を定義する。上の例では、関数のシグネチャは
Person.greet(name, age, callback)...
であるため、nameが最初の引数、ageが2つ目の引数、そしてコールバックが自動的にLoopBackによって提供される(accepts配列には指定しないこと)。詳細は、引数の説明を参照ください。

既定値は空の配列 [ ] です。
{  ...
accepts: [
 {arg: 'name', type: 'string'},
 {arg: 'age',  type: 'number'},
 ...],
... }
accessScopes ユーザーは、自身のアクセストークンが `accessScopes` リストで定義されたスコープの内、どれか1つ以上で許可されているときのみ、 このリモートメソッドを呼び出すことができる。 認証スコープを参照ください。

既定値は DEFAULT という単一の値を持つリストです。
accessScopes: [
  'read',
  'read:user'
]
description メソッドを説明する文章。OpenAPI(旧 Swagger)のような APIドキュメント生成ツールによって使われる。 必要に応じて、長い文字列を配列に入れることもできる(以下参照)。
http メソッドが公開されるルートを指定する。 下にあるhttp プロパティ を参照ください。
notes OpenAPI(旧Swagger)によって使われる追加の注記。 必要に応じて、長い文字列を配列に入れることもできる(以下参照)。
documented falseにした場合、このメソッドはOpenAPI(旧Swagger)が生成した文書には登場しなくなる。
returns リモートメソッドのコールバック引数を指定する。引数の説明を参照ください。 err引数は暗黙のうちに指定されるので、記述しないこと。 既定では、空の配列 [] です。
returns: {arg: 'greeting',
          type: 'string'}

http プロパティ

http プロパティは、リモートメソッドが公開されるHTTPルートについての情報を提供します。

オプション 説明
path HTTP path (relative to the model) at which the method is exposed. モデルが公開される HTTP パス (モデルに対する相対パス)
http: {path: '/sayhi'}
verb メソッドを呼び出せる HTTP メソッド(動詞)。以下のいずれか一つ。
  • get
  • post (既定)
  • patch
  • put
  • del
  • all
http: {path: '/sayhi',
       verb: 'get'}
status エラーなしにコールバックが呼び出された時の、既定の HTTP ステータス。
http: {status: 201}
errorStatus エラー時にコールバックが呼び出された時の、既定の HTTP ステータス。
http: {errorStatus: 400}

引数の説明

accepts returnsオプションのプロパティは、単一の引数をオブジェクトとして、または順序付けされた引数のセットを配列として定義します。 次の表は、個々の引数のプロパティを示しています。

プロパティ (キー) 説明
arg String 引数の名前
description String または Array 引数を説明する文章。OpenAPI(旧Swagger)のようなAPI文書生成ツールによって使われる。 必要に応じて、長い文字列を配列に入れることもできる(上の注記参照)。
http オブジェクトまたは関数 引数について: HTTPリクエストと引数の値を紐付けを記述する関数またはオブジェクト。下にある入力引数とHTTPのマッピングを参照ください。
http.target String コールバック引数の値と、HTTPレスポンスオブジェクトを紐付ける。以下の値がサポートされている。
  • statusres.statusCode にセットする値を指定する
  • headerhttp.header または arg という名前のヘッダにセットする値を指定する
required Boolean 引数が必須の場合は、true にする。さもなくば false にする。
root Boolean コールバックの引数として: 関数が、単一のコールバック引数を取り、リモートの呼び出し側に返却する大本のオブジェクトとして使いたい場合、 このプロパティを trueにする。 さもなくば、大本のオブジェクトはマップ(引数の名前と値)になる。
type String 引数のデータ型。 Loopbackの型のいずれかでなければならない。 加えて、コールバック引数は、特別な型として「file」を指定できる。以下を参照。
default String loopback-explorer の入力フィールドやswaggerの文書を作るために使われる既定値。 : この値は、引数が存在しない場合は、リモートメソッドに渡されることはない。
documented Boolean falseにすると、このパラメータは OpenAPI(旧Swagger)が生成する文書には登場しなくなる。

例えば、単一の引数はオブジェクトで以下のように指定できる。

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

複数の引数は、配列で指定する。

[
  {arg: 'arg1', type: 'number', required: true},
  {arg: 'arg2', type: 'array'}
]

ファイル(ストリーム)レスポンスを返す。

コールバック引数として、{ type: 'file', root: true }を指定すると、レスポンスボディを直接送信できる。 ファイル引数は以下のいずれかの値に設定できる。

例:

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 の紐付け

There are two ways to specify HTTP mapping for input parameters (what the method accepts): HTTPと(メソッドが受け付ける)入力パラメータの紐付けを指定する方法が2つあります。

  • source プロパティを持つオブジェクトを提供する。
  • 独自のマッピング関数を指定する。

sourceプロパティを持つオブジェクトを指定する

入力パラメータとHTTPの紐付けに最初の方法を使うには、以下の表に示す値の一つを持つsourceプロパティのあるオブジェクトを提供します。

source プロパティの値 説明
body リクエストボディ全体が値として使われます。
form
query
path
値は、ルート引数・リクエストボディ・クエリ文字列を検索する req.param を使用して参照されます。 querypathformの別名ですので注意してください。
req ExpressのHTTPリクエストオブジェクト
res ExpressのHTTPレスポンスオブジェクト
context リクエストとレスポンスオブジェクトを保持する、context オブジェクト全体。

例えば、リクエストボディ全体を受け取る引数は以下のように指定します。

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

ExpressのHTTPリクエストとレスポンスオブジェクトを使用する例は以下のとおりです。

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

独自のマッピング関数を使う

入力パラメータとHTTPの紐付けを指定する2つ目の方法は、独自のマッピング関数を指定するものです。例えば、以下のようにします。

{
  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リクエストパラメータ args がJSONの中にある場合、それは、args['name'] として扱います。
  2. さもなくば、req.param('name')として使います。

JSONフィールドにないデータを返す。

arg プロパティのある return 引数を指定すると、自動的に 同じ名前のフィールドにデータが格納されたJSONオブジェクトを返します。

メインのレスポンスとして、例えば配列のようなデータを返したい場合、 root プロパティを持つオブジェクトを設定し、arg を消去することで可能です。

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

リモートメソッドルートを指定する

既定では、リモートメソッドは以下のURLで公開されます。

POST http://apiRoot/modelName/methodName

ここで、

  • apiRoot  はアプリケーションのAPI最上位パスです。
  • modelName はモデル名の複数形です。
  • methodName は関数の名前です。

上の例に従うと、リモートメソッドは以下のように公開されます。

POST /api/people/greet

ルートを変更するには、remoteMethod() に渡すオプションの http.pathhttp.verb プロパティを使います。例えば以下のようにします。

/common/models/model.js

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

こうすることで、ルートが以下のように変更されます。

GET /api/people/sayhi

すると、 http://localhost:3000/api/people/sayhi?msg=LoopBack%20developer への GETリクエストは、以下のような値を返します。

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

リモートメソッドにACLを追加する

独自のリモートメソッドへのアクセスを制限するには、他のAPIへのアクセス制御と同様に、ACL生成ツールを使います。 独自のリモートメソッドをアクセス種別は「Execute」です。

基本的な使い方

たとえば、上の例で使った greet メソッドの呼出しを禁止する場合、以下のようにします。

$ 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

これで、以下のようなアクセス制御設定が作成されます。

/common/models/person.json

...
"acls": [{
  "principalType": "ROLE",
  "principalId": "$everyone",  // 全員にACLを適用する
  "permission": "DENY",        // メソッド呼び出しを拒否する
  "property": "greet"          // greet() メソッドにアクセス制御を適用する
}],
...

進んだ使い方

他の例として、リモートメソッドの呼出しをモデルの $owner に限定するには以下のようにします。

/common/models/YourModel.js

module.exports = function(YourModel) {
  //...
  YourModel.remoteMethod(
    'someRemoteMethod',
    {
      accepts: [
        {arg: 'id', type: 'number', required: true}
      ],
      // ':id' を RESTのURLに入れることで、 $owner を判断してアクセス制御が行えるようにする
      http: {path: '/:id/some-remote-method', verb: 'get'}
    }
  );
};

リモートメソッドのレスポンスを整形する

起動スクリプトapp.remotes()が 返すオブジェクトを修正する処理を追加することで、全てのリモートメソッドの戻り値を整形することができます。

/server/boot/hook.js

module.exports = function(app) {
  var remotes = app.remotes();
  // 全ての戻り値を修正する
  remotes.after('**', function (ctx, next) {
    ctx.result = {
      data: ctx.result
    };

    next();
  });
};

リモートメソッドを無効化する

リモートメソッドを無効化するには、Model.disableRemoteMethod(name, isStatic)Model.disableRemoteMethodByName(name) を使います。詳細は以下を参照してください。