LoginSignup
50
53

More than 5 years have passed since last update.

LoopBack.jsで高速REST API開発 〜ゼロから開発、APIの使い方まで〜

Posted at

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-apptodo-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を使用している関係でhost192.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の画面が表示されます。

Kobito.bp6NAS.png

APIを使ってみる

Swaggerの画面では、REST APIに対する各種操作が可能になっています。デモデータとしてあらかじめ追加してあるToDoタスクを取得できるか試してみましょう。

GET /Accounts/{id}/toDosのパスをクリックし、操作画面を開きます。Parametersの下にあるidの欄に1を入力してTry it out!ボタンをクリックします。

Kobito.6fwCzQ.png

401エラーが返ってきました。実は、AccountモデルはビルトインのUserモデルを継承していて、アクセス制限がかかっています。認証周りの実装の手間が省けるのは非常に便利です。

画面を少し下に移動して、POST /Accounts/loginを開きましょう。credentialsの欄に以下の認証情報を入力し、Try it out!ボタンをクリックします。

{
  "email": "foo@foo.com",
  "password": "foo"
}

Kobito.jvagwY.png

200が返ってきたらOKです。レスポンスの中のidがアクセストークンで、アクセス制限がかかっているパスにアクセスするときに必要になります。

画面右上にこのアクセストークンを設定するところがあるので、テキストボックスにトークンを入力してSet Access Tokenボタンをクリックしてください。

Kobito.HNM6Gb.png

ログインができたので、再度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タスクを取得してみましょう。

Kobito.LhMR1e.png

上図のようにレスポンスとして3つのToDoタスクが表示されたら成功です。

まとめ

ゼロからLoopBackアプリケーションを作成し、実際にREST APIを操作するところまで解説しました。コマンドベースでアプリケーションが作成できる手軽さと、オンラインドキュメントや認証機能などAPIとして必要な機能があらかじめ備わっているというのは非常に便利です。

LoopBack.jsの記事はあまり多くないので、今後増えていくことを期待しています^^

50
53
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
50
53