ExternalCallout policy

本頁適用於 ApigeeApigee Hybrid

查看 Apigee Edge 說明文件。

政策圖示

結果

您可以使用 ExternalCallout 政策,將 gRPC 要求傳送至 gRPC 伺服器,藉此實作 Apigee 政策不支援的自訂行為。在伺服器程式碼中,您可以輕鬆存取及修改 Proxy 流程中的流程變數。

Apigee 會透過 API 的 ExternalCallout 政策與 gRPC 伺服器通訊。 Apigee 會使用 API 將流程變數傳送至 gRPC 伺服器。您可以在 gRPC 伺服器中讀取「流程變數」參考頁面中列出的流程變數,並視需要變更這些變數,以及您在政策 XML 中指定的其他變數。

如果您使用 Apigee 設定 gRPC 伺服器,並在 Proxy 中加入這項政策,Apigee 會依下列方式處理 API 要求:

  1. Apigee 會將包含流程變數的訊息傳送至 gRPC 伺服器。
  2. gRPC 伺服器程式碼會執行、存取及修改程式碼中定義的變數。然後 gRPC 伺服器會傳送包含所有流程變數的回應,傳回至 Apigee。
  3. Apigee 會讀取 gRPC 伺服器的回應。如果新增任何變數或修改可變更的流程變數,這些變數會在 Apigee 中更新。

這項政策是標準政策,可部署至任何環境類型。如要瞭解政策類型和各環境類型的可用性,請參閱「政策類型」。

如要進一步瞭解如何傳送 gRPC 要求,請參閱下列連結:

<ExternalCallout>

定義 ExternalCallout 政策。

<ExternalCallout async="true" continueOnError="true" enabled="true" name="EC">

這個元素包含下列所有政策都適用的屬性:

屬性 預設 是否必要? 說明
name 不適用 必要

政策的內部名稱。name 屬性的值可以包含英文字母、數字、空格、連字號、底線和句號。這個值不得超過 255 個半形字元。

您可以選擇使用 <DisplayName> 元素,在管理 UI 代理程式編輯器中為政策加上不同、自然語言的名稱。

continueOnError false 選用 將其設為 false,即可在政策失敗時傳回錯誤。這是大多數政策的預期行為。將其設為 true,即使政策失敗,流程執行作業仍會繼續進行。另請參閱:
enabled 選用 設為 true 即可強制執行政策。設為 false 即可關閉政策。即使政策仍附加至流程,系統也不會強制執行這項政策。
async   false 已淘汰 此屬性已淘汰。

下表說明 <ExternalCallout> 的子元素。

子元素 必填 說明
<TimeoutMs> 必填 gRPC 要求的逾時時間 (以毫秒為單位)。
<GrpcConnection> 必填 指定要將現有 TargetServer 的名稱設為 gRPC 伺服器,以便傳送要求。
<Configurations> 選用 可讓您設定 ExternalCallout 政策的各個層面,包括 <Property><FlowVariable> 元素。

範例 1

您可以在 GitHub 的 External Callout 範例中找到 ExternalCallout 的工作範例。

以下範例說明 ExternalCallout 政策設定。

<ExternalCallout enabled="true" continueOnError="false" name="ExternalCallout-1">
  <DisplayName>External Callout 1</DisplayName>
  <TimeoutMs>5000</TimeoutMs>
  <GrpcConnection>
    <Server name="external-target-server"/>
  </GrpcConnection>
  <Configurations>
    <Property name="with.request.content">true</Property>
    <Property name="with.request.headers">false</Property>
    <Property name="with.response.content">true</Property>
    <Property name="with.response.headers">false</Property>
    <FlowVariable>example1.flow.variable</FlowVariable>
    <FlowVariable>example2.flow.variable</FlowVariable>
  </Configurations>
<ExternalCallout>

這個範例會向外部 gRPC 伺服器傳送要求,該伺服器由名為 external-target-server TargetServer 代表,並採用以下設定:

  • <Property>:在傳送至 gRPC 伺服器的要求中,加入要求和回應內容,但不加入要求和回應標頭。
  • <FlowVariable>:在傳送至 gRPC 伺服器的要求中,加入由 FlowVariable 元素指定的其他流程變數 example1.flow.variableexample2.flow.variable

範例 2

在以下範例中,Audience 元素的 useTargetUrl 屬性設為 true。如果 useTargetUrltrue,系統會將 gRPC 目標伺服器的主機名稱用作目標對象。舉例來說,如果伺服器的主機是 my-grpc-server-java.a.run.app,則使用的目標對象會是 https://my-grpc-server-java.a.run.app

