處理錯誤

您目前查看的是 Apigee Edge 說明文件。
參閱 Apigee X 說明文件
資訊

當 API Proxy 從應用程式處理要求時,可能會發生許多錯誤狀況。例如,與後端服務進行通訊時,API Proxy 可能會發生網路問題、應用程式可能顯示已過期的憑證、要求訊息的格式可能不正確等等。

如果用戶端應用程式呼叫 API Proxy 時發生錯誤,錯誤訊息就會傳回至用戶端。根據預設,用戶端會收到隱密的錯誤訊息,其中未提供詳細資料或指引。不過,如果您想以更實用的自訂訊息取代預設錯誤訊息,甚至利用其他 HTTP 標頭等內容來充實這些訊息,就必須在 Edge 中設定自訂錯誤處理功能。

您也可以利用自訂錯誤處理功能,在發生錯誤時新增訊息記錄等功能。

在說明在 API Proxy 中實作自訂錯誤處理功能之前,建議您先瞭解錯誤發生的方式,以及 API Proxy 對這些錯誤的回應方式。

影片

請觀看以下影片,進一步瞭解錯誤處理機制。

影片 說明
錯誤處理和錯誤流程簡介 瞭解錯誤處理機制,以及 API Proxy 發生錯誤時會發生什麼情況。
使用錯誤規則處理錯誤 瞭解如何使用錯誤規則處理錯誤。
使用 IncreaseFault 政策提高自訂錯誤 在 API 執行階段使用 IncreaseFault 政策引發自訂錯誤。
在 API Proxy 和目標端點中定義錯誤規則 在 API Proxy 和目標端點中定義錯誤規則,以及瞭解差異。
瞭解錯誤規則的執行順序 瞭解 API Proxy 和目標端點中的錯誤規則執行順序。
定義預設錯誤規則 定義預設錯誤規則來處理 API 中的一般錯誤。

錯誤發生方式

首先,我們會說明錯誤發生的方式。瞭解錯誤發生的方式有助於針對要實作自訂錯誤處理的不同情況做好規劃。

自動錯誤

在以下情況中,API Proxy 會自動擲回錯誤:

  • 政策會擲回錯誤。舉例來說,如果 API 呼叫傳送過期的金鑰,VerifyAPIKey 政策會自動擲回錯誤;如果 API 呼叫數量超過特定限制,則配額政策SpikeArrest 政策會擲回錯誤。(如要瞭解可能擲回的錯誤政策類型,請參閱政策錯誤參考資料)。
  • API Proxy 訊息流程發生問題,例如轉送錯誤。
  • 後端失敗,例如因通訊協定層級失敗而發生 HTTP 錯誤、TLS/SSL 錯誤或目標服務無法使用。
  • 發生系統層級的錯誤,例如記憶體不足的例外狀況。

如要進一步瞭解這些錯誤,請參閱本主題的假分類一節。

自訂錯誤

在沒有自動錯誤的情況下,您可能需要擲回自訂錯誤,例如回應包含「unavailable」一詞,或 HTTP 狀態碼大於 201。請在 API Proxy 流程中適當的位置新增 IncreaseFault 政策

您可以在 API Proxy 流程中新增 好處 Fault 政策,做法與新增任何其他政策相同。在以下 Proxy 設定範例中,Raise-Fault-1 政策會附加至 TargetEndpoint 回應。如果目標服務的回應中出現「unavailable」字詞,系統就會執行 IncreaseFault 政策,並擲回錯誤。

<TargetEndpoint name="default">
...
  <Response>
    <Step>
      <Name>Raise-Fault-1</Name>
      <Condition>(message.content Like "*unavailable*")</Condition>
    </Step>
  </Response>

這只是要表示您可以擲回自訂錯誤。如要進一步瞭解 OverFault 政策,請參閱「FaultRules vs. 好處 Fault 政策」一節。

如需更多範例,請參閱 Apigee 社群論壇中的下列文章:

API Proxy 發生錯誤時會採取哪些動作

Proxy 擲回錯誤時會發生的情況。

退出 Proxy 管道

當 API Proxy 遇到錯誤時,無論發生方式為何,都會結束一般流程管道、進入錯誤狀態,並將錯誤訊息傳回用戶端應用程式。API Proxy 進入錯誤狀態後,就無法將處理程序傳回一般流程管道。

舉例來說,假設 API Proxy 在 ProxyEndpoint 要求中的順序如下:

  1. 驗證 API 金鑰
  2. 配額
  3. JSON 格式

如果在 API 金鑰驗證期間發生錯誤,API Proxy 就會進入錯誤狀態。系統不會執行配額和 JSON 到 XML 政策,Proxy 不會繼續前往 TargetEndpoint,且用戶端應用程式會顯示錯誤訊息。

檢查 FaultRules

在錯誤狀態中,API Proxy 也會按照 API Proxy 設定檢查是否含有下列項目 (依序) 是否將預設錯誤訊息傳回用戶端應用程式:

  1. <FaultRules> 區段,包含根據您定義的特定條件觸發自訂錯誤訊息 (和其他政策) 的邏輯。
  2. <DefaultFaultRule> 區段,會在下列情況中觸發預設錯誤訊息:
    • 未定義任何 <FaultRules>
    • 系統不會執行現有的 <FaultRules>
    • <AlwaysEnforce> 元素已設為 true。

基本上,API Proxy 可讓您傳回自訂錯誤訊息及觸發其他邏輯。如果 Proxy 找不到這些區段,或是存在沒有自訂錯誤,Proxy 會自行傳送 Edge 產生的預設訊息。

簡易錯誤處理示例

先從簡單的範例開始,對 API Proxy 的呼叫並未包含必要的 API 金鑰。根據預設,系統會傳回以下回應至用戶端應用程式:

HTTP/1.1 401 Unauthorized
Date: Wed, 20 Jul 2016 19:19:32 GMT
Content-Type: application/json
Content-Length: 150
Connection: keep-alive
Server: Apigee Router

* Connection #0 to host myorg-test.apigee.net left intact
{"fault":{"faultstring":"Failed to resolve API Key variable request.queryparam.apikey","detail":{"errorcode":"steps.oauth.v2.FailedToResolveAPIKey"}}}

