カスタム プラグインを開発する

Apigee Edge のドキュメントを表示しています。
Apigee X のドキュメントをご覧ください。

Edge Microgateway v 3.3.x

視聴者

このトピックは、カスタム プラグインを記述して Edge Microgateway 機能を拡張するデベロッパーを対象としています。新しいプラグインを作成するには、JavaScript と Node.js の使用経験が必要です。

カスタム Edge Microgateway プラグインとは

プラグインは、Edge Microgateway に機能を追加する Node.js モジュールです。プラグイン モジュールは一貫したパターンに従い、Edge Microgateway が認識している場所に保存されるため、モジュールが自動的に検出されて実行されます。Edge Microgateway のインストール時に、いくつかの事前定義プラグインが用意されています。これには、認証、Spar Arrest、割り当て、分析用のプラグインが含まれます。既存のプラグインについては、プラグインを使用するをご覧ください。

カスタム プラグインを作成することで、Microgateway に新しい機能を追加できます。デフォルトでは、Edge Microgateway は基本的にターゲット サービスとの間のリクエストとレスポンスを変更せずに渡す安全なパススルー プロキシです。カスタム プラグインを使用すると、Microgateway を通過するリクエストとレスポンスをプログラムで操作できます。

カスタム プラグイン コードを配置する場所

カスタム プラグイン用のフォルダは、Edge Microgateway のインストールの一部として含まれています。

[prefix]/lib/node_modules/edgemicro/node_modules/microgateway-plugins

ここで、[prefix]npm プレフィックス ディレクトリです。詳細については、Edge Microgateway のインストールの「Edge Microgateway がインストールされている場所」をご覧ください。

このデフォルトのプラグイン ディレクトリを変更できます。プラグインの場所をご覧ください。

事前定義されたプラグインの確認

独自のプラグインを開発する前に、事前定義されたプラグインの中に要件を遵守していないものがないか確認することをおすすめします。これらのプラグインは、次の場所にあります。

[prefix]/lib/node_modules/edgemicro/node_modules/microgateway-plugins

ここで、[prefix]npm 接頭辞ディレクトリです。Edge Microgateway のインストールの「Edge Microgateway がインストールされている場所」もご覧ください。

詳細については、Edge Microgateway に提供されている事前定義のプラグインもご覧ください。

簡単なプラグインを作成する

このセクションでは、シンプルなプラグインを作成するために必要な手順を説明します。このプラグインは、レスポンス データを「Hello, World!」という文字列でオーバーライドし、ターミナルに出力します。

  1. Edge Microgateway が実行されている場合は、ここで停止します。
    edgemicro stop
    
  2. cd をカスタム プラグイン ディレクトリに移動します。

    cd [prefix]/lib/node_modules/edgemicro/plugins

    ここで、[prefix]npm プレフィックス ディレクトリです。詳細については、Edge Microgateway のインストールの「Edge Microgateway がインストールされている場所」をご覧ください。

  3. response-override という名前の新しいプラグイン プロジェクトを作成し、そのプロジェクトに cd を作成します。
    mkdir response-override && cd response-override
    
  4. 新しい Node.js プロジェクトを作成します。
    npm init
    
    [Return] を複数回押して、デフォルト値を受け入れます。
  5. テキスト エディタを使用して、index.js という名前の新しいファイルを作成します。
  6. 次のコードを index.js にコピーし、ファイルを保存します。
    'use strict';
    var debug = require('debug')
    
    module.exports.init = function(config, logger, stats) {
    
      return {
       
        ondata_response: function(req, res, data, next) {
          debug('***** plugin ondata_response');
          next(null, null);
        },
        
        onend_response: function(req, res, data, next) {
          debug('***** plugin onend_response');
          next(null, "Hello, World!\n\n");
        }
      };
    }
    
  7. 作成したプラグインを Edge Microgateway 構成に追加する必要があります。ファイル $HOME/.edgemicro/[org]-[env]-config.yaml を開きます。ここで、orgenv は Edge の組織名と環境名です。
  8. 以下に示すように、response-override プラグインを plugins:sequence 要素に追加します。
          ...
          
          plugins:
            dir: ../plugins
            sequence:
              - oauth
              - response-override
              
          ...
    
  9. Edge Microgateway を再起動します。
  10. Edge Microgateway を介して API を呼び出します。Edge Microgateway の設定と構成:
    curl -H 'x-api-key: uAM4gBSb6YoMvTHfx5lXJizYIpr5Jd' http://localhost:8000/hello/echo
    Hello, World!
    

