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に追加して無視します。
mongo
今回使うHapi.jsのプラグインのhapi-swaggerがNode.jsのバージョンに0.10.xを指定しているためベースイメージもこれにあわせます。
"engines": {
"node": "0.10.x"
},
これからこのプロジェクトでHapi.jsのプラグインとMongoDBを使ったサンプルを書いていこうと思います。
{
"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に実装します。
'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を追加していくのが基本的なコードになります。
....
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メソッドを使ってプラグインを追加します。
...
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は必須項目になっています。
...
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が使えるようになります。