您的 API 使用者或許能找到錯誤訊息,但可能無法瞭解。而且許多預設錯誤則更為細緻,而且不易解密。

API 開發人員可以自行變更這則訊息,滿足最終收到錯誤訊息的人員需求,無論是 iOS 應用程式開發人員,還是有本身錯誤訊息格式規定的內部測試群組都適用。

這個基本範例將說明如何建立自訂錯誤訊息來處理這項錯誤。這需要 1) 定義自訂訊息的政策,以及 2) 用於在 Proxy 進入錯誤狀態時執行政策的 FaultRule。

1. 建立可定義自訂訊息的政策

首先,請建立定義自訂錯誤訊息的政策。您可以使用任何類型的政策 (例如 AssignMessage 政策) 設定酬載和選用的 HTTP 標頭,例如狀態碼和原因詞組。指定訊息非常適合用於這個目的。可讓您控管訊息酬載、設定其他 HTTP 狀態碼、設定不同的 HTTP 原因詞組,以及新增 HTTP 標頭。

請勿將政策附加至 API Proxy 中的任何流程。只是存在於 Proxy 套件中就夠了。如要在管理 UI Proxy 編輯器中執行這項操作,請前往「開發」分頁,然後在導覽窗格中點選「政策」列的 + 圖示。

這可讓您建立政策,而不必將其附加至 API Proxy 中的流程。未附加至任何流程的政策會在政策清單中加上「已卸離」圖示標記,與上圖所示的 API 金鑰訊息政策相鄰。

以下是 AssignMessage 政策的範例:

  • 傳回 JSON 訊息。
  • 設定 HTTP 狀態碼 (911;這是明顯不存在的狀態碼,只是用於說明您的彈性)。狀態碼會顯示在 HTTP 標頭中。
  • 設定 HTTP 原因詞組 (以取代這個缺少 API 金鑰錯誤的預設「未經授權」原因詞組)。原因詞組會顯示在 HTTP 標頭中的狀態碼旁邊。
  • 建立並填入名為 invalidKey 的新 HTTP 標頭。
<AssignMessage async="false" continueOnError="false" enabled="true" name="invalid-key-message">
    <DisplayName>Invalid key message</DisplayName>
    <Set>
        <Payload contentType="application/json">{"Citizen":"Where's your API key? I don't see it as a query parameter"}</Payload>
        <StatusCode>911</StatusCode>
        <ReasonPhrase>Rejected by API Key Emergency Services</ReasonPhrase>
    </Set>
    <Add>
        <Headers>
            <Header name="invalidKey">Invalid API key! Call the cops!</Header>
        </Headers>
    </Add>
    <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
    <AssignTo createNew="false" transport="http" type="request"/>
</AssignMessage>

執行這項政策後,對用戶端應用程式的回應如下所示。 並和先前顯示的預設回應進行比較。

HTTP/1.1 911 Rejected by API Key Emergency Services
Date: Wed, 20 Jul 2016 18:42:36 GMT
Content-Type: application/json
Content-Length: 35
Connection: keep-alive
invalidKey: Invalid API key! Call the cops!
Server: Apigee Router

* Connection #0 to host myorg-test.apigee.net left intact
{"Citizen":"Where's your API key? I don't see it as a query parameter."}

是的,有點傻,但看起來有潛力。收到訊息的開發人員至少知道他們忘了加入 API 金鑰做為查詢參數。

但這項政策是如何執行的?下一節將為您顯示。

2. 建立會觸發政策的 <FaultRule>

在 Proxy 設定的 <ProxyEndpoint><TargetEndpoint> 區段中,您將新增包含一或多個個別 <FaultRule> 區段的 <FaultRules> XML 區塊。每個 FaultRule 都代表要處理的不同錯誤。在本簡易範例中,我們僅使用一個 FaultRule 來說明其組成內容。

如果未執行任何 FaultRules,您也應新增 <DefaultFaultRule>,以提供自訂的一般錯誤訊息。

範例

<ProxyEndpoint name="default">
...
    <FaultRules>
       <FaultRule name="invalid_key_rule">
            <Step>
                <Name>invalid-key-message</Name>
            </Step>
            <Condition>(fault.name = "FailedToResolveAPIKey")</Condition>
        </FaultRule>
    </FaultRules>
    <DefaultFaultRule name="default-fault">
        <Step>
            <Name>Default-message</Name>
        </Step>
    </DefaultFaultRule>

重點:

  • FaultRules 是在 ProxyEndpoint 中定義。這很重要進一步瞭解如何在 ProxyEndpoint 和 TargetEndpoint 中加入 FaultRules。
  • <Name>:要執行的政策名稱。這個名稱來自父項元素中政策的 name 屬性,如前述的政策範例所示。
  • <Condition> - 邊緣評估條件並只在條件為 True 時執行政策。如果有多個 FaultRules 評估為 true,則 Edge 會執行第一個為 true 的 FaultRule。(重要事項:FultRules 的捨棄順序 (由上至下或由下到上),TargetEndpoint 和 ProxyEndpoint 之間會有所不同,如多個 FaultRules and 執行邏輯一節所述。)如未加入條件,FultRule 會自動設為 true。但這不是最佳做法。每個 FaultRule 都應有自己的條件。

  • <DefaultFaultRule> - 如未執行自訂 FaultRule,系統會執行 <DefaultFaultRule>,並傳送較一般的自訂訊息,而非隱含的預設 Edge 產生訊息。<DefaultFaultRule>也可以包含 <Condition>,但在大部分情況下,您不會加入其中一個,因為您希望不管是什麼做法都能執行。

    DefaultFaultRule 通常用於針對任何非預期的錯誤傳回一般錯誤訊息。例如訊息,內含技術支援人員的聯絡資訊。這項預設回應主要用於提供方便開發人員的資訊,同時對後端網址或其他可能用於入侵系統的資訊進行模糊處理。

多個 FaultRules 和執行邏輯

