Apigee Edge の JavaScript ポリシーを使用すると、API プロキシフローの処理中にカスタムコードを実行できます。たとえば、JavaScript ポリシーのカスタムコードを次の目的で使用できます。
- フロー変数を取得して設定する
- カスタム ロジックを実行し、障害処理を実施する
- リクエストまたはレスポンスからデータを抽出する
- バックエンドのターゲット URL を動的に編集する
- リクエストまたはレスポンスに対して動的にヘッダーの追加または削除を行う
- JSON レスポンスを解析する
HTTP クライアント
HTTP クライアントは、JavaScript ポリシーの高度な機能です。HTTP クライアント(httpClient
オブジェクト)を使用すると、1 つまたは複数のバックエンド サービスまたは外部サービスを呼び出すことができます。HTTP クライアントが特に役立つのは、複数の外部サービスを呼び出して、レスポンスを単一の API の中にマッシュアップする必要がある場合です。
httpClient オブジェクトを使用してバックエンドを呼び出す JavaScript コードの例
var headers = {'X-SOME-HEADER' : 'some value' }; var myRequest = new Request("http://www.example.com","GET",headers); var exchange = httpClient.send(myRequest);
httpClient
オブジェクトは 2 つのメソッド get
と send
を公開し(send
は上記のサンプルコードで使用)、HTTP リクエストを実行します。どちらのメソッドも非同期的で、実際の HTTP リクエストが完了する前に exchange
オブジェクトを返します。
HTTP リクエストには数秒から数分かかる場合があります。HTTP リクエストが行われた後、リクエストからのレスポンスを処理できるように、完了したタイミングを知ることが重要です。HTTP リクエストが完了したタイミングを判断する最も一般的な方法の 1 つは、exchange
オブジェクトの waitForComplete()
メソッドを呼び出すことです。
waitForComplete()
waitForComplete()
メソッドは、HTTP リクエストが完了してレスポンス(成功 / 失敗)が返されるまで、スレッドを一時停止します。その後で、バックエンドまたは外部サービスからのレスポンスを処理できるようになります。
waitForComplete() を使用した JavaScript コードの例
var headers = {'X-SOME-HEADER' : 'some value' }; var myRequest = new Request("http://www.example.com","GET",headers); var exchange = httpClient.send(myRequest); // Wait for the asynchronous GET request to finish exchange.waitForComplete(); // Get and Process the response if (exchange.isSuccess()) { var responseObj = exchange.getResponse().content.asJSON; return responseObj.access_token; } else if (exchange.isError()) { throw new Error(exchange.getError()); }
アンチパターン
JavaScript コードで HTTP リクエストを送信した後に waitForComplete()
を使用すると、パフォーマンスに影響を与えます。
HTTP リクエストの送信後に waitForComplete()
を呼び出す次の JavaScript コードを考えてみましょう。
sample.js のコード
// Send the HTTP request var exchangeObj = httpClient.get("http://example.com"); // Wait until the request is completed exchangeObj.waitForComplete(); // Check if the request was successful if (exchangeObj.isSuccess()) { response = exchangeObj.getResponse(); context.setVariable('example.status', response1.status); } else { error = exchangeObj.getError(); context.setVariable('example.error', 'Woops: ' + error); }
この例では
- JavaScript コードが HTTP リクエストをバックエンド API に送信します。
- 次に
waitForComplete()
を呼び出して、リクエストが完了するまで実行を一時停止します。waitForComplete()
API を使用すると、バックエンドがリクエストの処理を完了して応答するまで、JavaScript コードを実行しているスレッドがブロックされます。
Message Processor で JavaScript コードを同時に実行できるスレッドの数には、常に上限があります(30%)。この上限に達すると、JavaScript コードを実行できるスレッドはなくなります。そのため、JavaScript コードで waitForComplete()
API を実行する同時リクエストが多すぎる場合、後続のリクエストが 500 Internal Server Error で失敗し、JavaScript ポリシーがタイムアウトする前でも「タイムアウト」エラー メッセージが表示されます。
一般に、このシナリオは、バックエンドでのリクエストの処理に時間がかかる場合や、トラフィックが多い場合に発生する可能性があります。
影響
- JavaScript コードで
waitForComplete()
を実行する同時リクエストの数が事前定義された上限を超えると、API リクエストは 500 Internal Server Error で失敗し、エラー メッセージ「タイムアウト」が表示されます。 - 特定の JavaScript ポリシーの制限時間が経過していなくても JavaScript が「タイムアウト」エラーで失敗するので、問題の原因を診断しにくくなる可能性があります。
ベスト プラクティス
HTTP クライアントで callback を使用して、コールアウト コードを合理化し、パフォーマンスを改善します。また JavaScript コードで waitForComplete()
を使用しないようにします。この方法により、HTTP リクエストが完了するまでの間、JavaScript を実行するスレッドがブロックされないようになります。
callback が使用されると、スレッドは JavaScript コードで HTTP コードを送信し、プールに戻ります。スレッドはブロックされなくなったので、他のリクエストを処理できます。HTTP リクエストが完了し、callback を実行する準備ができると、タスクが作成されてタスクキューに追加されます。プールのスレッドの 1 つが、タスクの優先度に基づいて callback を実行します。
httpClient で callback を使用した JavaScript コードの例
function onComplete(response,error) { // Check if the HTTP request was successful if (response) { context.setVariable('example.status', response.status); } else { context.setVariable('example.error', 'Woops: ' + error); } } // Specify the callback Function as an argument httpClient.get("http://example.com", onComplete);