プラグインの構造

次の Edge Microgateway サンプル プラグインは、独自のプラグインを開発する際に遵守するパターンを示しています。このセクションで説明するサンプル プラグインのソースコードは plugins/header-uppercase/index.js. にあります。

  • プラグインは、ルートフォルダに package.jsonindex.js がある標準の NPM モジュールです。
  • プラグインは init() 関数をエクスポートする必要があります。
  • init() 関数は、configloggerstats の 3 つの引数を取ります。これらの引数については、プラグインの init() 関数の引数で説明しています。
  • init() は、関数の存続期間中に特定のイベントが発生したときに呼び出される名前付き関数ハンドラを含むオブジェクトを返します。

イベント ハンドラ関数

プラグインでは、これらのイベント ハンドラ関数の一部またはすべてを実装する必要があります。これらの関数の実装は任意です。任意の関数は省略可能です。一般的なプラグインでは少なくともこれらの関数のサブセットが実装されます。

リクエスト フローのイベント ハンドラ

これらの関数は、Edge Microgateway のリクエスト イベントで呼び出されます。

  • onrequest
  • ondata_request
  • onend_request
  • onclose_request
  • onerror_request

onrequest 関数

クライアント リクエストの開始時に呼び出されます。この関数は、リクエストの最初のバイトが Edge Microgateway で受信されたときに呼び出されます。この関数を使用して、リクエスト ヘッダー、URL、クエリ パラメータ、HTTP メソッドにアクセスできます。次に、信頼できる最初の引数(Error のインスタンスなど)を指定して呼び出した場合、リクエストの処理が停止し、ターゲット リクエストが開始されません。

例:

onrequest: function(req, res, next) {
      debug('plugin onrequest');
      req.headers['x-foo-request-start'] = Date.now();
      next();
    }

ondata_request 関数

クライアントからチャンクチャンクを受信したときに呼び出されます。プラグイン シーケンスの次のプラグインにリクエスト データを渡します。シーケンス内の最後のプラグインから返された値がターゲットに送信されます。次に示す典型的なユースケースは、リクエスト データをターゲットに送信する前に変換することです。

例:

ondata_request: function(req, res, data, next) {
      debug('plugin ondata_request ' + data.length);
      var transformed = data.toString().toUpperCase();
      next(null, transformed);
    }

onend_request 関数

すべてのリクエスト データがクライアントから受信されたときに呼び出されます。

例:

onend_request: function(req, res, data, next) {
      debug('plugin onend_request');
      next(null, data);
    }

onclose_request 関数

クライアント接続が閉じられたことを示します。この関数はクライアント接続の信頼性が低い場合に使用します。このメソッドは、クライアントへのソケット接続が閉じられたときに呼び出されます。

例:

onclose_request: function(req, res, next) {
      debug('plugin onclose_request');
      next();
    }

onerror_request 関数

クライアント リクエストの受信中にエラーが発生した場合に呼び出されます。

例:

onerror_request: function(req, res, err, next) {
      debug('plugin onerror_request ' + err);
      next();
    }

レスポンス フロー イベント ハンドラ

これらの関数は、Edge Microgateway のレスポンス イベントで呼び出されます。

  • onresponse
  • ondata_response
  • onend_response
  • onclose_response
  • onerror_response

onresponse 関数

ターゲット レスポンスの開始時に呼び出されます。この関数は、Edge Microgateway がレスポンスの最初のバイトを受信すると呼び出されます。この関数を使用すると、レスポンス ヘッダーとステータス コードにアクセスできます。

例:

onresponse: function(req, res, next) {      
    debug('plugin onresponse');     
    res.setHeader('x-foo-response-time', Date.now() - req.headers['x-foo-request-start'])    
    next();    
}


ondata_response 関数

ターゲットからデータチャンクが受信されたときに呼び出されます。

例:

ondata_response: function(req, res, data, next) {
      debug('plugin ondata_response ' + data.length);
      var transformed = data.toString().toUpperCase();
      next(null, transformed);
    }


onend_response 関数

すべてのレスポンス データがターゲットから受信されたときに呼び出されます。

例:

onend_response: function(req, res, data, next) {
      debug('plugin onend_response');
      next(null, data);
    }

onclose_response 関数

ターゲット接続が閉じられたことを示します。ターゲット接続が不安定な場合は、この関数を使用できます。ターゲットへのソケット接続が切断されたときに呼び出されます。

例:

onclose_response: function(req, res, next) {
      debug('plugin onclose_response');
      next();
    }


onerror_response 関数

ターゲット レスポンスの受信中にエラーが発生した場合に呼び出されます。

例:

onerror_response: function(req, res, err, next) {
      debug('plugin onerror_response ' + err);
      next();
    }

プラグイン イベント ハンドラ関数について知っておくべきこと

プラグイン イベント ハンドラ関数は、Edge Microgateway が特定の API リクエストを処理している間に発生した特定のイベントに応答して呼び出されます。

  • init() 関数ハンドラ(ondata_requestondata_response など)は、処理が完了したときに next() コールバックを呼び出す必要があります。next() を呼び出さないと、処理が停止し、リクエストがハングします。
  • next() の最初の引数は、リクエスト処理を終了させるエラーである可能性があります。
  • ondata_ ハンドラと onend_ ハンドラは、ターゲットまたはクライアントに渡されるデータを含む 2 番目の引数を指定して next() を呼び出す必要があります。プラグインがバッファリングを行っていて、その時点で変換するのに十分なデータがない場合、この引数は null にすることができます。
  • すべてのリクエストとレスポンスに対応するために使用されるプラグインは 1 つだけです。プラグインが呼び出し間でリクエストごとの状態を保持する場合は、提供された request オブジェクト(req)に追加されたプロパティにその状態を保存します。このオブジェクトの存続期間は API 呼び出しの存続期間です。
  • すべてのエラーを注意深く捉え、エラーで next() を呼び出します。next() を呼び出さないと、API 呼び出しがハングします。
  • Edge TensorBoard の全体的なパフォーマンスに影響する可能性があるため、メモリリークが発生しないように注意してください。メモリ不足でクラッシュする可能性があります。
  • メインスレッドでコンピューティング負荷の高いタスクを行わないと、Node.js モデルに従う必要があります。これは、Edge Microgateway のパフォーマンスに悪影響を与える可能性があります。

プラグイン init() 関数について

このセクションでは、init() 関数に渡される引数 configloggerstats について説明します。

config

Edge Microgateway 構成ファイルを Apigee Edge からダウンロードしたデータと結合して取得した構成データは、config という名前のオブジェクトに配置されます。

値が foo の構成パラメータを response-override というプラグインに追加するには、これを default.yaml ファイルに配置します。

response-override:
    param: foo

その後、次のようにプラグイン コードでパラメータにアクセスできます。

// Called when response data is received
    ondata_response: function(req, res, data, next) {
      debug('***** plugin ondata_response');
      debug('***** plugin ondata_response: config.param: ' + config.param);
      next(null, data);
    },

この場合、プラグインのデバッグ出力に foo が表示されます。

Sun, 13 Dec 2015 21:25:08 GMT plugin:response-override ***** plugin ondata_response: config.param: foo

マージされたマイクロゲートウェイの構成にアクセスし、子オブジェクト config.emgConfigs 内の Apigee Edge データをダウンロードできます。たとえば、init 関数では、次のようにこの構成データにアクセスできます。

