本頁內容適用於 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 伺服器的要求中,加入example1.flow.variable
和example2.flow.variable
,以及FlowVariable
元素指定的其他流程變數。
範例 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 |