JavaScript 物件模型

查看 Apigee Edge 說明文件。
前往 Apigee X說明文件
資訊

本主題將探討 Apigee Edge JavaScript 物件模型。請務必瞭解 這個模型 (如果您打算使用 JavaScript 政策,將自訂 JavaScript 新增至 API) Proxy 上。

關於 Edge JavaScript 物件模型

Apigee Edge JavaScript 物件模型會定義具備下列屬性的物件: 適用於在 Apigee Edge Proxy 流程中執行的 JavaScript 程式碼。您使用 JavaScript 政策,將這個自訂程式碼附加至 API Proxy 流程。

這個模型定義的物件在 API Proxy 流程中具有「範圍」, 某些物件和屬性只能在流程中的特定時間點存取。當您 執行 JavaScript 時,系統會建立執行作業的範圍。在這個範圍內 物件參照

  • context提供訊息背景存取權的物件
  • request允許存取要求物件的簡寫
  • response允許存取要求物件的簡寫
  • 加密提供各種雜湊函式
  • print用來發出輸出的函式
  • properties可讀取政策的設定屬性

結構定義物件

context 物件具有全域範圍。可在 API 中的任何位置使用 以及 Proxy 流程其中包含四個子物件:proxyRequestproxyResponsetargetRequesttargetResponse。這些子物件的範圍僅限 可能是 Proxy 要求和回應,或目標要求和 回應。例如,如果 JavaScript 政策在流程的 Proxy 端點部分執行, 則 context.proxyRequestcontext.proxyResponse 物件都在 範圍。如果 JavaScript 在目標流程中執行,則 context.targetRequestcontext.targetResponse 個物件在範圍內。

context 物件也具有屬性和方法,這些屬性和方法詳細說明 舉例來說,下列 JavaScript 程式碼範例使用 context.flow屬性,並呼叫 get/setVariable() 方法, context

if (context.flow=="PROXY_REQ_FLOW") {
     var username = context.getVariable("request.formparam.user");
     context.setVariable("USER.name", username);
}

這些方法直接與流程變數互動。 context.flow 屬性值是目前的流程範圍。在 Proxy 中 要求流程,就會設為常數 PROXY_REQ_FLOW。在目標區間內 則設為 TARGET_RESP_FLOW。這個常數適用於 執行特定範圍的程式碼getter 可讓您取得流程變數,setter 則可讓您 流程變數這些變數通常可在 Proxy 流程中存取,且可在 Proxy 流程中使用 其他政策。

詳情請參閱下方的結構定義物件參考資料。 範例。

加密物件

加密編譯物件為 JavaScript 物件提供基本的高效能加密編譯支援。 模型如需詳細資訊和範例,請參閱下方的加密物件參考資料

要求和回應 物品

requestresponse 物件是「快速」參照, 可能是 Proxy 要求和回應,或目標要求和 回應。這些變數所參照的物件取決於 JavaScript 的結構定義 執行政策。如果 JavaScript 在 Proxy 端點的流程中執行,則要求和 回應變數是指 context.proxyRequestcontext.proxyResponse。如果 JavaScript 在目標流程中執行, 請參閱 context.targetRequestcontext.targetResponse

JavaScript 物件模型包含 print() 函式,可用來輸出偵錯 連線至 Edge Trace 工具請參閱使用 JavaScript print() 進行偵錯 陳述式

屬性物件

在政策設定中使用 元素時, JavaScript 程式碼可以使用 properties 變數。

舉例來說,如果您的 JavaScript 設定包含:

<Javascript name='JS-1' >
  <Properties>
    <Property name="number">8675309</Property>
    <Property name="firstname">Jenny</Property>
  </Properties>
  <ResourceURL>jsc://my-code.js</ResourceURL>
</Javascript>

接著,您可以在 my-code.js 中執行下列操作:

  print(properties.firstname);  // prints Jenny
  print(properties.number);  // 8675309

更重要的是,設定可讓程式碼的行為不同 就能在不同環境、不同時機 原因。

舉例來說,下列參數指定「變數名稱」還有風格 JavaScript 應將資訊發送為:

<Javascript name='JS-2' >
  <Properties>
    <Property name="output">my_output_variable</Property>
    <Property name="prettyPrint">true</Property>
  </Properties>
  <ResourceURL>jsc://emit-results.js</ResourceURL>