簡易錯誤處理範例一節中,我們使用了一個 FaultRule 和條件的簡單範例。在實際的 API 專案中,可能發生所有可能發生的錯誤,且 <ProxyEndpoint><TargetEndpoint> 中可能同時含有多個 FaultRules 和 DefaultFaultRule。最終,當 API Proxy 進入錯誤狀態時,系統只會執行一個 FaultRule。

本節說明 Edge Edge 在處理 FaultRule 時使用的邏輯,從其到達單一 FaultRule 的方式,到觸發 FaultRule 時,系統如何處理「內部」步驟條件。本節也說明在 <ProxyEndpoint><TargetEndpoint> 中定義 FaultRules 的時機,以及 FaultRules 和 IncreaseFault 政策之間的關係。

FaultRules 執行

簡單來說,API Proxy 進入錯誤狀態時,Edge 使用的邏輯如下。請注意,ProxyEndpoint 中的 FaultRules 評估與 TargetEndpoint 的評估方式略有不同。

  1. Edge 會依據發生錯誤的位置,評估 ProxyEndpoint 或 TargetEndpoint 中的 FaultRules:
    • ProxyEndpoint - 邊緣的設定會從設定 XML 中的 底部 <FaultRule> 開始,然後往上運作,接著評估每個 <FaultRule><Condition> (「外部」條件,而非「內部」<Step> 條件)。
    • TargetEndpoint - 邊緣的從設定 XML 中的 top <FaultRule> 開始,然後向下運作,接著會評估每個 <FaultRule><Condition> (「外部」條件,而非「內部」<Step> 條件)。
  2. 執行條件為 true 的 first FaultRule。如果 FaultRule 沒有條件,則預設為 true。
    • 執行 FaultRule 時,系統會依序評估 FaultRule 中的所有步驟,由 XML 設定由上而下進行。系統會自動執行沒有條件的步驟 (系統會執行政策),以及執行<Condition>評估結果為「true」的步驟 (系統不會執行評估為「false」的條件)。
    • 如果已執行 FaultRule,但沒有執行 FaultRule 中的步驟 (因為當中的條件評估為「false」),Edge 產生的預設錯誤訊息將傳回至用戶端應用程式。由於 Edge 已執行其一項 FaultRule,因此「不會」執行 <DefaultFaultRule>

  3. 如未執行 FaultRule,邊緣會執行 <DefaultFaultRule> (如有)。

以下是內嵌註解的範例。

ProxyEndpoint 執行

ProxyEndpoint FaultRules 的評估結果由下到上,請從下例中的最後一個 FaultRule 開始閱讀,然後逐步完成工作。最後查看 DefaultFaultRule。

<ProxyEndpoint name="default">
...
    <FaultRules>
<!-- 3. This FaultRule is automatically TRUE, because there's no "outer" 
     condition. But because the FaultRule just below this got
     executed (bottom-to-top evaluation in a ProxyEndpoint), Edge
     doesn't even evaluate this FaultRule.
     Note that it's not a best practice to have a FaultRule without 
     an outer condition, which automatically makes the FaultRule true. -->
        <FaultRule name="random-error-message">
            <Step>
                <Name>Random-fault</Name>
            </Step>
        </FaultRule>
<!-- 2. Let's say this fault is TRUE. The Quota policy threw a QuotaViolation
     error. This is the first FaultRule to be TRUE, so it's executed. 
     Now the Steps are evaluated, and for the ones whose conditions
     evaluate to TRUE, their policies are executed. Steps without
     conditions are automatically true. -->
<FaultRule name="over_quota">
            <Step>
                <Name>developer-over-quota-fault</Name>
                <Condition>(ratelimit.developer-quota-policy.exceed.count GreaterThan "0")</Condition>
            </Step>
            <Step>
                <Name>global-over-quota-fault</Name>
                <Condition>(ratelimit.global-quota-policy.exceed.count GreaterThan "0")</Condition>
            </Step>
            <Step>
                <Name>log-error-message</Name>
            </Step>
            <Condition>(fault.name = "QuotaViolation")</Condition>
        </FaultRule>
<!-- 1. Because this is the ProxyEndpoint, Edge looks at this FaultRule
     first. But let's say this FaultRule is FALSE. A policy did not 
     throw a FailedToResolveAPIKey error. Edge moves UP to check
     the next FaultRule. -->
        <FaultRule name="invalid_key_rule">
            <Step>
                <Name>invalid-key-message</Name>
            </Step>
            <Condition>(fault.name = "FailedToResolveAPIKey")</Condition>
        </FaultRule>
    </FaultRules>

<!-- If no <FaultRule> is executed, the <DefaultFaultRule> is executed. 
     If a FaultRule is executed, but none of its Steps are executed,
     The DefaultFaultRule is not executed (because Edge has already
     executed its one FaultRule). -->
    <DefaultFaultRule name="default-fault">
        <Step>
            <Name>Default-message</Name>
        </Step>
    </DefaultFaultRule>

執行目標端點

評估目標端點 FaultRules 由上至下,因此請先閱讀以下範例中第一個 FaultRule 的內容,然後逐步完成工作。最後查看 DefaultFaultRule。

<TargetEndpoint name="default">
...
    <FaultRules>
<!-- 1. Because this is the TargetEndpoint, Edge looks at this FaultRule
     first. Let's say this FaultRule is FALSE. 
     A policy did not throw a FailedToResolveAPIKey error. 
     Edge moves down to the next FaultRule. -->
        <FaultRule name="invalid_key_rule">
            <Step>
                <Name>invalid-key-message</Name>
            </Step>
            <Condition>(fault.name = "FailedToResolveAPIKey")</Condition>
        </FaultRule>
<!-- 2. Let's say this fault is TRUE. The Quota policy threw a QuotaViolation
     error. This is the first FaultRule to be TRUE, so it's executed. 
     Now the Steps are evaluated, and for the ones whose conditions
     evaluate to TRUE, their policies are executed. Steps without
     conditions are automatically true. -->
        <FaultRule name="over_quota">
            <Step>
                <Name>developer-over-quota-fault</Name>
                <Condition>(ratelimit.developer-quota-policy.exceed.count GreaterThan "0")</Condition>
            </Step>
            <Step>
                <Name>global-over-quota-fault</Name>
                <Condition>(ratelimit.global-quota-policy.exceed.count GreaterThan "0")</Condition>
            </Step>
            <Step>
                <Name>log-error-message</Name>
            </Step>
            <Condition>(fault.name = "QuotaViolation")</Condition>
        </FaultRule>