<ExternalCallout continueOnError="false" enabled="true" name="External-Callout-1">
  <DisplayName>External-Callout-1</DisplayName>
  <GrpcConnection>
    <Server name="cloud_run_server_name"/>
    <Authentication>
      <GoogleIDToken>
        <Audience useTargetUrl="true"/>
      </GoogleIDToken>
    </Authentication>
  </GrpcConnection>
  <TimeoutMs>5000</TimeoutMs>
  <Configurations>
    <Property name="with.request.content">true</Property>
    <Property name="with.request.headers">true</Property>
    <Property name="with.response.content">true</Property>
    <Property name="with.response.headers">true</Property>
    <FlowVariable>example.flow.variable</FlowVariable>
    <FlowVariable>another.flow.variable</FlowVariable>
  </Configurations>
</ExternalCallout>

子元素參照

以下各節將說明 ExternalCallout 的子元素。

<TimeoutMs>

gRPC 要求的逾時時間 (以毫秒為單位)。<TimeoutMs> 必須是正數。

<GrpcConnection>

<GrpcConnection> 元素會將 gRPC 伺服器設為 TargetServer,由 name 屬性指定。請參閱 TargetServer 資源參考資料頁面。

注意:TargetServer 通訊協定必須為 GRPC

例如,下列程式碼

<GrpcConnection>
  <Server name="external-target-server"/>
</GrpcConnection>

指定 gRPC 伺服器為名為 external-target-server 的現有 TargetServer

使用 <Authentication> 元素 (請參閱本節後續說明) 產生 Google 核發的 OpenID Connect 權杖,以便對以 gRPC 為基礎的服務 (例如在 Cloud Run 中代管的自訂服務) 發出經過驗證的呼叫。

下表說明 <GrpcConnection> 的子元素。

子元素 是否必要 說明
<Server> 元素 必要 指定 gRPC 伺服器。
<Authentication> 元素 選用 產生 Google 核發的 OpenID Connect 權杖,以便對 Cloud Run 等以 gRPC 為基礎的服務發出已驗證的呼叫。

<Server> 元素

指定 gRPC 伺服器。

下表說明 <Server> 元素的屬性。

屬性 說明 預設 存在必要性 類型
name

現有 TargetServer 的名稱,用於將要求傳送至 gRPC 伺服器。

不適用 必填 字串

<Authentication> 元素

產生 Google 核發的 OpenID Connect 權杖,以便對以 gRPC 為基礎的服務 (例如在 Cloud Run 中代管的自訂服務) 進行驗證呼叫。如要使用這個元素,您必須按照「使用 Google 驗證」一文所述的步驟進行設定和部署作業。在適當設定下,政策會為您建立驗證權杖,並將其新增至服務要求。

這個元素有一個必要的子元素:GoogleIDToken

預設 不適用
是否必要? 選填。
類型 複雜類型
上層元素 <GrpcConnection>
子元素 <GoogleIDToken>

Authentication 元素使用以下語法:

語法

<ExternalCallout>
...
  <GrpcConnection>
    <Server name="cloud_run_server_name"/>
    <Authentication>
      <HeaderName ref="FLOW_VARIABLE">STRING</HeaderName>
      <GoogleIDToken>
         <Audience ref="variable-1">STRING</Audience>
         <IncludeEmail ref="variable-2">BOOLEAN</IncludeEmail>
      </GoogleIDToken>
    </Authentication>
  </GrpcConnection>
</ExternalCallout>

範例

以下範例顯示 GoogleIDToken 元素:

<ExternalCallout continueOnError="false" enabled="true" name="External-Callout-1">
  <DisplayName>External-Callout-1</DisplayName>
  <GrpcConnection>
     <Server name="cloud_run_server_name"/>
     <Authentication>
        <HeaderName ref='my-variable'>X-Serverless-Authorization</HeaderName>
        <GoogleIDToken>
           <Audience>https://cloudrun-hostname.a.run.app</Audience>
        </GoogleIDToken>
     </Authentication>
  </GrpcConnection>
  <TimeoutMs>5000</TimeoutMs>
  <Configurations>
    <Property name="with.request.content">true</Property>
    <Property name="with.request.headers">true</Property>
    <Property name="with.response.content">true</Property>
    <Property name="with.response.headers">true</Property>
    <FlowVariable>example.flow.variable</FlowVariable>
    <FlowVariable>another.flow.variable</FlowVariable>
  </Configurations>
</ExternalCallout>
屬性

無。

<HeaderName> 子元素

根據預設,如果有驗證設定,Apigee 會產生權杖,並將其插入傳送至目標系統的訊息中 Authorization 標頭。您可以使用 HeaderName 元素指定不同的標頭名稱,用於儲存權杖權杖。當目標是使用 X-Serverless-Authorization 標頭的 Cloud Run 服務時,這項功能就格外實用。如果有 Authorization 標頭,則會保留不變,並一併傳送至要求中。

預設 不適用
是否必要?
類型 字串
上層元素 <Authentication>
子元素

HeaderName 元素使用以下語法:

語法

<ExternalCallout>
...
  <Authentication>
    <HeaderName ref="FLOW_VARIABLE">STRING</HeaderName>
    <GoogleIDToken>
    ... 
    </GoogleIDToken>
  </Authentication>
  ...
</ExternalCallout>

使用靜態字串

在這個範例中,系統預設會將產生的權杖權杖新增至傳送至目標系統的 X-Serverless-Authorization 標頭。如果有 Authorization 標頭,則會保留不變,並一併傳送至要求中。

<Authentication>
  <HeaderName>X-Serverless-Authorization</HeaderName>
  <GoogleIDToken>
    <Audience>https://cloudrun-hostname.a.run.app</Audience>
  </GoogleIDToken>
</Authentication>

含有變數參照

在這個範例中,系統預設會將產生的權杖權杖新增至傳送至目標系統的 X-Serverless-Authorization 標頭。如果 my-variable 有值,系統會使用該值,而非預設字串。如果有 Authorization 標頭,則會保留不變,並一併傳送至要求中。

<Authentication>
  <HeaderName ref='my-variable'>X-Serverless-Authorization</HeaderName>
  <GoogleIDToken>
    <Audience>https://cloudrun-hostname.a.run.app</Audience>
  </GoogleIDToken>
</Authentication>
<GoogleIDToken> 子元素

產生 Google 核發的 OpenID Connect 權杖,以便對 Google 服務 (例如在 Cloud Run 中代管的自訂服務) 發出經過驗證的呼叫。

預設 不適用
是否必要? 必填
類型 字串
上層元素 <Authentication>
子元素 <Audience>
<IncludeEmail>

GoogleIDToken 元素使用以下語法:

語法

<ExternalCallout>
...
  <GrpcConnection>
    <Server name="cloud_run_server_name"/>
    <Authentication>
      <GoogleIDToken>
        <Audience ref="context-variable" useTargetUrl='BOOLEAN'>STRING</Audience>
        <IncludeEmail ref="context-variable">BOOLEAN</IncludeEmail>
      </GoogleIDToken>
    </Authentication>
  </GrpcConnection>
</ExternalCallout>

範例

以下範例顯示 GoogleIDToken 元素:

<Authentication>
  <GoogleIDToken>
      <Audience>https://httpserver0-bar.run.app</Audience>
      <IncludeEmail>true</IncludeEmail>
  </GoogleIDToken>
</Authentication>
<Audience> 子元素

產生驗證權杖的對象,例如權杖授予存取權的 API 或帳戶。

如果 Audience 的值為空白、ref 為空白或解析為空白值,且 useTargetUrltrue,則系統會使用「https://」+ (gRPC 目標伺服器的主機名稱) 做為目標對象。舉例來說,如果伺服器的主機是 my-grpc-server-java.a.run.app,則使用的目標對象會是 https://my-grpc-server-java.a.run.app

根據預設,useTargetUrlfalse

<Audience>explicit-audience-value-here</Audience>

or:

<Audience ref='variable-name-here'/>

or:

<Audience ref='variable-name-here' useTargetUrl='true'/>

or:

<Audience useTargetUrl='true'/>
預設 不適用
是否必要? 必填
類型 字串
上層元素 <GoogleIDToken>
子元素
<IncludeEmail> 子元素

如果將其設為 true,則產生的驗證權杖將包含服務帳戶 emailemail_verified 宣告。

預設 false
是否必要? 選用
類型 布林值
上層元素 <GoogleIDToken>
子元素

<Configurations>

<Configurations> 元素可讓您設定 ExternalCallout 政策的各個層面,包括 <Property><FlowVariable>

下表說明 <Configurations> 的子元素。

子元素 是否必要 說明
<Property> 必要

指定是否要將要求/回應標頭和/或內容傳送至伺服器。可能的值為 truefalse。預設值為 false

<FlowVariable> 必要

指定應將哪些額外的流程變數傳送至伺服器。

<Property>

<Property> 元素會指定是否要將要求/回應標頭和/或內容傳送至伺服器。可能的值為 true (會傳送商品) 或 false (不會傳送商品)。預設值為 false

下表說明 <Property> 元素的屬性。

屬性 說明 預設 存在必要性 類型
name

指定要傳送至伺服器的內容。name 的可能值如下:

  • with.request.content
  • with.request.headers
  • with.response.content
  • with.response.headers
不適用 必填 字串

<FlowVariable>

<FlowVariable> 元素會指定要傳送至伺服器的其他流程變數。<FlowVariable> 的值是變數的前置字串,而非完整的變數名稱。舉例來說,如果 元素為 a.b.c,系統會將名為 a.b.c 的變數值傳送至伺服器。同樣地,名為 a.b.c.my-variable 的變數值也會傳送至伺服器。但名稱為 a.x.another-variable 的變數值不會傳送,因為它沒有前置字串 a.b.c。以下列舉幾個例子

