本頁內容適用於 Apigee 和 Apigee Hybrid。
查看
Apigee Edge 說明文件。
ExternalCallout 政策可讓您將 gRPC 要求傳送至 gRPC 伺服器,藉此實作 Apigee 政策不支援的自訂行為。在伺服器的程式碼中,您可以輕鬆存取及修改 Proxy 流程中的流程變數。
Apigee 會透過 API,使用 ExternalCallout 政策與 gRPC 伺服器通訊。 Apigee 會使用 API 將流程變數傳送至 gRPC 伺服器。 在 gRPC 伺服器中,您可以讀取 (並視變數而定,修改)「流程變數」參考頁面中列出的流程變數,以及您在政策 XML 中指定的其他變數。
如果您使用 Apigee 設定 gRPC 伺服器,並在 Proxy 中加入這項政策,Apigee 會按照下列方式處理 API 要求:
- Apigee 會將含有流程變數的訊息傳送至 gRPC 伺服器。
- gRPC 伺服器程式碼會執行,並存取及修改程式碼中定義的變數。然後,gRPC 伺服器會將包含所有流程變數的回應傳回 Apigee。
- Apigee 會讀取 gRPC 伺服器的回應。如果新增任何變數或修改可修改的流程變數,這些變數就會在 Apigee 中更新。
這項政策是標準政策,可部署至任何環境類型。如要瞭解各環境類型適用的政策類型和可用性,請參閱「政策類型」。
如要進一步瞭解如何傳送 gRPC 要求,請參閱下列連結:
<ExternalCallout>
定義 ExternalCallout 政策。
<ExternalCallout async="true" continueOnError="true" enabled="true" name="EC">
這個元素包含下列所有政策都適用的屬性:
| 屬性 | 預設 | 是否必要? | 說明 |
|---|---|---|---|
name |
不適用 | 必要 |
政策的內部名稱。 您可以選擇使用 |
continueOnError |
false | 選用 | 將其設為 false,即可在政策失敗時傳回錯誤。這是大多數政策的預期行為。將其設為 true,即使政策失敗,流程執行作業仍會繼續進行。另請參閱:
|
enabled |
是 | 選用 | 設為 true 即可強制執行政策。設為 false 即可關閉政策。即使政策仍附加至流程,系統也不會強制執行這項政策。 |
async |
false | 已淘汰 | 此屬性已淘汰。 |
下表說明 <ExternalCallout> 的子元素。
| 子元素 | 必填 | 說明 |
|---|---|---|
<TimeoutMs> |
必填 | gRPC 要求的逾時時間 (以毫秒為單位)。 |
<GrpcConnection> |
必填 | 指定現有 TargetServer 的名稱,做為要傳送要求的 gRPC 伺服器。 |
<Configurations> |
選用 | 可讓您設定 ExternalCallout 政策的各個層面,包括 <Property> 和 <FlowVariable> 元素。 |
範例 1
如需 ExternalCallout 的工作範例,請前往 GitHub 的「External Callout Samples」。
以下範例說明 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>
這個範例會將要求傳送至以名為 external-target-server 的
TargetServer 代表的外部 gRPC 伺服器,並採用下列設定:
<Property>:在傳送至 gRPC 伺服器的要求中,納入要求和回應內容,但不納入要求和回應標頭。<FlowVariable>:在傳送至 gRPC 伺服器的要求中,加入FlowVariable元素指定的其他流程變數example1.flow.variable和example2.flow.variable。
範例 2
在以下範例中,Audience 元素的 useTargetUrl 屬性設為 true。如果 useTargetUrl 為 true,系統會將 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 伺服器為現有的 TargetServer 名為 external-target-server。
使用 <Authentication> 元素 (本節稍後會說明),產生 Google 發行的 OpenID Connect 權杖,向以 gRPC 為基礎的服務 (例如 Cloud Run 中代管的自訂服務) 發出經過驗證的呼叫。
下表說明 <GrpcConnection> 的子元素。
| 子元素 | 是否必要 | 說明 |
|---|---|---|
<Server> 元素 |
必要 | 指定 gRPC 伺服器。 |
<Authentication> 元素 |
選用 | 產生 Google 發行的 OpenID Connect 權杖,向以 gRPC 為基礎的服務 (例如 Cloud Run) 發出經過驗證的呼叫。 |
<Server> 元素
指定 gRPC 伺服器。
下表說明 <Server> 元素的屬性。
| 屬性 | 說明 | 預設 | 狀態 | 類型 |
|---|---|---|---|---|
name |
現有 |
不適用 | 必填 | 字串 |
<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 為空或解析為空值,且 useTargetUrl 為 true,則「https://」+ (gRPC 目標伺服器的主機名稱) 會做為目標對象。舉例來說,如果伺服器主機是 my-grpc-server-java.a.run.app,則使用的目標對象會是 https://my-grpc-server-java.a.run.app。
根據預設,useTargetUrl 為 false。
<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,產生的驗證權杖會包含服務帳戶 email 和 email_verified 聲明。
| 預設 | false |
| 必填與否 | 選用 |
| 類型 | 布林值 |
| 父項元素 | <GoogleIDToken> |
| 子元素 | 無 |
<Configurations>
<Configurations> 元素可讓您設定 ExternalCallout 政策的各個層面,包括 <Property> 和 <FlowVariable>。
下表說明 <Configurations> 的子元素。
| 子元素 | 是否必要 | 說明 |
|---|---|---|
<Property> |
必要 | 指定是否要將要求/回應標頭和/或內容傳送至伺服器。可能的值為 |
<FlowVariable> |
必要 | 指定應傳送至伺服器的其他流程變數。 |
<Property>
<Property> 元素會指定是否要將要求/回應標頭和/或內容傳送至伺服器。可能的值為 true (系統會傳送項目) 或 false (系統不會傳送項目)。預設值為 false。
下表說明 <Property> 元素的屬性。
| 屬性 | 說明 | 預設 | 狀態 | 類型 |
|---|---|---|---|---|
name |
指定要傳送至伺服器的內容。
|
不適用 | 必填 | 字串 |
<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 |
如果使用 <Authentication> 標記設定 Proxy 時缺少服務帳戶,就會發生這個錯誤。例如: 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> 標記設定,服務帳戶發生權限問題時就會發生這個錯誤。可能原因:
|
執行階段錯誤
下表說明政策執行時可能發生的執行階段錯誤。
| 錯誤代碼 | HTTP 狀態 | 原因 |
|---|---|---|
GrpcTlsInitFailed |
500 |
如果使用 gRPC 伺服器初始化 TLS 時發生任何問題 (例如金鑰儲存區或信任儲存區問題),就會發生這個錯誤。 |
steps.externalcallout.[error_code] |
500 |
|
steps.externalcallout.ExecutionError |
500 |
如果執行這項政策時發生任何其他例外狀況,就會出現這個錯誤。基礎例外狀況會顯示在 faultstring 中。 如果 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 |
已啟用 |
steps.externalcallout.ExecutionError
錯誤字串:
|
500 |
如果 API Proxy 是使用
|
steps.externalcallout.ExecutionError,且 faultstring 包含
PERMISSION DENIED。
舉例來說,Cloud Run 的 faultstring 如下所示:
|
500 |
如果 API Proxy 是使用
|
其他錯誤
下表說明其他錯誤。詳情請參閱原因。
| 錯誤代碼 | 原因 |
|---|---|
ReferencesExistToGrpcServer |
如果使用者嘗試刪除 gRPC 目標伺服器,但該伺服器仍由其他政策使用,就會發生這個錯誤。 |
斷層
下表中的錯誤變數預設會為所有政策設定。請參閱 政策錯誤專屬變數。
| 變數 | 地點 | 範例 |
|---|---|---|
fault.name="fault_name" |
fault_name 是故障名稱,如上方的「執行階段錯誤」表格所示。錯誤名稱是錯誤代碼的最後一部分。 |
fault.name 與「ExecutionError」相符。 |
externalcallout.[policy_name].failed |
policy_name 是使用者指定的政策名稱,該政策擲回了錯誤。 |
externalcallout.ExternalCallout-1.failed = true |