處理錯誤

本頁內容適用於 ApigeeApigee Hybrid

查看 Apigee Edge 說明文件。

API Proxy 處理應用程式要求時,可能會發生許多錯誤狀況。舉例來說,API Proxy 與後端服務通訊時可能會遇到網路問題、應用程式可能會提供過期的憑證、要求訊息格式可能不正確等等。

用戶端應用程式呼叫 API Proxy 後發生錯誤時,系統會向用戶端傳回錯誤訊息。根據預設,用戶端會收到通常很隱晦的錯誤訊息,其中沒有詳細資料或指引。不過,如果您想以更有用的自訂訊息取代預設錯誤訊息,甚至加入額外的 HTTP 標頭等內容,就必須在 Apigee 中設定自訂錯誤處理機制。

自訂錯誤處理機制也可讓您新增功能,例如在發生錯誤時記錄訊息。

在討論如何在 API Proxy 中實作自訂錯誤處理機制之前,建議您先瞭解錯誤的發生方式,以及 API Proxy 如何處理錯誤。

影片

如要進一步瞭解錯誤處理,請觀看下列影片。

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

錯誤發生方式

首先,我們會簡單說明如何發生錯誤。瞭解錯誤的發生方式,有助於規劃要導入自訂錯誤處理的不同情況。

自動錯誤

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

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

如要進一步瞭解這些錯誤,請參閱本主題的「故障分類」。

自訂錯誤

如果沒有自動錯誤,您可能想擲回自訂錯誤;舉例來說,如果回應包含「unavailable」一詞,或 HTTP 狀態碼大於 201,方法是在 API Proxy 流程的適當位置新增 RaiseFault 政策

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

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

這只是為了向您展示如何擲回自訂錯誤。我們會在「FaultRules 與 RaiseFault 政策」一節中,詳細說明 RaiseFault 政策。

如需更多範例,請參閱下列 Apigee 社群貼文:

發生錯誤時,API Proxy 的處理方式

以下說明 Proxy 擲回錯誤時會發生什麼情況。

結束 Proxy 管道

API Proxy 發生錯誤時 (無論錯誤原因為何),都會退出正常流程管道,進入錯誤狀態,並向用戶端應用程式傳回錯誤訊息。API Proxy 進入錯誤狀態後,就無法將處理作業傳回正常流程管道。

舉例來說,假設 API Proxy 在 ProxyEndpoint 要求中依下列順序套用政策:

  1. 驗證 API 金鑰
  2. 配額
  3. 從 JSON 到 XML

如果 API 金鑰驗證期間發生錯誤,API 代理伺服器會進入錯誤狀態。系統不會執行配額和 JSON 轉 XML 政策,Proxy 不會繼續前往 TargetEndpoint,且會將錯誤訊息傳回用戶端應用程式。

檢查 FaultRule

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

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

基本上,API Proxy 可讓您傳回自訂錯誤訊息,並觸發其他邏輯。如果 Proxy 找不到這兩個區段,或這兩個區段存在但未觸發任何自訂錯誤,Proxy 會傳送 Apigee 產生的預設訊息。

簡單的錯誤處理範例

我們先來看一個簡單的範例,其中對 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 標頭 (例如狀態碼)。AssignMessage 政策非常適合這個用途。您可以藉此控制訊息酬載、設定不同的 HTTP 狀態碼,以及新增 HTTP 標頭。

您不需要將政策附加至流程,只要按照「建立政策」一文所述建立政策即可。

以下是 AssignMessage 政策範例,可執行下列操作:

  • 傳回 JSON 訊息。
  • 設定 HTTP 狀態碼 (911,這是明顯不存在的狀態碼,僅用於說明您擁有的彈性)。狀態碼會顯示在 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>
    </Set>
    <Add>
        <Headers>
            <Header name="invalidKey">Invalid API key!</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!
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> 區段中,您會新增 <FaultRules> XML 區塊,其中包含一或多個個別的 <FaultRule> 區段。每個 FaultRule 都代表您要處理的不同錯誤。在這個簡單的範例中,我們只會使用一個 FaultRule,向您說明其組成內容。