</Javascript>
接著,在 emit-results.js 中,程式碼可執行以下操作:
var result = { prop1: "something", prop2 : "something else" } ;
if (properties.prettyPrint == "true") {
  context.setVariable(properties.output, JSON.stringify(result, null, 2));
}
else {
  context.setVariable(properties.output, JSON.stringify(result));
}

加密物件參考資料

加密物件可讓您在 JavaScript 中執行基本的加密編譯雜湊函式。

加密物件具有全域範圍。不論在 API Proxy 流程中,均可使用。 啟用加密之後,您就能使用以下雜湊物件:

  • SHA-1
  • SHA256
  • SHA512
  • MD5
,瞭解如何調查及移除這項存取權。

使用 SHA-1 物件

您可以建立並更新 SHA-1 物件,然後將其轉換為十六進位值和 Base64 值。

建立新的 SHA-1 物件

var _sha1 = crypto.getSHA1();

更新 SHA-1 物件

語法

_sha1.update(value);

參數

  • value - (字串) 任何字串值。

範例

更新 SHA-1 物件:

_sha1.update("salt_value");

_sha1.update("some text");

以十六進位字串的形式傳回 SHA-1 物件

var _hashed_token = _sha1.digest();

以 Base64 字串的形式傳回 SHA-1 物件

var _hashed_token = _sha1.digest64();

使用 SHA-256 物件

您可以建立並更新 SHA-256 物件,然後將其轉換為十六進位值和 Base64 值。

建立新的 SHA-256 物件

var _sha256 = crypto.getSHA256();

更新 SHA-256 物件

語法

_sha256.update(value);

參數

  • value - (字串) 任何字串值。

範例

更新 SHA-256 物件:

_sha256.update("salt_value");

_sha256.update("some text");

以十六進位字串的形式傳回 SHA-256 物件

var _hashed_token = _sha256.digest();

以 Base64 字串的形式傳回 SHA-256 物件

var _hashed_token = _sha256.digest64();

使用 SHA-512 物件

您可以建立並更新 SHA-512 物件,然後將其轉換為十六進位值和 Base64 值。

建立新的 SHA-512 物件

var _sha512 = crypto.getSHA512();

更新 SHA-512 物件

語法

_sha512.update(value);

參數

  • value - (字串) 任何字串值。

範例

更新 SHA-512 物件:

_sha512.update("salt_value");

_sha512.update("some text");

以十六進位字串的形式傳回 SHA-512 物件

var _hashed_token = _sha512.digest();

以 Base64 字串的形式傳回 SHA-512 物件

var _hashed_token = _sha512.digest64();

使用 MD5 物件

您可以建立並更新 MD5 物件,然後將其轉換為十六進位值和 Base64 值。

建立新的 MD5 物件

var _md5 = crypto.getMD5();

更新 MD5 物件

語法

_md5.update(value);

參數

  • value - (字串) 任何字串值。

範例

更新 MD5 物件:

_md5.update("salt_value");

_md5.update("some text");

以十六進位字串的形式傳回 MD5 物件

var _hashed_token = _md5.digest();

以 Base64 字串的形式傳回 MD5 物件

var _hashed_token = _md5.digest64();

加密編譯日期/時間支援

加密物件支援日期/時間格式化模式。

crypto.dateFormat()

以字串格式傳回日期。

語法

crypto.dateFormat(format, [timezone], [time])

參數

  • format - (字串) 這個參數的基礎實作 是 java.text.SimpleDateFormat。 例如:「yyyy-MM-DD HH:mm:ss.SSS」。
  • timezone:(字串,選用) 此指標的基礎實作 參數是 java.util.TimeZone。 這個參數相同:UTC
  • time:(數字,選用) 要格式化的 Unix 時間戳記值。預設: 目前時間

範例

取得目前時間 (最低至毫秒):

var _now = crypto.dateFormat('yyyy-MM-DD HH:mm:ss.SSS');

取得太平洋時區的目前時間:

var _pst = crypto.dateFormat('yyyy-MM-DD HH:mm:ss.SSS','PST');

取得 10 秒後的值:

var _timeNow = Number(context.getVariable('system.timestamp'));
var ten_seconds = crypto.dateFormat('yyyy-MM-DD HH:mm:ss.SSS','PST', _timeNow + 10 * 1000);

其他範例。另請參閱 java.text.SimpleDateFormat 說明文件。

var _pst = crypto.dateFormat('M');
var _pst = crypto.dateFormat('EEE, d MMM yyyy HH:mm:ss Z');
var _pst = crypto.dateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");

使用 getHash() 取得 任何支援的雜湊物件

範例

var _hash1 = crypto.getHash('MD5');

var _hash2 = crypto.getHash('SHA-1');

var _hash3 = crypto.getHash('SHA-256');

var _hash4 = crypto.getHash('SHA-512');

加密貨幣取樣

try {
    // get values to use with hash functions
    var salt = context.getVariable("salt") || 'SomeHardCodedSalt';
    var host = context.getVariable("request.header.Host");
    var unhashed_token = "";

    var _timeNow = Number(context.getVariable('system.timestamp'));
    var now = crypto.dateFormat('yyyy-MM-DD HH:mm:ss.SSS','PST', _timeNow);
    unhashed_token = "|" + now + "|" + host

    // generate a hash with the unhashedToken:
    var sha512 = crypto.getSHA512();
    sha512.update(salt);
    sha512.update(unhashed_token);

    // convert to base64
    var base64_token = sha512.digest64();

    // set headers
    context.setVariable("request.header.now", now);
    context.setVariable("request.header.token", base64_token);

} catch(e) {
    throw 'Error in Javascript';
}

情境物件 參照

系統會為每個要求/回應交易執行的每項要求/回應交易建立 context 物件 並存取 API Proxycontext 物件會公開取得、設定及移除變數的方法 與每筆交易相關。

變數會定義交易專屬的屬性。時間、地區語言 請求用戶端、提出要求用戶端的使用者代理程式,以及目標服務的網址 context 中所有可用的變數。因此 context 適合建構依賴這些屬性執行的邏輯 自訂行為

請參閱流程變數參考資料擷取變數 政策

背景資訊 物件摘要

這個表格會簡要說明結構定義物件及其子項,並列出相關屬性 各個項目

名稱 說明 屬性
context 訊息處理管道結構定義,以及要求和回應的包裝函式 ProxyEndpoint 和 TargetEndpoint 執行的流程。 流程, 工作階段
context.proxyRequest 這個物件代表對 ProxyEndpoint 的傳入要求訊息 (來自 向 API Proxy 要求應用程式) 標題, 查詢參數, 方法, 內文, 網址
context.targetRequest 這個物件代表來自 TargetEndpoint 的傳出要求訊息 (來自 從 API Proxy 連線到後端服務 標題, 查詢參數, 方法, 內文, 網址
context.targetResponse 代表傳入目標回應訊息的物件 (來自後端服務) 至 API Proxy) 標題、內容、狀態
context.proxyResponse 代表傳出 Proxy 回應訊息的物件 (從 API Proxy 到 提出要求的應用程式) 標題、內容、狀態
context.flow 目前流程的名稱。 請參閱下方的 context.flow
context.session 名稱/值組合的對應,可用於在兩個不同步驟之間傳送物件 並在相同情況下執行例如 context.session['key'] = 123 如要進一步瞭解該物件的使用時機和時機,請參閱 Apigee 社群討論。

背景資訊 物件方法

context.getVariable()

擷取預先定義或自訂變數的值。

語法

context.getVariable("variable-name");

範例

如何取得今年的值:

var year = context.getVariable('system.time.year');

context.setVariable()

為自訂變數或任何可寫入的 預先定義變數設定值。

語法

context.setVariable("variable-name", value);

範例

設定變數的常見情況是 API Proxy 必須以動態方式 目標網址下列 JavaScript 會取得名為 USER.name 的變數值。 將這個值以查詢參數形式附加至網址 http://mocktarget.apigee.net?user=,然後設定預先定義的 target.url

context.setVariable("target.url", "http://mocktarget.apigee.net/user?user="+context.getVariable("USER.name"));

context.removeVariable()

從結構定義中移除變數。

語法

context.removeVariable('variable-name');

結構定義物件屬性

context.flow

