HogeFugaHogera

IT系の備忘録とか、他徒然なるままに

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')
};

注意として、最初の例では、nameversionを明確にセットした。しかしながら、次の例では、値として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);
    }
});

プラグインにオプションを渡すためには、代わりにregisteroptionsキーを作る。 例えば、

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 サーバは、一つ、もしくは複数のラベルで構成され、vhostprefix修飾子に、プラグインが登録された任意のルートを適用するのも同様である。

例えば、仮に以下のようなプラグインがあるとして:

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) {
});

これは、プラグインのコードを変える事なしに、サーバ上の特定の接続を、プラグインに追加することができる。