如果沒有執行任何 FaultRule,您也應新增 <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 中放置 FaultRule 的差異。
  • <Name>:要執行的政策名稱。名稱來自父項元素中的政策 name 屬性,如先前的政策範例所示。
  • <Condition>:Apigee 會評估條件,且只有在條件為 true 時才會執行政策。如果有多個 FaultRule 評估結果為 true,Apigee 會執行第一個結果為 true 的 FaultRule。(重要事項:系統評估 FaultRule 的順序 (由上而下或由下而上),在 TargetEndpoint 和 ProxyEndpoint 之間有所不同,詳情請參閱「多個 FaultRule 和執行邏輯」一節。)如未加入條件,FaultRule 會自動設為 true。但這並非最佳做法。每個 FaultRule 都應有自己的條件。

  • <DefaultFaultRule>:如果沒有執行任何自訂 FaultRule,系統就會執行 <DefaultFaultRule>,傳送較為通用的自訂訊息,而不是 Apigee 產生的預設訊息 (內容較為隱晦)。<DefaultFaultRule> 也可以有 <Condition>,但大多數情況下不會包含,因為您希望無論如何都要執行,做為最後手段。

    DefaultFaultRule 通常用於針對任何非預期的錯誤,傳回一般錯誤訊息。例如,含有技術支援聯絡資訊的訊息。這項預設回應有雙重用途,不僅提供開發人員友善的資訊,同時也會混淆後端網址或其他可能用於入侵系統的資訊。

多個 FaultRule 和執行邏輯

在「簡單的錯誤處理範例」一節中,我們使用單一 FaultRule 和條件的簡單範例。在實際的 API 專案中,由於可能發生各種錯誤,您可能會在 <ProxyEndpoint><TargetEndpoint> 中,有多個 FaultRule 和一個 DefaultFaultRule。不過,API Proxy 進入錯誤狀態時,最終只會執行一項 FaultRule。

本節說明 Apigee 處理 FaultRule 時使用的邏輯,包括如何找出要執行的單一 FaultRule,以及觸發 FaultRule 時如何處理「內部」步驟條件。本節也提供相關指引,說明何時應在 <ProxyEndpoint> 中定義 FaultRules,以及 FaultRules 與 RaiseFault 政策之間的關係。<TargetEndpoint>

執行 FaultRules

簡而言之,當 API Proxy 進入錯誤狀態時,Apigee 會使用以下邏輯。請注意,ProxyEndpoint 和 TargetEndpoint 中的 FaultRules 評估結果略有不同。

  1. Apigee 會在 ProxyEndpoint 或 TargetEndpoint 中評估 FaultRules,視錯誤發生位置而定:
    • ProxyEndpoint - Apigee 會從設定 XML 中的「底部」<FaultRule> 開始,逐步向上評估每個 <FaultRule><Step> (外部條件,而非內部 <Step> 條件)。<Condition>
    • TargetEndpoint - Apigee 會從設定 XML 中的頂端開始,然後向下評估每個 <FaultRule><Condition> (外部條件,而非內部 <Step> 條件)。<FaultRule>
  2. 執行條件為 true 的第一個 FaultRule。如果 FaultRule 沒有條件,預設為 true。
    • 執行 FaultRule 時,系統會依序評估 FaultRule 內的所有步驟,也就是 XML 設定檔中由上而下的順序。沒有條件的步驟會自動執行 (即執行政策),而評估結果為 <Condition> 的步驟也會執行 (評估結果為 code 的條件不會執行)。
    • 如果執行 FaultRule,但 FaultRule 中沒有任何步驟 (因為條件評估結果為 code),系統會將 Apigee 產生的預設錯誤訊息傳回給用戶端應用程式。<DefaultFaultRule> 不會執行,因為 Apigee 已執行其 FaultRule。

  3. 如果沒有執行任何 FaultRule,Apigee 會執行 <DefaultFaultRule> (如有)。

以下是內嵌註解的範例。

ProxyEndpoint 執行作業

ProxyEndpoint FaultRule 的評估順序是由下往上,因此請從下列範例的最後一個 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), Apigee
     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, Apigee looks at this FaultRule
     first. But let's say this FaultRule is FALSE. A policy did not
     throw a FailedToResolveAPIKey error. Apigee 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 Apigee has already
     executed its one FaultRule). -->
    <DefaultFaultRule name="default-fault">
        <Step>
            <Name>Default-message</Name>
        </Step>
    </DefaultFaultRule>