flow 屬性是目前 API Proxy 流程的字串。這個 屬性用來指出附加 JavaScript 的流程。支援的值 是:

  • PROXY_REQ_FLOW
  • PROXY_RESP_FLOW
  • TARGET_REQ_FLOW
  • TARGET_RESP_FLOW

每個流程名稱都包含 PreFlow、PostFlow 以及 ProxyEndpoint 或 Target Endpoints

當您在多個流程中執行通用 JavaScript 時,這個選用屬性就很實用。 但它的行為可能會依據其執行的流程而有所不同。使用「流程」屬性 建立要在多個 API Proxy 中重複使用的 JavaScript 模組,程式碼 在執行邏輯前,需要先檢查目前的 Flow。

範例

僅在 targetRequest 流程上設定 HTTP 標頭:

if (context.flow=="TARGET_REQ_FLOW") {
     context.targetRequest.headers['TARGET-HEADER-X']='foo';
}

僅在 ProxyResponse 流程上設定內容:

if (context.flow=="PROXY_RESP_FLOW") {
     context.proxyResponse.content='bar';
}

context.session

名稱/值組合的對應,可用於在兩個執行中的政策之間傳送物件 相同訊息情境下

範例

設定工作階段中的值:

context.session['key']  = 123;

取得工作階段的值:

var value = context.session['key']; // 123

情境物件子項

如下所示,完整的 API Proxy 流程包含四個不同的階段,且每個階段 相關訊息物件 (這是內容物件的子項):

  • context.proxyRequest:從要求取得的傳入要求訊息 用戶端。
  • context.targetRequest:傳送至後端的傳出要求訊息 課程中也會快速介紹 Memorystore 這是 Google Cloud 的全代管 Redis 服務
  • context.proxyResponse:將傳出回應訊息傳回給 請求用戶端。
  • context.targetResponse:從後端收到的傳入要求訊息 課程中也會快速介紹 Memorystore 這是 Google Cloud 的全代管 Redis 服務

以下各節說明這些物件的方法和屬性:

背景內容。*要求子項物件

在 API Proxy 中執行的每項 HTTP 交易中,您有兩個要求訊息物件 已建立:一項「傳入」 (來自用戶端的要求) 和一個「傳出」 (由 並提交至後端目標)。

context 物件包含代表以下要求訊息的子物件: context.proxyRequestcontext.targetRequest。您可以透過這些物件 存取 JavaScript 程式碼時,要求流程中的屬性。 執行作業。

注意:您也可以使用簡寫物件 request 來存取 在要求流程中執行這些屬性request 物件是指 context.proxyRequestcontext.targetRequest,視 方便您瞭解 JavaScript 程式碼執行流程

content.*要求子項物件屬性

屬性名稱 說明
url

url 屬性是讀取/寫入便利屬性, targetRequest 的配置、主機、通訊埠、路徑和查詢參數。

要求的完整網址由下列屬性組成:

  • 通訊協定:網址的通訊協定 (例如 HTTP、HTTPS)
  • 通訊埠:通訊埠 (例如 :80、:443)
  • host:網址的主機 (例如 www.example.com)
  • path:URI 路徑 (例如 /v1/mocktarget)

取得 url 時,系統會使用以下格式傳回網址:

protocol://host:port/path?queryParams

範例:

context.targetRequest.url = 'http://www.example.com/path?q1=1'
context.targetRequest.protocol ='https';
headers

HTTP 要求標頭可對應 String => List

範例:

針對這個 HTTP 要求:

POST /v1/blogs HTTP/1.1
Host: api.example.com
Content-Type: application/json
Authorization: Bearer ylSkZIjbdWybfs4fUQe9BqP0LH5Z
下列 JavaScript:
context.proxyRequest.headers['Content-Type'];
context.proxyRequest.headers['Authorization'];

會傳回下列值

application/json
Bearer ylSkZIjbdWybfs4fUQe9BqP0LH5Z
queryParams

要求訊息查詢參數,做為 String => List 的對應。

範例:

"?city=PaloAlto&city=NewYork"

可以當成:

context.proxyRequest.queryParams['city'];  // == 'PaloAlto'
context.proxyRequest.queryParams['city'][0]     // == 'PaloAlto'
context.proxyRequest.queryParams['city'][1];    // == 'NewYork'
context.proxyRequest.queryParams['city'].length(); // == 2
method