module.exports.init = function(config, logger, stats) {
   let emgconfigs = config.emgConfigs;

emgConfigs に含まれるデータの例を次に示します。

{
    edgemicro:
    {
        port: 8000,
        max_connections: 1000,
        config_change_poll_interval: 600,
        logging:
        {
            level: 'error',
            dir: '/var/tmp',
            stats_log_interval: 60,
            rotate_interval: 24,
            stack_trace: false
        },
        plugins: { sequence: [Array] },
        global: { org: 'Your Org', env: 'test' }
    },
    headers:
    {
        'x-forwarded-for': true,
        'x-forwarded-host': true,
        'x-request-id': true,
        'x-response-time': true,
        via: true
    },
    proxies:
    [    {
                max_connections: 1000,
                name: 'edgemicro_delayed',
                revision: '1',
                proxy_name: 'default',
                base_path: '/edgemicro_delayed',
                target_name: 'default',
                url: 'https://httpbin.org/delay/10',
                timeout: 0
            }
    ],
    product_to_proxy: { EdgeMicroTestProduct: [ 'edgemicro-auth','edgemicro_delayed',] },
    product_to_scopes: {prod4: [ 'Admin', 'Guest', 'Student' ] },
    product_to_api_resource: { EdgeMicroTestProduct: [ '/*' ] },
    _hash: 0,
    keys: { key: 'Your key', secret: 'Your key ' },
    uid: 'Internally generated uuid',
    targets: []
  }

logger

システムロガー。現在使用されているロガーは、これらの関数をエクスポートします。オブジェクトには、文字列、HTTP リクエスト、HTTP レスポンス、Error インスタンスがあります。

  • info(object, message)
  • warn(object, message)
  • error(object, message)
  • trace(object, message)
  • debug(object, message)

stats

Microgateway インスタンスを通過するリクエストとレスポンスに関連するリクエスト、レスポンス、エラー、その他の集計統計情報を保持するオブジェクト。

  • treqErrors - エラーが発生したターゲット リクエストの数。
  • treqErrors - エラーが発生したターゲット レスポンスの数。
  • statusCodes - レスポンス コードの数を含むオブジェクト。
{
  1: number of target responses with 1xx response codes
  2: number of target responses with 2xx response codes
  3: number of target responses with 3xx response codes
  4: number of target responses with 4xx response codes
  5: number of target responses with 5xx response codes
  }
  
  • requests - リクエストの合計数。
  • responses - レスポンスの合計数。
  • connections - アクティブなターゲット接続の数。

next() 関数について

すべてのプラグイン メソッドは、next() を呼び出して、シリーズの次のメソッドを処理し続ける必要があります(プラグイン プロセスがハングします)。リクエストのライフサイクルで最初に呼び出されるメソッドは onrequest() です。次に呼び出されるメソッドは ondata_request() メソッドです。ondata_request は、POST リクエストなどで、リクエストにデータが含まれている場合にのみ呼び出されます。次に呼び出されるメソッドは onend_request() で、リクエストの処理が完了すると呼び出されます。onerror_* 関数はエラー時にのみ呼び出されるので、必要に応じてカスタムコードでエラーを処理できます。

リクエストでデータが送信され、ondata_request() が呼び出されたとします。この関数は次の 2 つのパラメータを指定して next() を呼び出します。

next(null, data);

慣例により、最初のパラメータはエラー情報を伝えるために使用されます。エラー情報は、チェーンの後続の関数で処理できます。Faly 引数 null に設定すると、エラーは発生せず、リクエストの処理は通常どおり行われます。この引数が true(Error オブジェクトなど)の場合、リクエスト処理は停止し、リクエストがターゲットに送信されます。

2 つ目のパラメータは、リクエスト データをチェーンの次の関数に渡します。追加の処理を行わない場合、リクエスト データは変更されず、API のターゲットに渡されます。ただし、このメソッド内でリクエスト データを変更し、変更されたリクエストをターゲットに渡すこともできます。たとえば、リクエスト データが XML で、ターゲットが JSON を想定している場合は、(a)リクエスト ヘッダーの Content-Type を application/json に変更し、任意の方法でリクエスト データを JSON に変換するコードを ondata_request() メソッドに追加します(たとえば、NPM から取得した Node.js xml2json コンバータを使用できます)。

どのように表示されるかを確認してみましょう。

ondata_request: function(req, res, data, next) {
  debug('****** plugin ondata_request');
  var translated_data = parser.toJson(data);
  next(null, translated_data);
},

この場合、リクエスト データ(XML と見なされます)は JSON に変換され、変換されたデータが next() を介してリクエスト チェーンの次の関数に渡されてから、バックエンド ターゲットに渡されます。

デバッグ用に変換したデータを出力するデバッグ ステートメントをもう 1 つ追加することもできます。次に例を示します。

ondata_request: function(req, res, data, next) {
  debug('****** plugin ondata_request');
  var translated_data = parser.toJson(data);
  debug('****** plugin ondata_response: translated_json: ' + translated_json);
  next(null, translated_data);
},

プラグイン ハンドラの実行順序について

Edge Microgateway のプラグインを作成する場合は、プラグイン イベント ハンドラの実行順序を理解する必要があります。

重要な点は、Edge Helm 構成ファイルでプラグイン シーケンスを指定するときに、リクエスト ハンドラは昇順で実行され、レスポンス ハンドラは降順で実行されることです。

次の例は、この実行シーケンスを理解するのに役立ちます。

1. 3 つのシンプルなプラグインを作成する

次のプラグインを検討してください。イベント ハンドラが呼び出されたときにコンソールの出力を出力します。

plugins/plugin-1/index.js

module.exports.init = function(config, logger, stats) {

  return {

    onrequest: function(req, res, next) {
      console.log('plugin-1: onrequest');
      next();
    },

    onend_request: function(req, res, data, next) {
      console.log('plugin-1: onend_request');
      next(null, data);
    },

    ondata_response: function(req, res, data, next) {
      console.log('plugin-1: ondata_response ' + data.length);
      next(null, data);
    },

    onend_response: function(req, res, data, next) {
      console.log('plugin-1: onend_response');
      next(null, data);
    }
  };
}

次に、同じコードで plugin-2plugin-3 の 2 つのプラグインを追加することを検討してください(ただし、console.log() ステートメントをそれぞれ plugin-2plugin-3 に変更します)。

2. プラグイン コードを確認する

<microgateway-root-dir>/plugins/plugin-1/index.js でエクスポートされたプラグイン関数は、リクエストとレスポンスの処理中に特定の時間に実行されるイベント ハンドラです。たとえば、onrequest はリクエスト ヘッダーの最初のバイトを受信します。onend_response は、レスポンス データの最後のバイトが受信された後に実行されます。

ondata_response ハンドラをご覧ください。レスポンス データのチャンクが受信されるたびに呼び出されます。レスポンス データがすべて一度に受信されるとは限らないことに注意してください。むしろ、データは任意の長さのチャンクで受信される可能性があります。

3. プラグイン シーケンスにプラグインを追加する

この例のプラグインを、次の Edge 構成ファイル(~./edgemicro/config.yaml)のプラグイン シーケンスに追加します。順序は重要です。プラグイン ハンドラの実行順序を定義します。

  plugins:
    dir: ../plugins
    sequence:
      - plugin-1
      - plugin-2
      - plugin-3
  

4. デバッグ出力を調べる

では、これらのプラグインが呼び出されたときに生成される出力を見てみましょう。注意すべき重要な点がいくつかあります。

  • プラグイン シーケンスの Edge Microgateway 構成ファイル(~./edgemicro/config.yaml)では、イベント ハンドラを呼び出す順序を指定します。
  • リクエスト ハンドラは、昇順(プラグイン シーケンス 1、2、3 の出現順)で呼び出されます。
  • レスポンス ハンドラは降順(3、2、1)で呼び出されます。
  • ondata_response ハンドラは、到着するデータのチャンクごとに 1 回呼び出されます。この例では(出力は下記に示す)、2 つのチャンクを受け取ります。

これら 3 つのプラグインが使用され、Edge Microgateway を介してリクエストを送信したときに生成されるデバッグ出力の例を次に示します。ハンドラが呼び出される順序に注目してください。

  plugin-1: onrequest
  plugin-2: onrequest
  plugin-3: onrequest

  plugin-1: onend_request
  plugin-2: onend_request
  plugin-3: onend_request

  plugin-3: ondata_response 931
  plugin-2: ondata_response 931
  plugin-1: ondata_response 931

  plugin-3: ondata_response 1808
  plugin-3: onend_response

  plugin-2: ondata_response 1808
  plugin-2: onend_response

  plugin-1: ondata_response 1808
  plugin-1: onend_response

まとめ

リクエスト データやレスポンス データの蓄積や変換といったカスタム プラグイン機能を実装する場合、プラグイン ハンドラの呼び出し順序を理解することは非常に重要です。

リクエスト ハンドラは、Edge Microgateway 構成ファイルでプラグインが指定されている順序で実行され、レスポンス ハンドラは逆の順序で実行されます。

プラグインでのグローバル変数の使用について

Edge Microgateway へのリクエストはすべてプラグインの同じインスタンスに送信されるため、別のクライアントからの 2 番目のリクエストの状態は最初のインスタンスを上書きします。プラグインの状態を保存する唯一の安全な場所は、リクエストまたはレスポンス オブジェクトのプロパティに状態を保存することです(このオブジェクトの存続期間はリクエストの存続期間に限定されます)。

プラグインのターゲット URL の書き換え

追加先: v2.3.3

プラグイン コードの req.targetHostnamereq.targetPath の変数を変更すると、プラグインのデフォルトのターゲット URL を動的にオーバーライドできます。

追加先: v2.4.x

ターゲット エンドポイント ポートをオーバーライドして、HTTP と HTTPS を選択することもできます。プラグイン コードの req.targetPort および req.targetSecure を変更します。HTTPS を選択するには、req.targetSecuretrue に設定します。HTTP の場合は false に設定します。req.targetSecure を true に設定する場合は、こちらのディスカッション スレッドをご覧ください。

eurekaclient というサンプル プラグインが Edge Microgateway に追加されました。このプラグインは、req.targetPort および req.targetSecure 変数の使用方法を説明し、Edge Microgateway が Eureka をサービス エンドポイント カタログとして使用して動的エンドポイント ルックアップを実行する方法を示しています。


サンプル プラグイン

これらのプラグインは、Edge Microgateway のインストールに付属しています。Edge Microgateway インストールの

[prefix]/lib/node_modules/edgemicro/plugins

ここで、[prefix]npm プレフィックス ディレクトリです。詳細については、Edge Microgateway のインストールの「Edge Microgateway がインストールされている場所」をご覧ください。

累積リクエスト

このプラグインは、クライアントからデータチャンクを、リクエスト オブジェクトに接続されている配列プロパティに蓄積します。すべてのリクエスト データを受信すると、配列がバッファに連結され、シーケンス内の次のプラグインに渡されます。後続のプラグインが蓄積されたリクエストデータを受け取るように、このプラグインはシーケンス内の最初のプラグインにする必要があります。

module.exports.init = function(config, logger, stats) {

  function accumulate(req, data) {

    if (!req._chunks) req._chunks = [];
    req._chunks.push(data);

  }

  return {

    ondata_request: function(req, res, data, next) {

      if (data && data.length > 0) accumulate(req, data);

      next(null, null);

    },


    onend_request: function(req, res, data, next) {

      if (data && data.length > 0) accumulate(req, data);

      var content = null;

      if (req._chunks && req._chunks.length) {

        content = Buffer.concat(req._chunks);

      }

      delete req._chunks;

      next(null, content);

    }

  };

}

累積応答

このプラグインは、ターゲットからデータチャンクを、レスポンス オブジェクトに関連付けられた配列プロパティに蓄積します。すべてのレスポンス データを受信すると、配列はバッファに連結され、シーケンス内の次のプラグインに渡されます。このプラグインは、逆の順序で処理されるレスポンスを操作するため、最後のプラグインとして配置する必要があります。

module.exports.init = function(config, logger, stats) {

  function accumulate(res, data) {
    if (!res._chunks) res._chunks = [];
    res._chunks.push(data);
  }

  return {

    ondata_response: function(req, res, data, next) {
      if (data && data.length > 0) accumulate(res, data);
      next(null, null);
    },

    onend_response: function(req, res, data, next) {
      if (data && data.length > 0) accumulate(res, data);
      var content = Buffer.concat(res._chunks);
      delete res._chunks;
      next(null, content);
    }

  };

}

header-uppercase プラグイン

Edge Microgateway ディストリビューションには、<microgateway-root-dir>/plugins/header-uppercase というサンプル プラグインが含まれています。このサンプルには、各関数ハンドラを説明するコメントが含まれています。このサンプルは、ターゲット レスポンスの単純なデータ変換を行い、クライアント リクエストとターゲット レスポンスにカスタム ヘッダーを追加します。

<microgateway-root-dir>/plugins/header-uppercase/index.js のソースコードは次のとおりです。

'use strict';

var debug = require('debug')('plugin:header-uppercase');

// required
module.exports.init = function(config, logger, stats) {

  var counter = 0;

  return {

    // indicates start of client request
    // request headers, url, query params, method should be available at this time
    // request processing stops (and a target request is not initiated) if
    // next is called with a truthy first argument (an instance of Error, for example)
    onrequest: function(req, res, next) {
      debug('plugin onrequest');
      req.headers['x-foo-request-id'] = counter++;
      req.headers['x-foo-request-start'] = Date.now();
      next();
    },

    // indicates start of target response
    // response headers and status code should be available at this time
    onresponse: function(req, res, next) {
      debug('plugin onresponse');
      res.setHeader('x-foo-response-id', req.headers['x-foo-request-id']);
      res.setHeader('x-foo-response-time', Date.now() - req.headers['x-foo-request-start']);
      next();
    },

    // chunk of request body data received from client
    // should return (potentially) transformed data for next plugin in chain
    // the returned value from the last plugin in the chain is written to the target
    ondata_request: function(req, res, data, next) {
      debug('plugin ondata_request ' + data.length);
      var transformed = data.toString().toUpperCase();
      next(null, transformed);
    },

    // chunk of response body data received from target
    // should return (potentially) transformed data for next plugin in chain
    // the returned value from the last plugin in the chain is written to the client
    ondata_response: function(req, res, data, next) {
      debug('plugin ondata_response ' + data.length);
      var transformed = data.toString().toUpperCase();
      next(null, transformed);
    },

    // indicates end of client request
    onend_request: function(req, res, data, next) {
      debug('plugin onend_request');
      next(null, data);
    },

    // indicates end of target response
    onend_response: function(req, res, data, next) {
      debug('plugin onend_response');
      next(null, data);
    },

    // error receiving client request
    onerror_request: function(req, res, err, next) {
      debug('plugin onerror_request ' + err);
      next();
    },

    // error receiving target response
    onerror_response: function(req, res, err, next) {
      debug('plugin onerror_response ' + err);
      next();
    },

    // indicates client connection closed
    onclose_request: function(req, res, next) {
      debug('plugin onclose_request');
      next();
    },

    // indicates target connection closed
    onclose_response: function(req, res, next) {
      debug('plugin onclose_response');
      next();
    }

  };

}


変換

これは一般的な変換プラグインで、変更など、あらゆる種類の変換を実行できます。この例では、単にレスポンスとリクエスト データを大文字に変換しています。

 */
module.exports.init = function(config, logger, stats) {

  // perform content transformation here
  // the result of the transformation must be another Buffer
  function transform(data) {
    return new Buffer(data.toString().toUpperCase());
  }

  return {

    ondata_response: function(req, res, data, next) {
      // transform each chunk as it is received
      next(null, data ? transform(data) : null);
    },

    onend_response: function(req, res, data, next) {
      // transform accumulated data, if any
      next(null, data ? transform(data) : null);
    },

    ondata_request: function(req, res, data, next) {
      // transform each chunk as it is received
      next(null, data ? transform(data) : null);
    },

    onend_request: function(req, res, data, next) {
      // transform accumulated data, if any
      next(null, data ? transform(data) : null);
    }

  };

}