TargetEndpoint 執行作業

系統會由上而下評估 TargetEndpoint FaultRule,因此請從下列範例中的第一個 FaultRule 開始閱讀,然後依序往下。最後查看 DefaultFaultRule。

<TargetEndpoint name="default">
...
    <FaultRules>
<!-- 1. Because this is the TargetEndpoint, Apigee looks at this FaultRule
     first. Let's say this FaultRule is FALSE.
     A policy did not throw a FailedToResolveAPIKey error.
     Apigee 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), Apigee
     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 Apigee has already
     executed its one FaultRule). -->
    <DefaultFaultRule name="default-fault">
        <Step>
            <Name>Default-message</Name>
        </Step>
    </DefaultFaultRule>

故障規則順序

如上例所示,錯誤發生在 ProxyEndpoint 還是 TargetEndpoint,會影響您放置 FaultRule 的順序。

例如:

ProxyEndpoint 順序 TargetEndpoint 順序

在以下範例中,由於評估順序是由下往上,因此系統會執行 FaultRule 3,這表示系統不會評估 FaultRule 2 和 1。

5. FaultRule 1:FALSE

4. FaultRule 2:TRUE

3. FaultRule 3:TRUE

2. FaultRule 4:FALSE

1. FaultRule 5:FALSE

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

1. FaultRule 1:FALSE

2. FaultRule 2:TRUE

3. FaultRule 3:TRUE

4. FaultRule 4:FALSE

5. FaultRule 5:FALSE

要納入的政策

您可以將任何政策放入 Steps,藉此從 FaultRule 執行政策。舉例來說,您可以執行 AssignMessage 政策,格式化用戶端應用程式的回應,然後使用 MessageLogging 政策記錄訊息。系統會按照您放置政策的順序執行政策 (XML 中由上而下)。

只有在錯誤狀態下才會觸發錯誤規則 (與 continueOnError 相關)

標題可能看起來像是在重複說明,但請注意,如果 Proxy 錯誤導致 API Proxy 進入錯誤狀態 (或者說進入錯誤狀態),則政策的 continueOnError 屬性會有一項特定細微差異。

回顧一下:API Proxy <FaultRules><DefaultFaultRule> 會在 Proxy 進入錯誤狀態時評估。也就是說,即使 FaultRule 條件評估結果為 true,如果 Proxy 並未處於錯誤狀態,就不會觸發 FaultRule。

不過,以下是發生錯誤的範例,但 Proxy 並未進入錯誤狀態。在任何政策中,您都可以在名為 continueOnError 的父項元素上設定屬性。這個屬性對於錯誤處理非常重要,因為它會決定政策失敗時,Proxy 是否會進入錯誤狀態。在大多數情況下,您會想保留預設的 continueOnError="false",這樣一來,如果政策失敗,Proxy 就會進入錯誤狀態,並觸發自訂錯誤處理程序。不過,如果 continueOnError="true" (例如,您不希望服務呼叫失敗時停止 Proxy 執行),Proxy 不會進入錯誤狀態,也不會查看 FaultRules。

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

定義 FaultRule 的位置:ProxyEndpoint 或 TargetEndpoint

API Proxy 發生錯誤時,錯誤會出現在<ProxyEndpoint> (來自/傳送至用戶端應用程式的要求/回應) 或<TargetEndpoint> (傳送至/來自目標服務的要求/回應)。Apigee 會在發生錯誤的位置尋找 FaultRule。

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

以下再舉一例。如果 <ProxyEndpoint> 回應中的 RaiseFault 政策觸發錯誤,系統就不會執行 <TargetEndpoint> 中的 FaultRule。

FaultRules 與 RaiseFault 政策

從表面上看,錯誤規則和 RaiseFault 政策似乎是處理錯誤的替代方式,某種程度上來說確實如此。但兩者也會搭配運作。本節將說明兩者之間的關係。瞭解這項關係有助於設計錯誤處理機制,特別是當您想同時使用這兩者時。

簡要說明:

  • 當 API Proxy 進入錯誤狀態時,系統一律會評估錯誤規則
  • 如果沒有發生錯誤,RaiseFault 政策可讓 API Proxy 進入錯誤狀態。

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

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

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

