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

現在、Apigee Edge のドキュメントを表示しています。
Apigee X のドキュメントをご確認ください
情報

Edge Microgateway バージョン 3.3.x

対象読者

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

カスタム Edge Microgateway プラグインとは何ですか?

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

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

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

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

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

ここで、Edge Microgateway のインストールの「Edge Microgateway がインストールされている場所」で説明されているように、[prefix]npm 接頭辞ディレクトリです。

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

事前定義されたプラグインを確認する

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

[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] は、Edge Microgateway のインストールの「Edge Microgateway がインストールされている場所」で説明されている npm 接頭辞ディレクトリです。

  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 を呼び出します。(この API 呼び出しは、Edge Microgateway の設定と構成で説明されているように、API キー セキュリティに関するチュートリアルと同じ構成を設定していることを前提としています)。
    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 メソッドにアクセスできます。次に true となる最初の引数(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 つのインスタンスを使用して処理されます。プラグインでは、呼び出し間でリクエストごとの状態を保持したい場合、指定されたリクエスト オブジェクト(req)に追加されたプロパティにその状態を保存できます。その存続期間は API 呼び出しの継続時間となります。
  • すべてのエラーをキャッチし、そのエラーで next() を呼び出してください。next() を呼び出さないと、API 呼び出しがハングします。
  • メモリリークが発生しないように注意してください。Edge Microgateway の全体的なパフォーマンスに影響が及び、メモリが不足した場合にクラッシュを引き起こす可能性があります。
  • Node.js モデルに従う際は、メインスレッドでコンピューティング負荷の高いタスクを行わないように注意してください。Edge Microgateway のパフォーマンスに悪影響を及ぼす可能性があります。

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

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

config

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

foo という値を指定した param という構成パラメータを 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

結合された microgateway の構成と、子オブジェクト 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 レスポンス、エラー インスタンスです。

  • 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);

慣例として、最初のパラメータはエラー情報を伝えるために使用されます。この情報は、チェーン内の後続の関数で処理できます。これを null(falsy 引数)に設定すると、エラーがないこと、リクエスト処理が正常に行われる必要があるということです。この引数が true である場合(エラー オブジェクトなど)、リクエスト処理が停止し、リクエストがターゲットに送信されます。

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() を介してリクエスト チェーンの次の関数に渡されます。

デバッグ用に、別のデバッグ ステートメントを追加して変換済みのデータを出力することもできます。例:

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 Microgateway 構成ファイルでプラグイン シーケンスを指定すると、リクエスト ハンドラは昇順で実行され、レスポンス ハンドラは降順で実行されることです。

次の例は、この実行シーケンスの理解に役立つように設計されています。

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

次に、同じコードでさらに 2 つのプラグイン plugin-2plugin-3 を作成してみましょう(ただし、console.log() ステートメントをそれぞれ plugin-2plugin-3 に変更します)。

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

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

ondata_response ハンドラは、レスポンス データのチャンクを受け取るたびに呼び出されます。重要な点は、レスポンス データは必ずしも一度に受信されるとは限らないということです。実際には、任意の長さのチャンクでデータを受信することもできます。

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

この例では、Edge Microgateway 構成ファイル(~./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

ここで、Edge Microgateway のインストールの「Edge Microgateway がインストールされている場所」で説明されているように、[prefix]npm 接頭辞ディレクトリです。

累積リクエスト

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

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

    }

  };

}

accumulate-response

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

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

  };

}