Hapi.jsでHappy Coding - Part1: ルーティングとSwaggerプラグイン


Node.jsでREST APIを作成するフレームワークを調べていますがHapi.jsが良い感じです。いくつかチュートリアルで基本的な操作を勉強していきます。プラグインで機能を拡張することができるためベースはとても小さくできています。Swaggerのプラグインがあったので使ってみます。ただしLoopBackと違いメタデータを自分で定義する必要があります。

プロジェクト

今回作成するプロジェクトのディレクトリ構成です。ソースコードはリポジトリswaggerタグでpushしています。

$ cd ~/node_apps/docker-hapi
$ tree -L 1
.
├── Dockerfile
├── app.js
├── docker-compose.yml
├── mongo
├── node_modules -> /dist/node_modules
├── npm-debug.log
└── package.json

docker-compose.ymlのmongoサービスでdataディレクトリをカレントにマウントしています。mongoディレクトリの所有はrootになるのでbuild時にエラーになります。MongoDBのデータディレクトリをDockerイメージに追加しないように、.dockerignoreに追加して無視します。

~/node_apps/docker-hapi/.dockerignore
mongo

今回使うHapi.jsのプラグインのhapi-swaggerがNode.jsのバージョンに0.10.xを指定しているためベースイメージもこれにあわせます。

package.json
  "engines": {
    "node": "0.10.x"
  },

これからこのプロジェクトでHapi.jsのプラグインとMongoDBを使ったサンプルを書いていこうと思います。

~/node_apps/docker-hapi/package.json
{
  "name": "docker-hapi",
  "description": "node-static app",
  "version": "0.0.1",
  "private": true,
  "dependencies": {
      "hapi": "^8.6.1",
      "hapi-swagger": "^0.7.3",
      "good-console": "^5.0.2",
      "joi": "^6.4.3",
      "mongoose": "^4.0.4"
  },
  "scripts": {"start": "node app.js"}
}

ルーティング

SinatraやExpressと同じようにルーティングはHTTPメソッドとURLのパターンで構成します。

Hello World

やはり最初は公式のGetting Startedから始めます。写経して感じをつかむのには丁度良い長さです。定番のHello Worldをapp.jsに実装します。

~/node_apps/docker-hapi/app.js
'user strict';

var Hapi = require('hapi'),
    server = new Hapi.Server();

server.connection({port: 3000});

server.route({
    method: 'GET',
    path: '/{name}',
    handler: function(request, reply) {
        reply('Hello, ' + encodeURIComponent(request.params.name));
    }
});

server.start(function() {
    console.log('Server running at:', server.info.uri);
});

app.jsにパラメータ付きのpathでGETメソッドのRouteを1つ定義しています。URLのパラメーターはpathに定義したnameにバインドされて、request.params.nameの変数に格納されます。

$ curl -X GET localhost:3000/masato
Hello, masato

JSON

次はBuild RESTful API Using Node and Hapiを参考にしながらHapi.jsの使い方を勉強していきます。

app.jsに静的なJSONを返すRouteを追加します。APIの追加はmethod、path、handlerを追加していくのが基本的なコードになります。

~/node_apps/docker-hapi/app.js
....
server.route({
    method: 'GET',
    path: '/api/jobs',
    handler: function(request, reply) {
        reply({
            statusCode: 200,
            message: 'List all jobs',
            data: [
                {
                    name: 'Daily BABYMETAL',
                    query: 'babymetal'
                },{
                    nama: 'Hourly Android',
                    query: 'android'
                }
            ]
        });
    }
});
...

作成したRouteのpathをcurlでGETします。handlerでreplyしたJSONが返ります。

$ curl -X GET localhost:3000/api/jobs
{"statusCode":200,"message":"List all jobs","data":[{"name":"Daily BABYMETAL","query":"babymetal"},{"nama":"Hourly Andrond","query":"android"}]}

プラグイン

Swagger

Hapi.jsはプラグインを追加することで認証やAPIドキュメントなどの機能を追加していくことができます。
registerメソッドを使ってプラグインを追加します。

~/node_apps/docker-hapi/app.js
...
server.register({
    register: require('hapi-swagger'),
    options: {
        apiVersion: "0.0.1"
    }
}, function(err){
    if(err) {
        server.log(['error'], 'hapi-swagger load error: ' + err)
    } else {
        server.log(['start'], 'hapi-swagger interface loaded')
    }
});
...

SwaggerでAPIドキュメントを作成するため、RouteにSwagger用のconfigを追加します。tagsは必須項目になっています。

~/node_apps/docker-hapi/app.js
...
server.route({
    method: 'GET',
    path: '/api/jobs',
    config: {
        tags: ['api'],
        description: 'List all jobs',
        notes: 'List all jobs'
    },
...

Docker Composeをupします。

$ docker-compose up

/documentationをブラウザで開くとSwagger UIが使えるようになります。