如果 RaiseFault 政策觸發錯誤,導致 Proxy 進入錯誤狀態,並可能執行 FaultRule,會發生什麼情況?這部分稍微複雜。如果 RaiseFault 政策傳回錯誤訊息,且觸發 FaultRule 並傳回錯誤訊息,系統會將什麼內容傳回給用戶端應用程式?

  • 由於 FaultRule 或 DefaultFaultRule 會在 RaiseFault 政策執行後執行,因此 FaultRule 回應資料會優先處理。
  • 如果 FaultRule 或 DefaultFaultRule 未設定資料,系統就會使用 RaiseFault 政策回應資料 (狀態碼或訊息酬載)。
  • 如果 RaiseFault 政策和 FaultRule 都會新增自訂 HTTP 標頭,則回應中會同時包含這兩者。重複的標頭名稱會建立含有多個值的標頭。

以下範例說明 RaiseFault 政策和 FaultRule 設定的內容,以及傳回用戶端應用程式的內容。這些範例旨在簡潔,而非最佳做法。

由 RaiseFault 政策和 FaultRule 設定的內容。

用戶端應用程式會收到

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

<- Fault rules policy sets this

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

<- RaiseFault 政策會設定此項目

Status Code: 468
Payload: {"DOH!":"Try again."}
Header:
  errorNote: woops

建立條件

條件是執行 FaultRule 的關鍵。建立 FaultRule 條件的方式,與在 Apigee 中建立其他條件 (例如條件式流程或 RaiseFault 條件) 的方式相同。

為說明本節的其餘內容,以下提供範例錯誤規則,其中包含外部 FaultRule 條件和內部 Step 條件。

<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 變數。以下是不同政策的 *.failed 變數範例。如需政策命名空間,請參閱各政策參考資料主題中的流程變數。

其他可用變數

API Proxy 進入錯誤狀態時,條件中唯一可用的變數是:

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

更多資訊

錯誤處理最佳做法