HTTP 動詞 (GETPOSTPUTDELETE PATCH 等)

範例:

針對這項要求:

POST /v1/blogs HTTP/1.1
Host: api.example.com
Content-Type: application/json
Authorization: Bearer ylSkZIjbdWybfs4fUQe9BqP0LH5Z

下列 JavaScript:

context.proxyRequest.method;

會傳回下列值

POST
body

HTTP 要求的訊息主體 (酬載)。

要求主體具備下列成員:

  • context.targetRequest.body.asXML;
  • context.targetRequest.body.asJSON;
  • context.targetRequest.body.asForm;

範例:

XML 內文:

<customer number='1'>
<name>Fred<name/>
<customer/>

如要存取 XML 物件的元素,請按照下列步驟操作:

var name = context.targetRequest.body.asXML.name;

如要存取 XML 屬性屬性,請使用 @ 標記法。

var number = context.targetRequest.body.asXML.@number;

JSON 要求主體:

{
"a":  1 ,
"b" : "2"
}
var a = context.proxyRequest.body.asJSON.a;    // == 1
var b = context.proxyRequest.body.asJSON.b;    // == 2

如何讀取表單參數:

"vehicle=Car&vehicle=Truck"
v0 = context.proxyRequest.body.asForm['vehicle'][0];
v1 = context.proxyRequest.body.asForm['vehicle'][1];

context.*Response 子物件

在 API Proxy 中執行的每項 HTTP 交易中,會有兩個回應訊息物件 已建立:一個「傳入」 (後端服務的回應) 和一個「傳出」 (回應 傳回給用戶端)。

結構定義物件包含代表以下回應訊息的子物件: 《context.proxyResponse》和《context.targetResponse》。您可以透過這些物件 存取 JavaScript 程式碼時,回應流程中該範圍內的屬性 執行作業。

注意:您也可以使用簡寫物件 response 來存取 回應流程中的這些屬性response 物件是指 context.proxyResponsecontext.targetResponse,視 方便您瞭解 JavaScript 程式碼執行流程

context.*Response 物件屬性

屬性名稱 說明
headers

回應訊息的 HTTP 標頭,做為 String => List 的對應。

範例:

var cookie = context.targetResponse.headers['Set-Cookie'];
status

包含狀態訊息做為屬性的狀態碼。狀態碼和狀態訊息 可做為屬性使用

範例:

var status = context.targetResponse.status.code;   // 200
var msg = context.targetResponse.status.message;   // "OK"
content

回應訊息的 HTTP 主體 (酬載內容)。

回應內容會具有以下成員:

context.targetResponse.content.asXML;
context.targetResponse.content.asJSON;

使用 .asXML 標記法

使用 .asXML 標記法瀏覽 XML 文件是簡單又方便的方法。 本節說明這項標記法的使用方式,以及與這種標記的差異 《request.content》和《context.proxyRequest.content》。

例如:

request.content.asXML

context.proxyRequest.content.asXML

*.content*.content.asXML 表單都可用於字串 JavaScript 會強制將這些元素轉換成字串,在第一種案件中 (*.content),字串會包含所有宣告和 XML 註解。在 後者 (*.content.asXML),系統會清理結果的字串值 聲明和意見。

範例

msg.content:

<?xml version="1.0" encoding="UTF-8"?>
<yahoo:error xmlns:yahoo="http://yahooapis.com/v1/base.rng" xml:lang="en-US">
   <yahoo:description>Please provide valid credentials. OAuth oauth_problem="unable_to_determine_oauth_type", realm="yahooapis.com"
   </yahoo:description>
</yahoo:error>
<!-- mg023.mail.gq1.yahoo.com uncompressed/chunked Sat Dec 14 01:23:35 UTC 2013 -->

msg.content.asXML:

<?xml version="1.0" encoding="UTF-8"?>
<yahoo:error xmlns:yahoo="http://yahooapis.com/v1/base.rng" xml:lang="en-US">
   <yahoo:description>Please provide valid credentials. OAuth oauth_problem="unable_to_determine_oauth_type", realm="yahooapis.com"
   </yahoo:description>