<!-- 3. This FaultRule is automatically TRUE, because there's no "outer" 
     condition. But because the FaultRule just above this got
     executed (top-to-bottom evaluation in a TargetEndpoint), Edge
     doesn't even evaluate this FaultRule.
     Note that it's not a best practice to have a FaultRule without 
     an outer condition, which automatically makes the FaultRule true. -->
        <FaultRule name="random-error-message">
            <Step>
                <Name>Random-fault</Name>
            </Step>
        </FaultRule>
    </FaultRules>

<!-- If no <FaultRule> is executed, the <DefaultFaultRule> is executed. 
     If a FaultRule is executed, but none of its Steps are executed,
     The DefaultFaultRule is not executed (because Edge has already
     executed its one FaultRule). -->
    <DefaultFaultRule name="default-fault">
        <Step>
            <Name>Default-message</Name>
        </Step>
    </DefaultFaultRule>

錯誤規則順序

如前述範例所示,您在 FaultRules 的排列順序非常重要,實際情況取決於您在 ProxyEndpoint 中是否發生錯誤,以及 TargetEndpoint 中是否會發生。

例如:

ProxyEndpoint 順序 目標端點順序

在以下範例中,由於評估作業由下至上,因此執行 FaultRule 3,這表示不會評估 FaultRules 2 和 1。

5. FaultRule 1:FALSE

4. FaultRule 2:TRUE

3. FaultRule 3:TRUE

2. FaultRule 4:FALSE

1. FaultRule:5 FALSE

在以下範例中,由於評估作業由上至下,因此執行 FaultRule 2,這表示不會評估 FaultRules 3、4 和 5。

1. FaultRule 1:FALSE

2. FaultRule 2:TRUE

3. FaultRule 3:TRUE

4. FaultRule 4:FALSE

5. FaultRule:5 FALSE

要納入的政策

如要執行 FaultRule 中的任何政策,只要執行步驟即可。例如,您可以執行 AssignMessage 政策來為用戶端應用程式的回應設定格式,然後使用 MessageLogging 政策記錄訊息。政策會按照您設定的順序執行 (在 XML 中由上而下)。

錯誤規則「只會」在錯誤狀態中觸發 (關於 continueOnError)

標題看起來似乎已經重複了,但關於導致 API Proxy 進入錯誤狀態 (或「不是」輸入錯誤狀態) 時,標題應指的 continueOnError 屬性又要特別留意。

重點回顧:只有 Proxy 已進入錯誤狀態時,API Proxy 才會評估 <FaultRules><DefaultFaultRule>。這表示即使 FaultRule 條件評估為 true,即使 Proxy 未處於錯誤狀態,也不會觸發。

不過,以下是發生錯誤的示例,以及 Proxy 未進入錯誤狀態的例子。無論設定任何政策,您都可以在名為 continueOnError 的父項元素上設定屬性。 該屬性在處理錯誤時相當重要,因為這個屬性會決定 Proxy 是否會在政策失敗時進入錯誤狀態。在大多數情況下,建議您保留預設的 continueOnError="false",以便在政策失敗時讓 Proxy 進入錯誤狀態,並觸發自訂錯誤處理機制。不過,如果 continueOnError="true" (例如,如果您不希望服務呼叫失敗來停止 Proxy 執行作業),則當政策失敗時,Proxy 不會進入錯誤狀態,且 Proxy 也不會查看您的 FaultRules。

如要瞭解在 continueOnError="true" 時記錄錯誤,請參閱「處理目前流程中的政策錯誤」。

哪裡可以定義 FaultRules:ProxyEndpoint 或 TargetEndpoint

當 API Proxy 發生錯誤,錯誤會在 <ProxyEndpoint> (向用戶端應用程式發出的要求或回應用戶端應用程式) 或 <TargetEndpoint> (對目標服務的要求或回應) 發生。如有任何錯誤發生,Edge 就會尋找 FaultRules。

舉例來說,如果目標伺服器無法使用 (HTTP 狀態碼 503),API Proxy 就會進入 <TargetEndpoint> 回應中的錯誤狀態,且一般 API Proxy 流程不會繼續前往 <ProxyEndpoint>。如果只在 <ProxyEndpoint> 中定義了 FaultRules,就不會處理這項錯誤。

以下再舉一例說明:如果 <ProxyEndpoint> 回應上的 IncreaseFault 政策觸發了錯誤,系統不會執行 <TargetEndpoint> 中的 FaultRule。

FaultRules 與 IncreaseFault 政策的比較

錯誤規則和 IncreaseFault 政策在表面上可能發音,例如完成容錯處理的替代方法,有時就是符合的情境。但這些工具也能相輔相成本節將說明兩者之間的關係。瞭解這種關係應該有助於設計錯誤處理程序,尤其當您同時使用兩者時更是如此。

簡單來說:

  • 當 API Proxy 進入錯誤狀態時,系統一律會評估錯誤規則
  • OverFault 政策是在錯誤不會發生時,讓 API Proxy 進入錯誤狀態的方法。

    舉例來說,假如您想要在目標服務回應中的 HTTP 狀態碼大於 200 時擲回錯誤,請在回應流程中新增 IncreaseFault 政策。程式碼應如下所示:

    <TargetEndpoint name="default">
        <PreFlow name="PreFlow">
    ...
            <Response>
                <Step>
                    <Name>Raise-Fault-1</Name>
    <!-- If the condition is true, the Raise-Fault-1 policy gets executed -->
                    <Condition>(response.status.code GreaterThan "200")</Condition>
                </Step>
            </Response> 
    

    GrowFault 政策也會將錯誤訊息傳送至用戶端應用程式。