錯誤處理是 API Proxy 開發作業的主要架構設計工作。請務必花時間瞭解如何及何時處理錯誤、決定錯誤訊息的內容,以及設計錯誤訊息格式。找出這些事項後 (或同時),請運用下列最佳做法,協助您實作錯誤處理機制。

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

  • 在 FaultRules 中,您可以指定任何類型的政策。最常見的模式是使用 AssignMessage 政策,在待處理的錯誤回應中設定特定項目。您也可以使用 AssignMessage 設定用於其他用途的變數,例如在 PostClientFlow 或 FlowHooks 中執行的記錄政策所參照的變數。此外,如果想在特定錯誤情況下記錄特定錯誤,請考慮記錄訊息,例如使用 MessageLogging 政策ServiceCallout 政策
  • 請勿在 FaultRule 中將 RaiseFault 政策指定為步驟。建議使用 AssignMessage 政策設定或變更訊息元素,包括酬載、標頭或狀態碼。
  • 針對每個 FaultRule,或除了最後評估的 FaultRule 以外的所有 FaultRule,請提供做為 <FaultRule> 元素子項目的 outer <Condition>。如果 FaultRule 沒有明確指定 Condition,執行條件會隱含評估為 true。附加為 <Step> 元素子項的 <Condition> 元素,不會用來判斷 FaultRule 的執行條件是否評估為 truefalse。只有在 Apigee 執行含有步驟條件的 FaultRule 後,才會評估步驟條件。 在 FaultRule 中,通常會有包含 AssignMessage (或其他) 政策的多個步驟,每個步驟都有步驟條件。
  • 如要處理相同類型多項政策中的錯誤 (例如多項配額政策),請為您可能收到的每項政策錯誤建立一個 FaultRule,然後使用附加至步驟的條件區分個別錯誤。舉例來說,您可以建立 FaultRule 來處理配額政策中的錯誤 (例如 QuotaViolation),並為 InvalidApiKey 建立個別的 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>AM-developer-over-quota-fault</Name>
        <Condition>ratelimit.developer-quota-policy.exceed.count GreaterThan 0</Condition>
      </Step>
      <Step>
        <Name>AM-global-over-quota-fault</Name>
        <Condition>ratelimit.global-quota-policy.exceed.count GreaterThan 0</Condition>
      </Step>
    </FaultRule>

    如需其他範例,請參閱這項有關政策錯誤處理的討論

  • 如要處理使用單一類型政策時發生的錯誤,請考慮使用單一錯誤規則,在該政策失敗時執行,並納入對應每個可能錯誤的多個步驟。這樣一來,您只要使用單一 FaultRule,不必為每種錯誤類型各別使用 FaultRule,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>AM-Generic-Key-Fault</Name>
      </Step>
      <Step>
        <Name>AM-API-Key-NotFound</Name>
        <Condition>fault.name = "FailedToResolveAPIKey"</Condition>
      </Step>
      <Step>
        <Name>AM-API-Key-Invalid</Name>
        <Condition>fault.name = "InvalidApiKey"</Condition>
      </Step>
    </FaultRule>
  • 在會發生錯誤的位置新增 FaultRules (用戶端 <ProxyEndpoint> 或目標端 <TargetEndpoint>)。針對每個位置顯示的每項政策,加入 FaultRules。
  • 搭配使用 RaiseFault 政策和 FaultRules 時,請協調在 RaiseFault 政策和 FaultRule 都傳回資料時傳送的回應資料。舉例來說,如果您有設定 HTTP 狀態碼的 RaiseFault 政策,請勿在 FaultRule 中設定 AssignMessage 步驟,以免重設狀態碼。最糟的情況是,系統會將預設狀態碼傳回給用戶端應用程式。
  • <DefaultFaultRule> 元素可輔助 <FaultRules> 元素,讓您進一步控管 Proxy 在處理錯誤狀態時執行的政策。如果您指定 <DefaultFaultRule>,則在下列任一或兩個條件成立時,系統就會執行該動作:

    • 沒有其他 FaultRule 已執行。如果完全沒有設定 <FaultRules> 元素,則屬於特殊情況。
    • 如果 <DefaultFaultRule><AlwaysEnforce> 子項元素為 true。

    您也可以在 <DefaultFaultRule> 上指定 <Condition> 元素。 舉例來說,如果要求中存在或缺少特定標頭,您可能會想這麼做,以便根據要求或待處理錯誤訊息的某些狀態排除執行作業。

    如果有一或多項政策需要 Proxy 一律執行,無論先前的 FaultRule 是否已執行,請使用 <DefaultFaultRule> 並將 <AlwaysEnforce> 設為 true。其中一個可能的情境:假設您想在所有情況下將標頭插入回應中,無論 Proxy 要求是否導致錯誤,以及錯誤是否已事先處理。然後,您會在 <PostFlow>/<Response> 區段中附加適當的 AssignMessage 政策,並在 <DefaultFaultRule> 中附加相同政策,且 <AlwaysEnforce> 設為 true

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

Apigee Proxy 的錯誤處理模式說明集中式錯誤處理模式,不必重複編寫程式碼。

建立 FaultRule

如要新增 FaultRule,您必須編輯 ProxyEndpoint 或 TargetEndpoint 的 XML 設定。您可以在 API Proxy 的「開發」檢視畫面中,使用 Apigee UI 在「程式碼」窗格中進行這項編輯作業,也可以編輯定義 ProxyEndpoint 或 TargetEndpoint 的 XML 檔案。

如果您在 Apigee UI 中建立 FaultRules,請先建立要執行的政策,然後將這些政策新增至 FaultRule 設定。(如果您嘗試儲存參照尚未建立政策的 FaultRule,使用者介面就會顯示錯誤訊息)。

將政策新增至 FaultRule

雖然您可以在 FaultRule 中加入任何政策,但通常會使用 AssignMessage 政策,為錯誤情況產生自訂回應訊息。您可以使用 AssignMessage 設定 HTTP 回應的酬載、HTTP 狀態碼和標頭。

以下範例顯示典型的 AssignMessage 政策設定:

<AssignMessage name="AM-Invalid-Key">
  <Set>
      <Payload contentType="text/plain">That is an error.</Payload>
      <StatusCode>401</StatusCode>
  </Set>
  <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
</AssignMessage>