</yahoo:error>

此外,您可以使用 .asXML 表單掃遍 XML 階層,方法是: 指定元素和屬性的名稱無法掃遍階層 使用其他語法

使用 JavaScript 進行偵錯 print() 陳述式

請注意,如果您使用 JavaScript 政策執行自訂 JavaScript 程式碼,就可以使用 使用 print() 函式將偵錯資訊輸出至「追蹤工具」。這個函式可直接使用 讀取及傳遞資訊例如:

if (context.flow=="PROXY_REQ_FLOW") {
     print("In proxy request flow");
     var username = context.getVariable("request.queryparam.user");
     print("Got query param: " + username);
     context.setVariable("USER.name", username);
     print("Set query param: " + context.getVariable("USER.name"));
}


if (context.flow=="TARGET_REQ_FLOW") {
     print("In target request flow");
     var username = context.getVariable("USER.name");
     var url = "http://mocktarget.apigee.net/user?"
     context.setVariable("target.url", url + "user=" + username);
     print("callout to URL: ", context.getVariable("target.url"));
}

如要查看輸出內容,請在頁面底部選取「Output from 所有交易的輸出內容」。 Trace 視窗。您也可以在名為 stepExecution-stdout 的 Trace 屬性中找到輸出內容。

使用 httpClient 進行 JavaScript 呼叫

使用 httpClient 向任何網址發出多個並行的非同步 HTTP 要求 從在 API Proxy 流程中執行的自訂 JavaScript 程式碼內執行。 httpClient 物件由 Apigee Edge JavaScript 物件公開 模型

關於 httpClient

httpClient 物件會向在 Apigee Edge 上執行的自訂 JavaScript 程式碼公開 讀取及傳遞資訊如要將自訂 JavaScript 附加至 API Proxy,請使用 JavaScript 政策。當 自訂 JavaScript 程式碼就會執行

httpClient 物件適合用於開發複合服務或 混搭影片。舉例來說,您可以將多個後端呼叫合併為單一 API 方法。 這個物件通常會做為 ServiceCALL 政策的替代方案。

以下是基本使用模式。建立要求物件例項,並指派給其網址 (例如 您希望呼叫的後端服務),並透過該要求呼叫 httpClient.send 物件。

var myRequest = new Request();
myRequest.url = "http://www.example.com";
var exchangeObj = httpClient.send(myRequest);

httpClient 參考資源

HTTP 用戶端會公開兩種方法:get()send()

httpClient.get()

用於簡易 HTTP GET 要求的便利方法,不支援 HTTP 標頭。

用法

var exchangeObj = httpClient.get(url);

退貨

這個方法會傳回 exchange 物件。這個物件沒有任何屬性 列出下列方法:

  • isError():(布林值) 如果 httpClient 無法連線,會傳回 true 連線至伺服器HTTP 狀態碼 4xx5xx 會導致 isError() false,表示連線已完成,且回應有效 驗證碼。如果 isError() 傳回 true,則系統會對 getResponse() 會傳回 JavaScript undefined
  • isSuccess():(布林值) 如果傳送完成,則傳回 true 成功。
  • isComplete():(布林值) 如果要求為true 完成。
  • waitForComplete():讓執行緒暫停,直到要求完成 (成功) 為止 或發生錯誤)。
  • getResponse():(物件) 如果 httpClient.send() 已完成,並順利完成。傳回的物件 方法和屬性都相同。請參閱結構定義物件摘要
  • getError():(字串) 如果呼叫 httpClient.send() 導致 錯誤訊息,系統會以字串形式傳回錯誤訊息。

範例

傳送設定完成且包含 HTTP 屬性的 Request 物件 請求。使用非阻塞回呼來處理回應。

// Add the required the headers for making a specific API request
var headers = {'X-SOME-HEADER' : 'some value' };
// Make a GET API request along with headers
var myRequest = new Request("http://www.example.com","GET",headers);

// Define the callback function and process the response from the GET API request
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(myRequest, onComplete);

使用 JavaScript 政策

使用 JavaScript 政策將自訂 JavaScript 程式碼附加至 Proxy 流程。請參閱 JavaScript 政策

相關主題

Apigee 社群文章

您可以前往 Apigee 參閱這些相關文章 社群