如果 LiftFault 政策觸發了錯誤,導致 Proxy 進入錯誤狀態,他可能會執行 FaultRule,該怎麼辦?以下提供一些資訊如果 RepeatFault 政策傳回錯誤訊息「並且」觸發 FaultRule 並傳回錯誤訊息,請問什麼會返回用戶端應用程式?

  • 由於 FaultRule 或 DefaultFaultRule 是在 錶 Fault 政策執行後執行,因此系統會採用 FaultRule 回應資料。
  • 如果資料並非由 FaultRule 或 DefaultFaultRule 設定,則系統會使用 MrFault 政策回應資料 (狀態碼、原因詞組或訊息酬載)。
  • 如果 LiftFault 政策和 FaultRule 都加入自訂 HTTP 標頭,則兩項都會包含在回應中。重複的標頭名稱會建立包含多個值的標題。

以下舉例說明由 LiftFault 政策和 FaultRule 設定,以及傳回至用戶端應用程式的內容。這些範例的目的在於保持精簡,而非最佳做法。

用戶端應用程式會收到:

Status Code: 468
Reason Phrase: Something happened
Payload: {"Whoa":"Sorry."}
Header: 
  errorNote: woops,gremlins

<- 錯誤規則政策負責設定

Status Code: [none] 
Reason Phrase: Something happened
Payload: {"Whoa":"Sorry."}
Header: 
  errorNote: gremlins

<- HigherFault 政策設定了上述政策

Status Code: 468
Reason Phrase: Can't do that
Payload: {"DOH!":"Try again."}
Header: 
  errorNote: woops

建築物條件

條件是執行 FaultRule 的關鍵。建立 FaultRule 條件的方式與您在 Edge 中為其他條件建立的方法相同,例如針對條件式流程或 IncreaseFault 條件建立。

為了說明此章節的其餘部分,以下提供一個包含外部 FaultRule 條件和內部步驟條件的故障規則範例。

<FaultRule name="invalid_key_rule">
    <Step>
        <Name>invalid-key-message</Name>
        <Condition>(oauthV2.Verify-API-Key-1.failed = true)</Condition>
    </Step>
    <Condition>(fault.name = "FailedToResolveAPIKey")</Condition>
</FaultRule>

政策錯誤專用的變數

政策擲回錯誤時,可使用 fault.name{policy_namespace}.{policy_name}.failed 變數。

fault.name

當政策失敗時,使用 fault.name 變數擷取條件中的錯誤。例如:

<Condition>(fault.name = "policy_error_name")</Condition>

錯誤名稱會顯示在預設錯誤訊息中。舉例來說,在下列指令中,錯誤名稱為 FailedToResolveAPIKey。在這種情況下,名為 fault.name 的流程變數會設為 FailedToResolveAPIKey 值。

{"fault":{"faultstring":"Failed to resolve API Key variable request.queryparam.apikey","detail":{"errorcode":"steps.oauth.v2.FailedToResolveAPIKey"}}}

因此,條件應如下所示:

<Condition>(fault.name = "FailedToResolveAPIKey")</Condition>

如需政策錯誤清單,請參閱政策錯誤參考資料

{policy_namespace}。{policy_name}。失敗

政策失敗時,*.failed 變數可以使用。以下是不同政策的 *.failed 變數範例。如需政策命名空間,請參閱每個政策參考資料主題中的流程變數。

  • OverFault 政策raisefault.failed (所有 IncreaseFault 政策相同)
  • 「VerifyAPIKey policy」oauthV2.{policy_name}.failed,例如 oauthV2.Verify-API-Key-1.failed
  • 配額政策SpikeArrest 政策ratelimit.{policy_name}.failed,例如 ratelimit.Quota-1.failed

其他可用的變數

當 API Proxy 進入錯誤狀態時,可在條件中使用唯一可用的變數如下:

  • 失敗的政策變數。
  • 故障時存在的 HTTP 訊息變數。舉例來說,如果回應中擲回錯誤,<TargetEndpoint> 中的 FaultRule 可以使用 HTTP 資料 response.status.codemessage.contenterror.content 等。如果配額政策失敗,您可以使用變數 ratelimit.{quota_policy_name}.exceed.count。使用追蹤記錄工具政策參考主題來找出可用的變數和 HTTP 資料。

更多資訊

處理錯誤的最佳做法

錯誤處理是 API Proxy 開發的重要架構設計工作。請務必花點時間決定如何處理錯誤、判斷應顯示哪些錯誤訊息,以及設計錯誤訊息格式。解決上述問題後,即可運用這些最佳做法協助執行故障處理。