<Configurations>
  <FlowVariable>a.b.c</FlowVariable>
  <FlowVariable>d.e.f</FlowVariable>
</Configurations>

錯誤參考資料

部署錯誤

錯誤名稱 原因
FAILED_PRECONDITION 如果 Proxy 使用 <Authentication> 標記進行設定時缺少服務帳戶,就會發生這個錯誤。

例如:

Deployment of \"organizations/foo/apis/apiproxy/revisions/1\"
requires a service account identity, but one was not provided
with the request.
PERMISSION_DENIED 如果 Proxy 是使用 <Authentication> 標記設定,而服務帳戶有權限問題,就會發生這個錯誤。可能的原因:
  • 服務帳戶不存在。
  • 服務帳戶並未在與 Apigee 機構相同的 Google Cloud 專案中建立。
  • 部署者確實具備服務帳戶的 iam.serviceAccounts.actAs 權限。詳情請參閱「關於服務帳戶權限」。

執行階段錯誤

下表說明執行政策時可能發生的執行階段錯誤。

錯誤代碼 HTTP 狀態 原因
GrpcTlsInitFailed 500

如果使用 gRPC 伺服器初始化 TLS 時發生任何問題 (例如 Keystore 或 truststore 問題),就會發生這個錯誤。

steps.externalcallout.[error_code] 500

[error_code] 是由錯誤訊息的 errorCode 欄位決定。錯誤的錯誤字串會是錯誤訊息的 faultstring 欄位。

steps.externalcallout.ExecutionError 500

如果在執行這項政策期間發生任何其他例外狀況,就會發生這個錯誤。基礎例外狀況會顯示在錯誤字串中。如果 gRPC 伺服器的憑證有問題,錯誤訊息會類似以下內容:

{
  "fault": {
    "faultstring": "Encountered the following exception while sending the gRPC request or
     processing the response: [io.grpc.StatusRuntimeException: UNAVAILABLE: Credentials failed
     to obtain metadata].",
    "detail": {
      "errorcode": "steps.externalcallout.ExecutionError"
    }
  }
}

您可以查看 MP 的記錄,進一步瞭解偵錯提示。

googletoken.EmptyIDTokenAudience 500

<GoogleIDToken> 已啟用,但 useTargetUrl 設為 false,且在發生錯誤時,沒有直接或透過參照的方式向 <Audience> 提供任何值。

steps.externalcallout.ExecutionError

錯誤字串:

Encountered the following exception while sending the gRPC request or processing the response: [io.grpc.StatusRuntimeException: UNAVAILABLE: Credentials failed to obtain metadata]

500

如果 API Proxy 是使用 <Authentication> 元素設定,就會發生這個錯誤。可能的原因:

  • 透過 Proxy 部署的服務帳戶:
    • 不存在於專案中 (在部署時存在,但在部署後遭到刪除)
    • 已停用
    • (僅限 Apigee hybrid) 未在 apigee-runtime 服務帳戶上授予 roles/iam.serviceAccountTokenCreator 角色。
  • (僅限 Apigee hybrid) apigee-runtime 服務帳戶的來源專案已停用 IAMCredentials API。

    注意:僅限 Apigee hybrid,請檢查執行階段容器的記錄,並搜尋 externalcallout.ExecutionError,找出更詳細的錯誤訊息,以便進行偵錯。

steps.externalcallout.ExecutionError,faultstring 包含 PERMISSION DENIED

舉例來說,Cloud Run 的錯誤字串會如下所示:

Encountered the following exception while sending the gRPC request or processing the response: [io.grpc.StatusRuntimeException: PERMISSION_DENIED: HTTP status code 403 …]

500

如果 API Proxy 是使用 <Authentication> 元素設定,就會發生這個錯誤。可能的原因:

  • 代理服務帳戶已啟用且存在,但沒有存取服務的正確權限。
  • 服務需要驗證,但要求中沒有驗證標頭 (例如:政策 XML 中未包含驗證 XML)。

其他錯誤

下表說明各種錯誤。請參閱原因瞭解詳情。

錯誤代碼 原因
ReferencesExistToGrpcServer

如果使用者嘗試刪除 gRPC 目標伺服器,但該伺服器仍在使用其他政策,就會發生這個錯誤。

錯誤

下表中的錯誤變數預設為所有政策設定。請參閱 政策錯誤專屬變數

變數 地點 範例
fault.name="fault_name" fault_name 是錯誤名稱,如上表的「執行階段錯誤」所列。錯誤名稱是錯誤代碼的最後一個部分。 fault.name 與「ExecutionError」相符。
externalcallout.[policy_name].failed policy_name 是使用者指定的政策名稱,該政策會擲回錯誤。 externalcallout.ExternalCallout-1.failed = true

相關主題