LoopBack.jsはサクッとREST APIを作るためのNode.jsフレームワークです。コマンドラインのジェネレーターを駆使してモデルを作っていくので、コーディングが少なく済みます。また、REST APIのオンラインドキュメントを生成してくれるSwaggerが組み込まれていて非常に便利です。
作成するモデル
今回はシンプルなToDoアプリを作ることを想定して、以下の様なモデルを作成します。
- Accountモデル: ToDoアプリのユーザ
- ToDoモデル: ToDoタスク
LoopBack.jsではビルトインのUserモデルが用意されていて、認証機能などがあらかじめ組み込まれています。今回AccountモデルはこのUserモデルを継承させるため、特に追加のプロパティは持たせません。
ToDoモデルについては以下のプロパティを持たせます。
プロパティ名 | 型 | 説明 |
---|---|---|
title | string | ToDoタスクのタイトル |
done | boolean | タスクの状態(完了or未完了) |
モデル間のリレーションは以下のように定義します。
- Account has many ToDo
- ToDo belongs to Account
データソース
LoopBack.jsではデータの保存先を以下から選択できます。
- Cloudant
- DB2
- メモリDB
- MongoDB
- MySQL
- Oracle
- PostgreSQL
- Redis
- SQL Server
今回はMySQLを使います。
環境準備
Node.jsはインストール済みとします。また、今回MySQLはDockerコンテナで動かす手順になっていますが、ローカルに直接インストールされている場合などはIPアドレスなど読み替えてください。
strongloopパッケージをグローバルインストールしておきます。
$ npm install strongloop -g
雛形作成
まずはアプリケーションの雛形を作成します。
$ slc loopback
雛形作成にあたり以下3つ質問してきますので、それぞれtodo-app
、todo-app
と入力、最後はapi-server
を選択してください。
? What's the name of your application? todo-app
? Enter name of the directory to contain the project: todo-app
? What kind of application do you have in mind? api-server (A LoopBack API server with local User auth)
このあと依存パッケージのインストールが自動で始まります。インストールが完了したら、todo-app
というディレクトリが作成されているはずです。以降のコマンドはこのディレクトリのルートパスで実行します。
モデル作成
雛形ができたら、次はモデルを作っていきます。
まずはAccountモデル。
$ slc loopback:model
雛形作成時と同様に作成するモデルについて質問してくるので、以下の通り回答してください。
? Enter the model name: Account
? Select the data-source to attach undefined to: db (memory)
? Select model's base class User
? Expose Account via the REST API? Yes
? Custom plural form (used to build REST URL):
? Common model or server only? server
Let's add some Account properties now.
Enter an empty property name when done.
? Property name:
次はToDoモデル。
$ slc loopback:model
? Enter the model name: ToDo
? Select the data-source to attach undefined to: db (memory)
? Select model's base class PersistedModel
? Expose ToDo via the REST API? no
? Common model or server only? server
Let's add some ToDo properties now.
Enter an empty property name when done.
? Property name: title
invoke loopback:property
? Property type: string
? Required? Yes
? Default value[leave blank for none]:
Let's add another ToDo property.
Enter an empty property name when done.
? Property name: done
invoke loopback:property
? Property type: boolean
? Required? Yes
? Default value[leave blank for none]:
Let's add another ToDo property.
Enter an empty property name when done.
? Property name:
リレーション作成
モデル間のリレーションを作成します。こちらもコマンドから行います。
まずはAccount has many ToDo
というリレーションを作成します。
$ slc loopback:relation
? Select the model to create the relationship from: Account
? Relation type: has many
? Choose a model to create a relationship with: ToDo
? Enter the property name for the relation: toDos
? Optionally enter a custom foreign key:
? Require a through model? No
次はToDo belongs to Account
というリレーションを作成します。
$ slc loopback:relation
? Select the model to create the relationship from: ToDo
? Relation type: belongs to
? Choose a model to create a relationship with: Account
? Enter the property name for the relation: account
? Optionally enter a custom foreign key:
MySQLサーバ起動
ここではDockerを使います。
$ docker run --name mysql -e MYSQL_ROOT_PASSWORD=r00t! -e MYSQL_DATABASE=loopback -e MYSQL_USER=todo -e MYSQL_PASSWORD=^todo$ -d -p 3306:3306 mysql
以下の設定をしています。
- ルートパスワード: r00t!
- データベース名: loopback
- ユーザ名: todo
- パスワード: ^todo$
データソース設定
モデルの保存先となるデータソースの設定を行います。これまで同様コマンドから行います。
$ slc loopback:datasource
? Enter the data-source name: todoDB
? Select the connector for todoDB: MySQL (supported by StrongLoop)
Connector-specific configuration:
? Connection String url to override other settings (eg: mysql://user:pass@host/db):
? host: 192.168.99.100
? port: 3306
? user: todo
? password: ******
? database: loopback
? Install loopback-connector-mysql@^2.2 Yes
今回DockerToolboxを使用している関係でhost
が192.168.99.100
になっています。MySQLがローカルで起動している場合はlocalhost
にするなど変更してください。
データソースの指定
slc loopback
コマンドによって雛形を作成した場合、モデルの保存先はデフォルトではメモリDBが指定されています。これを先ほど作成したtodoDB(MySQL)
に変更します。
データソースの指定はserver/model-config.json
で行います。現在は以下のようになっています。
{
"_meta": {
"sources": [
"loopback/common/models",
"loopback/server/models",
"../common/models",
"./models"
],
"mixins": [
"loopback/common/mixins",
"loopback/server/mixins",
"../common/mixins",
"./mixins"
]
},
"User": {
"dataSource": "db"
},
"AccessToken": {
"dataSource": "db",
"public": false
},
"ACL": {
"dataSource": "db",
"public": false
},
"RoleMapping": {
"dataSource": "db",
"public": false
},
"Role": {
"dataSource": "db",
"public": false
},
"Account": {
"dataSource": "db",
"public": true
},
"ToDo": {
"dataSource": "db",
"public": false
}
}
"dataSource": "db"
となっている箇所を全て"dataSource": "todoDB"
に変更してください。
{
"_meta": {
"sources": [
"loopback/common/models",
"loopback/server/models",
"../common/models",
"./models"
],
"mixins": [
"loopback/common/mixins",
"loopback/server/mixins",
"../common/mixins",
"./mixins"
]
},
"User": {
"dataSource": "todoDB"
},
"AccessToken": {
"dataSource": "todoDB",
"public": false
},
"ACL": {
"dataSource": "todoDB",
"public": false
},
"RoleMapping": {
"dataSource": "todoDB",
"public": false
},
"Role": {
"dataSource": "todoDB",
"public": false
},
"Account": {
"dataSource": "todoDB",
"public": true
},
"ToDo": {
"dataSource": "todoDB",
"public": false
}
}
マイグレーションスクリプトの作成
アプリケーション起動時にMySQLサーバのテーブル作成とデモデータの追加を行うためのスクリプトを作成します。
LoopBack.jsでは、server/boot/*.js
という名前のJavaScriptファイルを起動時に読み込む用になっています。ではserver/boot/automigrate.js
というファイルを作成します。
var async = require('async');
module.exports = function(app) {
ds = app.dataSources.todoDB;
async.waterfall([
createAccounts,
createTodos
], function(err, result) {
if (err) console.log('Error: ' + err);
console.log('Success!');
});
function createAccounts(callback) {
ds.automigrate(['Account', 'AccessToken', 'ACL', 'RoleMapping', 'Role'], function(err) {
if (err) return callback(err);
var accounts = [
{
email: 'foo@foo.com',
password: 'foo'
},
{
email: 'bar@bar.com',
password: 'bar'
},
{
email: 'baz@baz.com',
password: 'baz'
}
];
app.models.Account.create(accounts, callback);
});
}
function createTodos(accounts, callback) {
ds.automigrate('ToDo', function(err) {
if (err) return callback(err);
var todos = [];
for (var i = 0, len = accounts.length; i < len; i++) {
todos.push(createSampleTodo(accounts[i]));
}
app.models.ToDo.create(todos, callback);
});
function createSampleTodo(account) {
var name = account.email.split('@')[0];
return [
{
title: name + '-task1',
done: false,
accountId: account.id
},
{
title: name + '-task2',
done: true,
accountId: account.id
},
{
title: name + '-task3',
done: false,
accountId: account.id
}
];
}
}
};
async.js
を使用しているので、インストールしてください。
$ npm install async
スクリプトの中で登場するautomigrate()
メソッドは、もしすでに同名のテーブルが存在していた場合、テーブルを再作成します。なので、アプリケーションを起動する度にテーブルを作り直し、デモデータを追加し直しますので注意してください。
アプリケーション起動
以上で準備が完了しました。以下のコマンドでアプリケーションを起動してください。
$ node .
Web server listening at: http://0.0.0.0:3000
Browse your REST API at http://0.0.0.0:3000/explorer
Success!
ブラウザでhttp://0.0.0.0:3000/explorer
にアクセスすると、Swaggerの画面が表示されます。
APIを使ってみる
Swaggerの画面では、REST APIに対する各種操作が可能になっています。デモデータとしてあらかじめ追加してあるToDoタスクを取得できるか試してみましょう。
GET /Accounts/{id}/toDos
のパスをクリックし、操作画面を開きます。Parameters
の下にあるid
の欄に1
を入力してTry it out!
ボタンをクリックします。
401エラーが返ってきました。実は、AccountモデルはビルトインのUserモデルを継承していて、アクセス制限がかかっています。認証周りの実装の手間が省けるのは非常に便利です。
画面を少し下に移動して、POST /Accounts/login
を開きましょう。credentials
の欄に以下の認証情報を入力し、Try it out!
ボタンをクリックします。
{
"email": "foo@foo.com",
"password": "foo"
}
200が返ってきたらOKです。レスポンスの中のid
がアクセストークンで、アクセス制限がかかっているパスにアクセスするときに必要になります。
画面右上にこのアクセストークンを設定するところがあるので、テキストボックスにトークンを入力してSet Access Token
ボタンをクリックしてください。
ログインができたので、再度GET /Accounts/{id}/toDos
のところに戻ってToDoタスクを取得できるか試してみましょう。
、、、実はこの時点ではまだ401エラーになります。Userモデルではあらゆるアクセスがデフォルトで制限されているため、明示的に許可してあげる必要があるのです。
ACL設定
Accountモデルに対し、ACL(Access Control List)を設定します。
$ slc loopback:acl
? Select the model to apply the ACL entry to: Account
? Select the ACL scope: A single method
? Enter the method name __get__toDos
? Select the role The user owning the object
? Select the permission to apply Explicitly grant access
__get__toDos
という名前のメソッドを、ToDoモデルのオーナーにだけ実行を許可するという設定をしています。これにより、ToDoタスクの取得操作が可能になります。
ToDoタスクの作成や削除をさせたい場合は、さらにACLを追加する必要があります。対応するメソッド名は公式ドキュメントを参照ください。
ToDoタスク取得
これで全ての準備が完了です。先ほどと同様の手順でログイン、アクセストークンをセットし、ToDoタスクを取得してみましょう。
上図のようにレスポンスとして3つのToDoタスクが表示されたら成功です。
まとめ
ゼロからLoopBackアプリケーションを作成し、実際にREST APIを操作するところまで解説しました。コマンドベースでアプリケーションが作成できる手軽さと、オンラインドキュメントや認証機能などAPIとして必要な機能があらかじめ備わっているというのは非常に便利です。
LoopBack.jsの記事はあまり多くないので、今後増えていくことを期待しています^^