以下是設計及建構錯誤處理機制的一些最佳做法:

  • 針對每個 FaultRule,提供「outer」<Condition> (同 <Step> 元素)。沒有外部條件的故障規則會自動評估為 true。「內部」步驟條件「不會」用來判斷 FaultRule 為 true 或 false。只有在 Edge 執行包含這些條件的 FaultRule 時,系統才會評估步驟條件。 在 FaultRule 中,通常有多個步驟指派訊息 (或其他) 政策,且每個步驟都有一個步驟條件。
  • 如要處理多項相同類型政策中的錯誤 (例如多項配額政策),請為每個可能收到的政策錯誤建立一個 FaultRule。舉例來說,您可以為配額政策中每個可能的錯誤 (例如 QuotaViolationInvalidMessageWeightStartTimeNotSupported) 建立 FaultRule。(如要瞭解政策錯誤,請參閱政策錯誤參考資料。當您發現其他需要處理的錯誤時,可以稍後再返回將錯誤新增至 FaultRules。您也可以疊代,但需要重新部署 Proxy。)如此一來,無論擲回哪種政策,您都能擷取相同類型的錯誤,進而提高 FaultRules XML 的效率。

    如果需要更精細的錯誤控制,請使用內部步驟條件。舉例來說,如果您在要求流程中同時強制執行個別開發人員配額和全域配額,並設定兩項政策,請設定「outer」 FaultRule 條件來觸發 QuotaViolation 錯誤 (在任一情況下的配額超過時系統就會擲回)。接著設定「步驟」條件,以評估兩項配額政策中的 exceed.count 變數。只有相關錯誤會傳送給用戶端 (開發人員配額超額或全域配額超額)。以下是這項設定的範例:

    <FaultRule name="over_quota">
    <!-- This condition catches a QuotaViolation in *any* Quota policy -->
      <Condition>(fault.name = "QuotaViolation")</Condition>
      <Step>
        <Name>developer-over-quota-fault</Name>
        <Condition>(ratelimit.developer-quota-policy.exceed.count GreaterThan "0")</Condition>
      </Step>
      <Step>
        <Name>global-over-quota-fault</Name>
        <Condition>(ratelimit.global-quota-policy.exceed.count GreaterThan "0")</Condition>
      </Step>
    </FaultRule>
    

    如需其他範例,請參閱這個 Apigee 社群執行緒

  • 如要在使用單一類型的政策時處理錯誤,請考慮在該項政策失敗時執行的單一錯誤規則,並加入對應至各個可能錯誤的多個步驟。這樣一來,您就能使用單一 FaultRule,而非多個 FaultRules (每種錯誤類型各一個),藉此讓您的 XML 效率達到最高效率。例如:

    <FaultRule name="raise-fault-3">
    <!-- This condition catches *any* error in the Verify-API-Key-1 policy. -->
      <Condition>(oauthV2.Verify-API-Key-1.failed = "true")</Condition>
      <!-- This first step always executes, which handles errors you haven't mapped with inner conditions. -->
      <Step>
        <Name>Generic-Key-Fault</Name>
      </Step>
      <Step>
        <Name>Assign-Message-Raise-Fault-1</Name>
        <Condition>(fault.name = "FailedToResolveAPIKey")</Condition>
      </Step>
      <Step>
        <Name>Assign-Message-Raise-Fault-2</Name>
        <Condition>(fault.name = "InvalidApiKey")</Condition>
      </Step>
    </FaultRule>
    
  • 新增會發生錯誤的 FaultRules (用戶端 <ProxyEndpoint> 或目標端 <TargetEndpoint>)。為每個位置顯示的各項政策加入 FaultRules。
  • 在 FaultRules 中,您可以執行任何類型政策,將訊息傳回用戶端應用程式。AssignMessage 政策非常適合使用。如要追蹤錯誤,也請考慮使用 MessageLogging 政策記錄訊息。
  • 將 LiftFault 政策與 FaultRules 搭配使用時,應協調系統在 MrFault 政策和 FaultRule 傳回資料時傳回的回應資料。舉例來說,如果 LiftFault 政策會重設 HTTP 狀態碼,就不要重設 FaultRule 來重設狀態碼。最糟的情況是,預設的狀態碼會傳回用戶端應用程式。
  • <DefaultFaultRule> 執行:
    • 如果您希望在未執行其他 FaultRule 時一律執行 <DefaultFaultRule>,請不要在其中加入 <Condition>
    • 如果希望 <DefaultFaultRule> 即使在執行另一個 FaultRule 時也一律執行,請新增 <AlwaysEnforce>true</AlwaysEnforce> 子項元素。

集中且可重複使用的錯誤處理模式

以下 Apigee 社群貼文說明瞭無須複製程式碼即可集中處理錯誤處理的模式:

https://community.apigee.com/articles/23724/an-error-handling-pattern-for-apigee-Proxy.html

建立 FaultRules

如要新增 FaultRule,您必須編輯 ProxyEndpoint 或 TargetEndpoint 的 XML 設定。您可以使用 Edge UI 編輯 API Proxy「Develop」檢視畫面的「Code」窗格,或是編輯定義 ProxyEndpoint 或 TargetEndpoint 的 XML 檔案。

如果您是在管理 UI 中建立 FaultRules,請先建立要執行的政策,然後將政策新增至 FaultRule 設定。(如果您嘗試儲存的 FaultRule 參照尚未建立的政策,您就會在 UI 中收到錯誤訊息)。

將政策新增至 FaultRule

雖然您可以將任何政策放在 FaultRule 中,但通常也可以使用 AssignMessage 政策針對錯誤條件產生自訂回應訊息。AssignMessage 可讓您設定含有酬載、HTTP 狀態碼、標頭和原因詞組元素的 HTTP 回應。

以下範例為一般的 AssignMessage 政策設定:

<AssignMessage name="fault_invalidkey">
  <Set>
      <Payload contentType="text/plain">Contact support at support@mycompany.com.</Payload>
      <StatusCode>401</StatusCode>
      <ReasonPhrase>Unauthorized</ReasonPhrase>
  </Set>
  <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
</AssignMessage>

您現在可以在 FaultRule 中使用這項政策。請注意,如何在 FaultRule 中依名稱參照 AssignMessage 政策:

<ProxyEndpoint name="default">
  ...
  <FaultRules>
    <FaultRule name="invalid_key_rule">
      <Step>
        <Name>fault_invalidkey</Name>
      </Step>
      <Condition>(fault.name = "InvalidApiKey")</Condition>
    </FaultRule>
  </FaultRules>
</ProxyEndpoint>

部署上述設定時,只要應用程式顯示無效的 API 金鑰,API Proxy 就會執行名為 fault_invalidkey 的 AssignMessage 政策。

您可以在 FaultRule 中執行多項政策,如以下範例所示:

<ProxyEndpoint name="default">
  ...
  <FaultRules>
    <FaultRule name="invalid_key_rule">
      <Step>
        <Name>policy1</Name>
      </Step>
      <Step>
        <Name>policy2</Name>
      </Step>
      <Step>
        <Name>policy3</Name>
      </Step>
      <Condition>(fault.name = "InvalidApiKey")</Condition>
    </FaultRule>
  </FaultRules>
</ProxyEndpoint>

政策會依照定義的順序執行。舉例來說,您可以使用 MessageLogging 政策ExtractVariables 政策AssignMessage 政策或 FaultRule 中的任何其他政策。請注意,如果發生下列任一情況,系統會立即停止 FaultRule 的處理作業:

  • FaultRule 中的任何政策都會導致錯誤
  • FaultRule 中的任何政策都是 IncreaseFault 類型的政策

定義 FaultRule 傳回的自訂錯誤訊息

最佳做法是,從 API 定義明確的錯誤回應。如此一來,您就能為客戶提供一致且實用的資訊。

下列 AssignMessage 政策範例使用 <Payload><StatusCode><ReasonPhase> 標記來定義在 InvalidApiKey 錯誤時傳回用戶端的自訂錯誤回應 (請參閱先前的 FaultRules 範例)。