請注意,這個範例並未指定 <AssignTo> 元素。也就是說,系統會根據政策的附加位置,將政策指派給周遭環境訊息。

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

<ProxyEndpoint name="default">
  ...
  <FaultRules>
    <FaultRule name="invalid_key_rule">
      <Step>
        <Name>AM-Invalid-Key</Name>
      </Step>
      <Condition>fault.name = "InvalidApiKey"</Condition>
    </FaultRule>
  </FaultRules>
</ProxyEndpoint>

部署上述設定後,每當應用程式提供無效的 API 金鑰,API Proxy 就會執行名為 AM-Invalid-Key 的 AssignMessage 政策。

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

<ProxyEndpoint name="default">
  ...
  <FaultRules>
    <FaultRule name="invalid_key_rule">
      <Step>
        <Name>AM-Invalid-Key</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 中的任何政策屬於 RaiseFault 類型

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

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

下列指派訊息政策範例使用 <Payload><StatusCode> 標記,定義在發生 InvalidApiKey 錯誤時傳回給用戶端的自訂錯誤回應 (請參閱先前的 FaultRules 範例)。

<AssignMessage name="AM-Invalid-Key">
  <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>
  </Set>
  <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
</AssignMessage>

這項回應包括:

  • 包含錯誤訊息和支援團隊聯絡電子郵件地址的酬載。
  • 回應中傳回的 HTTP 狀態碼。

建立 DefaultFaultRule

如果其他 FaultRule 未明確處理任何錯誤,DefaultFaultRule 就會做為例外狀況處理常式。如果所有 FaultRule 的條件都不符合錯誤,則 DefaultFaultRule 會處理錯誤。如要啟用預設錯誤處理機制,請將 <DefaultFaultRule> 標記新增為 ProxyEndpoint 或 TargetEndpoint 的子項元素。

舉例來說,下列 TargetEndpoint 設定定義了 DefaultFaultRule,會叫用名為 AM-Return-Generic-Error 的政策:

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

  <DefaultFaultRule name="fault-rule">
    <Step>
      <Name>AM-Return-Generic-Error</Name>
    </Step>
  </DefaultFaultRule>

  <HTTPTargetConnection>
    <URL>https://mytarget.example.net</URL>
  </HTTPTargetConnection>
</TargetEndpoint>

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

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

<AssignMessage name="AM-Return-Generic-Error">
  <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>AM-Return-Generic-Error</Name>
    </Step>
    <AlwaysEnforce>true</AlwaysEnforce>
  </DefaultFaultRule>

DefaultFaultRule 的用途之一,是判斷您無法判斷的錯誤類型。舉例來說,如果 API Proxy 發生錯誤,但您無法判斷原因,可以使用 DefaultFaultRule 叫用下列 AssignMessage 政策。這項政策會將 fault.name 值寫入回應中名為 Unhandled-Fault 的標頭:

<AssignMessage name="AM-Set-Fault-Header">
  <Set>
    <Headers>
      <Header name="Unhandled-Fault">{fault.name}</Header>
    </Headers>
  </Set>
  <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
</AssignMessage>

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

在 PostClientFlow 中新增訊息記錄

Proxy 進入錯誤狀態後,只會執行 PostClientFlow。只有 MessageLogging 政策可以附加至這個流程,且會在回應傳回用戶端後執行。雖然將 MessageLogging 政策附加至這個流程,在技術上並非錯誤處理,但您可以使用這項政策記錄發生錯誤時的資訊。因為無論 Proxy 是否成功,都會執行這項作業,所以您可以將訊息記錄政策放在 PostClientFlow 中,保證政策一律會執行。

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

到目前為止,所有範例都使用 ProxyEndpoint 或 TargetEndpoint 上的 FaultRule,在錯誤狀態中處理任何政策錯誤。這是因為政策的 continueOnError 元素預設值為 false,也就是說,政策發生錯誤時,控制項會導向錯誤狀態。進入錯誤狀態後,您無法將控制權還原至正常管道,通常會將某種形式的錯誤訊息傳回給呼叫應用程式。

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

下方顯示名為 verify-api-keyVerifyAPIKey 政策,且 continueOnError 元素設為 true:

