<ph type="x-smartling-placeholder"></ph>
現在、Apigee Edge のドキュメントが表示されています。
Apigee X のドキュメント。 詳細
Edge AppSheet v. 2.4.x
オーディエンス
このトピックは、次を書いて Edge Dataproc の機能を拡張するデベロッパーを対象としています。 使用できます。新しいプラグインを作成する場合は、JavaScript と Node.js の使用経験を 必要ありません。
カスタム Edge Scanner プラグインとは
プラグインは、Edge Scanner に機能を追加する Node.js モジュールです。プラグイン モジュール 一貫したパターンに従って、そのデータが Edge 自動的に検出、実行されます。いくつかの事前定義プラグインが用意されており、 インストールします。これには、Authentication、Spike Arrest、Quota、 分析できますこれらの既存のプラグインについては、プラグインの使用をご覧ください。
custom プラグインをご覧ください。デフォルトでは、Edge Appliance は基本的に安全なパススルー プロキシです。 変更されることなく、ターゲット サービス間でリクエストとレスポンスを渡す。カスタム プラグインを使用すると、 マイクロゲートウェイを通過するリクエストおよびレスポンスをプログラムで操作します。
カスタム プラグイン コードの配置場所
カスタム プラグイン用のフォルダは Edge Appliance のインストールに含まれています。 こちらをご覧ください。
[prefix]/npm/lib/node_modules/edgemicro/plugins
ここで、[prefix] は npm 接頭辞ディレクトリです。
詳細は、このモジュールのコースリソースに記載のEdge のインストールに関するページ
できます。
このデフォルトのプラグイン ディレクトリは変更できます。詳しくは、 プラグインを見つけるをご覧ください。
事前定義プラグインの確認
独自のプラグインを開発する前に、事前定義されたプラグインが実装されていないことを 要件を満たす必要があります。これらのプラグインは次の場所にあります。
[prefix]/npm/lib/node_modules/edgemicro/node_modules/microgateway-plugins
ここで、[prefix] は npm 接頭辞ディレクトリです。詳しくは、
「Edge Apigee がインストールされている場所」もご覧ください。Edge のインストールに関するページ
できます。
詳しくは、事前定義 プラグインをご覧ください。
シンプルなプラグインを作成する
このセクションでは、簡単なプラグインの作成に必要な手順を説明します。このプラグイン レスポンス データ(その内容)を文字列「Hello, World!」でオーバーライドします。出力し、 終端します。
- Edge Appliance が実行中の場合は、この時点で停止します。
edgemicro stop
-
cdでカスタム プラグイン ディレクトリに移動します。cd [prefix]/npm/lib/node_modules/edgemicro/pluginsここで、
[prefix]はnpm接頭辞ディレクトリです。 (詳細は「Edge Gateway のインストール場所」を参照)Edge のインストールに関するページ できます。 - 新しいプラグイン プロジェクトを作成する
response-override という呼び出しを作成し、それに
cdします。
mkdir response-override && cd response-override
- 新しい Node.js プロジェクトを作成します。
Return キーを何度か押して、デフォルト値を受け入れます。npm init
- テキスト エディタを使用して、
index.jsという名前の新しいファイルを作成します。 - 次のコードを
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"); } }; }
- プラグインを作成したので、次は Edge Appliance の構成にプラグインを追加する必要があります。
$HOME/.edgemicro/[org]-[env]-config.yamlファイルを開きます。 ここで、orgとenvは Edge 組織です。 定義できます。 response-overrideプラグインを以下に追加します。plugins:sequence要素を定義します。
... plugins: dir: ../plugins sequence: - oauth - response-override ...- Edge Appliance を再起動します。
- Edge Appliance を介して API を呼び出します。(この API 呼び出しでは、同じ API 呼び出しが
API キーのセキュリティに関するチュートリアルと同じ構成を使用します。詳しくは、
構成する:
curl -H 'x-api-key: uAM4gBSb6YoMvTHfx5lXJizYIpr5Jd' http://localhost:8000/hello/echo Hello, World!
プラグインの構造
次の Edge AppSheet サンプル プラグインは、次の場合に従うパターンを示しています。
独自のプラグインを開発できます。このセクションで説明するサンプル プラグインのソースコードは、
plugins/header-uppercase/index.js.内
- プラグインは標準の NPM モジュールで、
ルートの
package.jsonとindex.jsフォルダに配置されます。 - プラグインは init() 関数をエクスポートする必要があります。
- init() 関数は 3 つの 引数: config、logger、 および統計情報です。これらの引数については、 プラグインの init() 関数の引数。
- init() は、呼び出された名前付き関数ハンドラを含むオブジェクトを返します リクエストの全期間で特定のイベントが発生したとき。
イベント ハンドラ関数
プラグインでは、これらのイベント ハンドラ関数の一部またはすべてを実装する必要があります。これらの実装 使用するかどうかは任意です。どの関数も省略可能で、一般的なプラグインは サブセットを残さずに済みます
リクエスト フローのイベント ハンドラ
これらの関数は、Edge API のリクエスト イベントで呼び出されます。
onrequestondata_requestonend_requestonclose_requestonerror_request
onrequest 関数
クライアント リクエストの開始時に呼び出されます。この関数は、呼び出しのバイト数の最初のバイトが 受信します。この関数を使用すると、リクエスト ヘッダー、 URL、クエリ パラメータ、HTTP メソッド。真実の第 1 引数( リクエストがあった場合、リクエスト処理は停止し、ターゲット リクエストは開始されません。
例:
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 Appliance のレスポンス イベントで呼び出されます。
onresponseondata_responseonend_responseonclose_responseonerror_response
onresponse 関数
ターゲット レスポンスの開始時に呼び出されます。この関数は、呼び出しのバイト数の最初のバイトが レスポンスが返されます。この関数を使用すると、レスポンス ヘッダーに ステータス コードが含まれます。
例:
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(); }
Google Cloud コンソールについて知っておくべきこと プラグインのイベント ハンドラ関数
プラグイン イベント ハンドラ関数は、プラグインの実行時に発生する特定のイベントに応答して呼び出されます。 Edge Appliance は、指定された API リクエストを処理します。
- 各 init() 関数ハンドラ (ondata_request、ondata_response など)は、 処理が完了したら next() コールバックを呼び出します。この操作を next() を呼び出すと、処理が停止し、リクエストがハングします。
- next() の最初の引数がエラーの場合、 終了します
- ondata_ ハンドラと onend_ ハンドラは、 渡されるデータを含む 2 番目の引数を指定して next() を呼び出す ターゲットまたはクライアントに送信しますプラグインがバッファリングされていて、かつプラグインが 必要なデータだけを集めようとしています。
- すべてのリクエストとレスポンスに対応するために、プラグインのインスタンスを 1 つ使用します。 呼び出し間でリクエストごとの状態を保持したい場合は、プラグインでその状態を 指定された request オブジェクトに追加されるプロパティ (req)。その存続期間は API 呼び出しの継続時間です。
- すべてのエラーを注意深くキャッチし、エラーを指定して next() を呼び出すようにしてください。 next() を呼び出せないと、API 呼び出しがハングします。
- メモリリークが発生しないように注意してください。Edge の全体的なパフォーマンスに影響する可能性があります。 メモリ不足になるとクラッシュします
- メインノードではコンピューティング負荷の高いタスクを行わず、Node.js モデルに従うようにしてください。 使用する必要があります。
プラグインの init() 関数について
このセクションでは、Terraform に渡される引数について説明します。 init() 関数: config、logger、 および統計情報です。
config
Edge Appliance の構成ファイルを
Apigee Edge からダウンロードされた情報(プロダクトや割り当てなど)です。詳しくは、
オブジェクト内のプラグイン固有の構成: config.<plugin-name>。
param という構成パラメータに値
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
logger
システムロガー。現在使用されているロガーは、これらの関数をエクスポートします。ここでは、 文字列、HTTP リクエスト、HTTP レスポンス、Error インスタンスです。
info(object, message)warn(object, message)error(object, message)
stats
リクエスト、レスポンス、エラーの数、その他の集計された統計情報を保持するオブジェクト 関連するリクエストとレスポンスに関するログエントリが含まれます
- 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 に設定すると、偽
エラーはなく、リクエスト処理は通常どおり続行されるはずです。条件
この引数が true(エラー オブジェクトなど)である場合、リクエスト処理は停止し、リクエストは
ターゲットに送信されます
2 番目のパラメータは、チェーンの次の関数にリクエスト データを渡します。「いいえ」の場合:
追加の処理が行われると、リクエスト データは変更されることなく API のターゲットに渡されます。
ただし、このメソッド内のリクエスト データを変更して、変更された
構成されます。たとえば、リクエスト データが XML で、ターゲットが JSON を想定している場合、
次に、ondata_request() メソッドにコードを追加します。これにより、(a)
リクエスト ヘッダーの Content-Type を application/json に変換し、
お好みの方法でデータを JSON にリクエストできます(たとえば、
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 AppSheet 用のプラグインを作成する場合は、どの順序でプラグインが記述されるかを理解する必要があります。 イベントハンドラが実行されます。
覚えておくべき重要な点は、Edge でプラグイン シーケンスを指定する際、 リクエスト ハンドラは、Deployment 構成ファイル内で 昇順で並べ替えられ、レスポンス ハンドラは 降順に並べます。
次の例は、この実行順序を理解するのに役立ちます。
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-2 プラグインと plugin-3 プラグイン(同じコードを使用)
(ただし、console.log() ステートメントは
plugin-2 と plugin-3 にそれぞれ設定)。
2. プラグイン コードを確認する
エクスポートされたプラグイン関数
<microgateway-root-dir>/plugins/plugin-1/index.jsにおけるイベント
リクエストとレスポンスの処理中に特定の時間に実行されるハンドラがあります。対象
たとえば、onrequest はリクエスト ヘッダーの最初のバイトを
受信します。一方、onend_response はレスポンスの最後のバイトの後に実行されます。
受信します。
ハンドラの ondata_response をご覧ください。このハンドラは、レスポンス データのチャンクが応答するたびに 受信します。知っておくべき重要な点は、レスポンス データは必ずしもすべての時点で受信されるわけではない 1 回だけです。データは任意の長さのチャンクで受信される可能性があります。
3. プラグインを プラグインのシーケンス
この例では、Edge のプラグイン シーケンスにプラグインを追加します。
次のとおりに更新します。~./edgemicro/config.yamlシーケンスは次のとおりです。
重要ですプラグイン ハンドラの実行順序を定義します。
plugins:
dir: ../plugins
sequence:
- plugin-1
- plugin-2
- plugin-3
4. デバッグ出力を調べる
では、これらのプラグインが呼び出されたときに生成される出力を見てみましょう。他にも 次の点に注意してください。
- Edge AppSheet 構成ファイルのプラグイン順序
(
~./edgemicro/config.yaml)は、イベント ハンドラを 呼び出すことができます。 - リクエスト ハンドラは、昇順( プラグインのシーケンス(1、2、3)に表示されます。
- レスポンス ハンドラは、3、2、降順で呼び出されます。 1.
ondata_responseハンドラは、データチャンクごとに 1 回呼び出されます。 予測します。この例(出力は下記)では、2 つのチャンクを受信します。
以下は、この 3 つのプラグインが使用されていて、リクエストが送信された場合に生成されるデバッグ出力のサンプルです。 接続しますハンドラが呼び出される順序に注目してください。
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 Appliance へのすべてのリクエストは、プラグインの同じインスタンスに送信されます。したがって、 別のクライアントからの 2 番目のリクエストの状態によって、最初のリクエストが上書きされます。安全に操作できる唯一の プラグインの状態を保存するには、リクエスト オブジェクトまたはレスポンス オブジェクトのプロパティ( リクエストのライフタイムに限定されます)。
プラグインのターゲット URL の書き換え
v2.3.3 で追加
これらの変数を変更することで、プラグインのデフォルトのターゲット URL を動的にオーバーライドできます。 (プラグイン) コード: req.targetHostname と req.targetPath。
v2.4.x で追加
ターゲット エンドポイント ポートをオーバーライドして、HTTP と HTTPS のいずれかを選択することもできます。これらを 変数を使用します。 コード: req.targetPort および req.targetSecure。宛先 HTTPS を選択し、req.targetSecure を true に設定します。 false に設定します。req.targetSecure を true に設定した場合 こちらのディスカッション スレッドをご覧ください。
サンプル プラグイン
これらのプラグインは、Edge Apigee のインストールに付属しています。確認するには、 Edge Appliance のインストール先:
[prefix]/npm/lib/node_modules/edgemicro/plugins
ここで、[prefix] は npm 接頭辞ディレクトリです。
詳細は、このモジュールのコースリソースに記載のEdge のインストールに関するページ
できます。
accumulate-request
このプラグインは、クライアントからのデータチャンクを、 リクエスト オブジェクト。すべてのリクエスト データを受信すると、配列がバッファに連結される シーケンスの次のプラグインに渡されます。このプラグインは、Google Cloud の 累積されたリクエスト データを後続のプラグインが受信できるようにします。
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
このプラグインは、ターゲットからのデータチャンクを、 レスポンス オブジェクト。すべてのレスポンス データを受信すると、配列はバッファに連結されます。 シーケンスの次のプラグインに渡されます。このプラグインは Google Cloud 上で 逆の順序で処理するため、最後のプラグインとして配置する必要があります。 必要があります。
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 AppSheet ディストリビューションにはサンプル プラグインが含まれています。
<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); } }; }
その他のプラグイン チュートリアル
Apigee ブログで次のチュートリアルもご覧ください。
- <ph type="x-smartling-placeholder"></ph> チュートリアル: Apigee Edge Appliance にロガー プラグインを追加する
- <ph type="x-smartling-placeholder"></ph> チュートリアル: Apigee Edge Appliance のカスタム変換プラグインの作成