<AssignMessage name="fault_invalidkey">
  <Set>
    <Payload contentType="text/plain">You have attempted to access a resource without the correct authorization. 
       Contact support at support@mycompany.com.</Payload>
    <StatusCode>401</StatusCode>
    <ReasonPhrase>Unauthorized</ReasonPhrase>
  </Set>
  <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
</AssignMessage>

回應包括:

  • 酬載包含錯誤訊息和聯絡支援團隊的電子郵件地址。
  • 回應中傳回的 HTTP 狀態碼。
  • 原因詞組,這是錯誤的簡短說明。

建立 DefaultFaultRule

DefaultFaultRule 用於任何未由其他 FaultRule 明確處理的錯誤,其行為都會視為例外狀況處理常式。如果所有 FaultRules 的條件與錯誤不符,則 DefaultFaultRule 會處理錯誤。將 <DefaultFaultRule> 標記新增為 ProxyEndpoint 或 TargetEndpoint 的子項元素,即可啟用預設錯誤處理功能。

舉例來說,以下的 TargetEndpoint 設定會定義一個會叫用名為 ReturnGenericError 的政策:

<TargetEndpoint name="default">
  ...
  <FaultRules>
    ...
  </FaultRules>

  <DefaultFaultRule name="fault-rule">
    <Step>
      <Name>ReturnGenericError</Name>
    </Step>
  </DefaultFaultRule>

  <HTTPTargetConnection>
    <URL>http://mocktarget.apigee.net</URL>
  </HTTPTargetConnection>
</TargetEndpoint>

DefaultFaultRule 通常用於針對任何非預期的錯誤傳回一般錯誤訊息,例如包含技術支援聯絡資訊的訊息。這項預設回應主要用於提供適合開發人員的資訊,同時對後端網址或其他可能遭駭系統的資訊進行模糊處理。

舉例來說,您可以定義下列 AssignMessage 政策來傳回一般錯誤:

<AssignMessage name="ReturnGenericError">
  <Set>
    <Payload type="text/plain">SERVICE UNAVAILABLE. PLEASE CONTACT SUPPORT: support@company.com.</Payload>
  </Set>
</AssignMessage>

請在 <DefaultFaultRule> 標記中加入 <AlwaysEnforce> 元素,以便為每個錯誤執行 DefaultFaultRule,即使已執行其他 FaultRule,DefaultFaultRule 一律為最後一個要執行的 FaultRule:

  <DefaultFaultRule name="fault-rule">
    <Step>
      <Name>ReturnGenericError</Name>
    </Step>
    <AlwaysEnforce>true</AlwaysEnforce>
  </DefaultFaultRule>

DefaultFaultRule 的其中一項用途是判斷在無法判斷的情況下發生的錯誤類型。例如,因您無法判斷的錯誤,API Proxy 就會失敗。使用 DefaultFaultRule 叫用下列 AssignMessage 政策。這項政策會在回應中將 fault.name 值寫入名為 DefaultFaultHeader 的標頭:

<AssignMessage async="false" continueOnError="false" enabled="true" name="DefaultFaultRule">
  <DisplayName>DefaultFaultRule</DisplayName>
  <Set>
    <Headers>
      <Header name="DefaultFaultHeader">{fault.name}</Header>
    </Headers>
  </Set>
  <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
  <AssignTo createNew="false" transport="http" type="response"/>
</AssignMessage>

接著,您可以在 Edge 追蹤工具或回應中查看標頭,瞭解導致錯誤的原因。

將訊息記錄新增至 PostClientFlow

PostClientFlow 是 Proxy 進入錯誤狀態後唯一執行的流程。只有 MessageLogging 政策可以附加至這個流程,在回應將回應傳回用戶端後執行。雖然將 MessageLogging 政策附加至這個流程實際上並非錯誤處理,但您可以將其用於記錄錯誤事件中的資訊。由於無論 Proxy 是否成功或失敗,系統都會執行訊息,因此您可以將訊息記錄政策置於 PostClientFlow,並保證這些政策一定會執行。

處理目前流程中的政策錯誤

目前顯示的示例全都使用 ProxyEndpoint 或 TargetEndpoint 的 FaultRule,來處理屬於錯誤狀態的任何政策錯誤。這是因為政策的 continueOnError 元素預設值為 false,這表示當政策發生錯誤時,系統會將控制項導向錯誤狀態。進入錯誤狀態後,您無法將控制項還原回一般管道,而通常會將某種形式的錯誤訊息傳回至呼叫應用程式。

不過,如果您將政策的 continueOnError 元素設為 true,控制項會留在目前流程中,而管道中的下一個政策會在導致錯誤的政策之後執行。處理目前流程中錯誤的好處,就是您也許可以從錯誤中復原到完成要求。

以下顯示名為 verify-api-keyVerifyAPIKey 政策,其中 continueOnError 元素已設為 true:

<VerifyAPIKey async="false" continueOnError="true" enabled="true" name="verify-api-key">
  <DisplayName>Verify API Key</DisplayName>
  <APIKey ref="request.queryparam.apikey"/>
</VerifyAPIKey>

如果 API 金鑰遺失或無效,VerifyAPIKey 政策會將 oauthV2.verify-api-key.failed 變數設為 true,但當前流程仍會持續處理。

然後在 ProxyEndpoint 的 PreFlow 中,將 VerifyAPIKey 政策新增為步驟:

<ProxyEndpoint name="default">
  ...
  <PreFlow name="PreFlow">
    <Request>
      <Step>
        <Name>verify-api-key</Name>
      </Step>
      <Step>
        <Name>FaultInFlow</Name>
        <Condition>(oauthV2.verify-api-key.failed = "true")</Condition>
      </Step>
    </Request>
    <Response/>
  </PreFlow>      
</ProxyEndpoint>  

請注意 PreFlow 的下一個步驟,如何使用條件來測試是否存在錯誤。如果 VerifAPIKey 政策發生錯誤,系統會執行名為 FaultInFlow 政策的政策。否則,系統會略過 FaultInFlow 政策。FaultInFlow 政策可執行許多動作,例如記錄錯誤、嘗試修正錯誤,或執行其他動作。