<VerifyAPIKey continueOnError="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 的下一個步驟會使用條件來測試是否存在錯誤。如果 VerifyAPIKey 政策發生錯誤,系統會執行名為 FaultInFlow 的政策。否則系統會略過 FaultInFlow 政策。FaultInFlow 政策可以執行許多動作,例如記錄錯誤、嘗試修正錯誤或執行其他動作。

使用 RaiseFault 政策觸發錯誤

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

使用 RaiseFault 政策的其中一個目的是測試特定條件,因為其他政策可能無法偵測到該條件。在上述範例中,您將 <Condition> 標記新增至 PreFlow <Step> 標記,導致政策 FaultInFlow 在符合條件時執行。如果 FaultInFlow 是 RaiseFault 政策,控制項會轉移至錯誤狀態。或者,您也可以在流程中插入 RaiseFault 政策,以便偵錯及測試 FaultRules。

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

<FaultRule name="raisefault_rule">
  <Step>
    <Name>POLICY-NAME-HERE</Name>
  </Step>
  <Condition>fault.name = "RaiseFault"</Condition>
</FaultRule>

請注意,條件會測試名為 RaiseFault 的故障。RaiseFault 政策一律會將 fault.name 的值設為 RaiseFault。您也可以在 RaiseFault 政策中設定自訂變數。這樣一來,您就能在「條件」元素中測試這些變數。

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

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

根據預設,Apigee 會將 1xx-3xx 範圍內的 HTTP 回應代碼視為成功,並將 4xx-5xx 範圍內的 HTTP 回應代碼視為失敗。也就是說,如果後端服務傳送的任何回應含有 HTTP 回應碼 4xx-5xx,系統就會自動叫用錯誤狀態,然後直接將錯誤訊息傳回給提出要求的用戶端。

您可以為任何 HTTP 回應代碼建立自訂處理常式。舉例來說,您可能不想將 4xx-5xx 範圍內的所有 HTTP 回應碼視為「失敗」,而只將 5xx 視為失敗,或是想為 HTTP 回應碼 400500 傳回自訂錯誤訊息。

在下一個範例中,您會使用 success.codes 屬性設定 TargetEndpoint,將 HTTP 回應代碼 400500 視為成功,以及預設的 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 回應代碼 400500 定義自訂處理常式,向提出要求的應用程式傳回自訂回應訊息。下列 TargetEndpoint 使用名為 ReturnError 的政策,處理 HTTP 400500 回應代碼:

<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 遇到 400500 的 HTTP 回應代碼,這個 TargetEndpoint 設定會導致名為 ReturnError 的政策處理回應。

故障分類

API 服務會將錯誤歸入下列類別和子類別。

類別 子類別 錯誤名稱 說明
訊息 訊息流程期間發生的失敗 (不包括政策失敗)
自訂錯誤 {fault_name} API Proxy 使用 RaiseFault 政策明確處理的任何錯誤
回應碼 InternalServerError、NotFound HTTP 錯誤碼 5xx4xx
轉送失敗 NoRoutesMatched 無法為要求選取具名的 TargetEndpoint
分類失敗 NotFound 要求 URI 與任何 ProxyEndpoint 的 BasePath 設定都不相符 (也就是沒有任何 API Proxy 與用戶端應用程式要求中的網址相符) 而導致失敗
Transport HTTP 傳輸層級錯誤
連線能力 ConnectionRefused、ConnectionReset、ConnectionTimeout 建立網路或傳輸層級連線時發生失敗
要求驗證 ContentLengthMissing, HostHeaderMissing 每次要求時的語意檢查都會發生錯誤
回應驗證 對每個回覆進行語意檢查時發生錯誤
IO 錯誤 SSLHandshakeError、ReadTimeout、ReadError、WriteTimeout、WriteError、ChunkError 用戶端或目標端點的讀取/寫入錯誤、逾時、TLS/SSL 錯誤和分塊錯誤
系統 未定義的執行階段錯誤
記憶體 OutOfMemory、GCOverLimit 記憶體相關失敗
討論串 RogueTaskTerminated 失敗,例如終止失控的工作
政策 如要瞭解各政策類型的錯誤,請參閱政策參考資料

錯誤訊息一律會附上失敗原因的文字說明。系統發生故障時,會填入一組屬性,協助排解問題。故障包含下列資訊:

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