hapi: プラグインのチュートリアル
hapiでmongoDBを使おうとして、モジュールを呼び込むために読んだチュートリアルの和訳を載せます。
プラグイン
hapiは、あなたのアプリケーションを個々のビジネスロジックにとても簡単に分割するための多くのパワフルなプラグインシステムと、再利用可能なユーティリティを持っている
プラグインの作製
プラグインを書く事は簡単である。その根底は、function (server, options, next)
という形式のregister
関数を持つオブジェクトである。そのregister
関数の下に、プラグインについての幾つかの追加情報(名前やバージョン等)をhapiに追加するためのattributes
オブジェクトを持つ。
以下の様にとても簡単である:
var myPlugin = { register: function (server, options, next) { next(); } } myPlugin.register.attributes = { name: 'myPlugin', version: '1.0.0' };
外部モジュールとして書かれた場合:
exports.register = function (server, options, next) { next(); }; exports.register.attributes = { pkg: require('./package.json') };
注意として、最初の例では、name
とversion
を明確にセットした。しかしながら、次の例では、値としてpackage.jsonの中身をpkg
パラメータとしてセットした。どちらでも問題はない。
加えて、attributes
オブジェクトは、multiple
キーを持てる。このキーがtrue
なら、同じサーバ上であたなのプラグインが何度でも安全に登録できることをhapiに伝える。
register(登録) メソッド
上記で見たきたように、register
メソッドは3つのパラメータ(setver
, options
, next
)を許す。
options
パラメータは、ユーザがプラグインに渡すどんなオプションであっても、単純である。変更は起きないし、オブジェクトはregister
メソッドに直接渡される。
next
は、プラグインを登録するために必要な手順がすべて終了した時に呼ばれるメソッドである。このメソッドはパラメータerr
のみ許し、プラグインの登録時にエラーが発生した場合のみ定義されるだろう。
server
オブジェクトは、プラグインが読み込まれているserver
への参照である。
server.select()
サーバは、ラベルの付いた接続を追加できる。
var server = new Hapi.Server(); server.connection({ labels: ['api'] });
このラベルは以降、server.select()
メソッドを使用することにより、特定の接続に対してだけ、プラグインとその他の設定を適用する為に使用できる。
例えば、'api'
ラベルの付いた接続にのみルートを追加するには、こう使うだろう。
var api = server.select('api'); api.route({ method: 'GET', path: '/', handler: function (request, reply) { reply('api index'); } });
複数のラベルを、文字列の配列を渡す事により、一度に選択する事でき、この働きは論理ORステートメントと同様である。論理ANDをとるには、以下の様にserver.select()
を繋げて呼ぶ事により可能である。
// backendとapiのラベルの付いた全てのサーバ var myServers = server.select(['backend', 'api']); // backend AND apiのラベルの付いたサーバ var adminServers = server.select('api').select('admin');
server.select()
の返り値は、選択された接続を含むサーバオブジェクトである。
[注釈] ラベルの論理ANDの意味
ラベルの論理ANDをとるといわれても、上の例だと振る舞いが分かりにくいので、APIドキュメントの例を下に載せます。
var Hapi = require('hapi'); var server = new Hapi.Server(); server.connection({ port: 80, labels: ['a', 'b'] }); server.connection({ port: 8080, labels: ['a', 'c'] }); server.connection({ port: 8081, labels: ['b', 'c'] }); var a = server.select('a'); // 80, 8080 var ac = a.select('c'); // 8080
すなわち、接続にはラベルが配列形式で複数指定できるので、同じラベルをもつ接続だけ選択できると意味である。よく見ると、接続にラベルを付ける最初の例も、しっかり配列になっている。
プラグインの読み込み
プラグインは、一つずつ、又は、server.register()
メソッドでまとめて読み込める。
- 単独のプラグインを読み込む
server.register({register: require('myplugin')}, function (err) { if (err) { console.error('Failed to load plugin:', err); } });
server.register([ { register: require('myplugin'), options: {} // 'myplugin'のオプション },{ register: require('yourplugin'), options: {} // 'yourplugin'のオプション } ], function (err) { if (err) { console.error('Failed to load a plugin:', err); } });
プラグインにオプションを渡すためには、代わりにregister
とoptions
キーを作る。
例えば、
server.register({ register: require('myplugin'), options: { message: 'hello' } }, function (err) { });
これらオブジェクトは配列内でも渡せる (=複数のプラグインを読み込む時)。
server.register([{ register: require('plugin1'), options: {} }, { register: require('plugin2'), options: {} }], function (err) { });
プラグインのオプション
コールバック前のserver.register()
には、オプションのパラメータも渡せる。このオブジェクトの説明は、API referenceから見る事ができる。
このオプションのパラメータはhapiによって使われ、ロードされている(複数の)プラグインには渡されない。pre-select サーバは、一つ、もしくは複数のラベルで構成され、vhost
やprefix
修飾子に、プラグインが登録された任意のルートを適用するのも同様である。
例えば、仮に以下のようなプラグインがあるとして:
exports.register = function (server, options, next) { server.route({ method: 'GET', path: '/test', handler: function (request, reply) { reply('test passed'); } }); next(); }; exports.register.attributes = { pkg: require('./package.json'); };
通常、このプラグインが読み込まれたとき、/test
を指すGET
ルートができる。これは、オプション上のprefix
を設定する事により変更ができ、プラグイン上に作られる全てのルートの先頭に、文字列が追加される:
server.register({register: require('myplugin')}, { routes: { prefix: '/plugins' } }, function (err) { });
今、プラグインがロードされたと仮定すると、prefix
オプションにより、/plugins/test
を指すGET
ルートが作られる。
同様にconfig.vhost
パラメータは、デフォルトのvhost
設定に、ロードされているプラグインによって作られた任意のルートが割当てられる。vhost
の設定に関すつ詳細はAPI referenceを見よ。
select
パラメータはserver.select()
全く同じように動き、その中では、関連するプラグインに対し、一つ、またはラベルの配列が渡せる。
server.register({register: require('myplugin')}, { select: ['webserver', 'admin'] }, function (err) { });