使用 LiftFault 政策觸發錯誤

您隨時可以在流程中使用 IncreaseFault 政策觸發錯誤。執行 IncreaseFault 政策時,會終止目前的流程,並將控制項轉移至錯誤狀態。

FlagFault 政策的其中一種用途是測試其他政策可能無法偵測到的特定條件。在上述範例中,您新增了 <Condition> 標記至 PreFlow <Step> 標記,此標記會在符合條件時執行政策 FaultInFlow。如果 FaultInFlow 為 IncreaseFault 政策,則控管轉移至錯誤狀態。或者,您也可以在流程中插入 IncreaseFault 政策,以便偵錯及測試 FaultRules。

當 好處 Fault 政策觸發錯誤時,您可以使用下列 FaultRule 和條件來處理:

<FaultRule name="raisefault_rule">
  <Step>
    <Name>{policy_name}</Name>
  </Step>
  <Condition>(fault.name = "RaiseFault")</Condition>
</FaultRule>

請注意,針對名為 RaiseFault 的錯誤測試條件。LiftFault 政策一律會將 fault.name 的值設為 RaiseFault

自訂目標伺服器 HTTP 錯誤代碼的處理方式

前幾節提供的範例適用於政策建立的錯誤。不過,您也可以針對傳輸層級錯誤建立自訂回應,也就是從目標伺服器傳回的 HTTP 錯誤。如要控管 HTTP 錯誤的回應,請設定 TargetEndpoint 以處理 HTTP 回應代碼。

根據預設,Edge 會將 1xx-3xx 範圍中的 HTTP 回應代碼視為「成功」,並在 4xx-5xx 範圍的 HTTP 回應代碼中視為「失敗」。也就是說,後端服務只要收到 HTTP 回應代碼 4xx-5xx 的回應就會自動叫用錯誤狀態,隨後將錯誤訊息直接傳回至要求用戶端。

您可以為任何 HTTP 回應代碼建立自訂處理常式。舉例來說,您可能不想將 4xx-5xx 這個範圍中的所有 HTTP 回應代碼都視為「失敗」,而只將 5xx 設為「失敗」,或者您可能想要針對 HTTP 回應代碼 400 和 500 傳回自訂錯誤訊息。

在下一個範例中,您會使用 success.codes 屬性設定 TargetEndpoint,將 HTTP 回應代碼 400 和 500 視為成功,以及預設的 HTTP 代碼。將這些代碼視為成功,TargetEndpoint 會負責處理回應訊息的處理作業,而不是叫用錯誤狀態:

<TargetEndpoint name="default">
  ...
  <HTTPTargetConnection>
    <Properties>
          <Property name="success.codes">1xx,2xx,3xx,400,500</Property>
    </Properties>
    <URL>http://weather.yahooapis.com</URL>
  </HTTPTargetConnection>
</TargetEndpoint>

如此範例所示,您可以使用萬用字元將 success.codes 屬性設為某個範圍的值。

設定 success.codes 屬性會覆寫預設值。因此,如要將 HTTP 代碼 400 新增至預設成功代碼清單,請將這個屬性設為:

<Property name="success.codes">1xx,2xx,3xx,400</Property>

不過,如果您只想將 HTTP 代碼 400 視為成功代碼,請將這個屬性設為:

<Property name="success.codes">400</Property>

您現在可以為 HTTP 回應代碼 400 和 500 定義自訂處理常式,以便向要求的應用程式傳回自訂回應訊息。下列 TargetEndpoint 會使用名為 ReturnError 的政策來處理 HTTP 400 和 500 回應代碼:

<TargetEndpoint name="default">
  <PreFlow name="PreFlow">
    <Request/>
    <Response>
      <Step>
        <Name>ReturnError</Name>
        <Condition>(response.status.code = 400) or (response.status.code = 500)</Condition>
      </Step>
    </Response>
  </PreFlow>

  <HTTPTargetConnection>
    <Properties>
      <Property name="success.codes">1xx,2xx,3xx,400,500</Property>
    </Properties>
    <URL>http://weather.yahooapis.com</URL>
  </HTTPTargetConnection>
</TargetEndpoint>

這個 TargetEndpoint 設定會讓名為 ReturnError 的政策在目標端點遇到 HTTP 回應代碼 400 或 500 時處理回應。

假分類

API 服務將錯誤分為下列類別和子類別。

類別 子類別 故障名稱 說明
訊息 在訊息流程期間發生的錯誤 (不含政策失敗)
自訂錯誤 {fault_name} 由 API Proxy 使用 IncreaseFault 政策明確處理的任何錯誤
回應碼 InternalServerError、NotFound HTTP 錯誤代碼 5xx、4xx
轉送失敗 沒有相符路徑 無法為要求選取已命名的 TargetEndpoint
分類失敗 找不到 要求 URI 與任何 ProxyEndpoint 設定的 BasePath 皆不相符,因而導致失敗 (也就是說,沒有 API Proxy 與用戶端應用程式要求中的網址相符)
運輸 HTTP 傳輸層級錯誤
連線能力 ConnectionRefused、ConnectionReset、ConnectionTimeout 建立網路或傳輸層級連線失敗
要求驗證 ContentLength Missing、HostHeader 缺少 針對每個要求的語意檢查期間修正錯誤
回應驗證 檢查每個回應的語意檢查期間是否發生錯誤
IO 錯誤 SSLHandshakeError、ReadTimeout、ReadError、WriteTimeout、WriteError、ChunkError 用戶端或目標端點、逾時、TLS/SSL 錯誤和區塊化錯誤的讀取/寫入錯誤
系統 未定義的執行階段錯誤
記憶體 OutOfMemory、GCOverLimit 記憶體相關失敗
討論串 RogueTaskTerminated 失敗,例如終止執行中的工作
政策 如要瞭解各種政策類型的錯誤,請參閱政策參考資料

系統一律會隨附錯誤原因的文字說明。當系統引發錯誤時,系統會填入一組屬性來協助排解問題。錯誤包含下列資訊:

  • 原因
  • 使用者定義的自訂屬性