ExternalCallout 政策

本页面适用于 ApigeeApigee Hybrid

查看 Apigee Edge 文档。

政策图标

内容

通过 ExternalCallout 政策,您可以向 gRPC 服务器发送 gRPC 请求,以实现 Apigee 政策不支持的自定义行为。您可以在服务器代码中轻松地访问和修改代理流中的流变量。

Apigee 通过 ExternalCallout 政策使用 API 与 gRPC 服务器通信。 Apigee 使用该 API 向 gRPC 服务器发送流变量。您可以在 gRPC 服务器中读取及修改(具体取决于变量权限)流变量参考页面中列出的流变量以及您在政策 XML 中指定的其他变量。

如果您使用 Apigee 配置 gRPC 服务器并将此政策添加到代理中,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> 元素在管理界面代理编辑器中给政策添加不同的自然语言名称标签。

continueOnError 可选 设置为 false 可在政策失败时返回错误。这是大多数政策的预期行为。设置为 true,即使在政策失败后,仍可以继续执行流。另请参阅:
enabled true 可选 设置为 true 可实施政策。 设为 false 可关闭政策。即使政策仍附加到某个流,也不会强制执行该政策。
async   已弃用 此属性已弃用。

下表介绍了 <ExternalCallout> 的子元素。

子元素 必需 说明
<TimeoutMs> 必需 gRPC 请求的请求超时(以毫秒为单位)。
<GrpcConnection> 必需 指定现有 TargetServer 的名称,作为向其发送请求的 gRPC 服务器。
<Configurations> 可选 允许您配置 ExternalCallout 政策的各个方面,包括 <Property><FlowVariable> 元素。

示例 1

如需查看 ExternalCallout 的工作示例,请参阅 GitHub 上的外部 Callout 示例

以下示例展示了 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.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 服务器设置为由 name 属性指定的现有 TargetServer。请参阅 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 令牌,以便对基于 gRPC 的服务(例如 Cloud Run)进行经过身份验证的调用。

<Server> 元素

指定 gRPC 服务器。

下表介绍了 <Server> 元素的属性。

属性 说明 默认 Presence 类型
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> 子元素

默认情况下,如果存在 Authentication 配置,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> 元素的属性。

属性 说明 默认 Presence 类型
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 如果在使用 <Authentication> 标记配置代理时缺少服务账号,则会发生此错误。

例如:

Deployment of \"organizations/foo/apis/apiproxy/revisions/1\"
requires a service account identity, but one was not provided
with the request.
PERMISSION_DENIED 如果在使用 <Authentication> 标记配置代理时服务账号出现权限问题,则会发生此错误。可能的原因:
  • 该服务账号不存在。
  • 服务账号不是在与 Apigee 组织相同的 Google Cloud 项目中创建的。
  • 部署者拥有服务账号的 iam.serviceAccounts.actAs 权限。如需了解详情,请参阅服务账号权限简介

运行时错误

下表介绍了执行政策时可能发生的运行时错误。

故障代码 HTTP Status 原因
GrpcTlsInitFailed 500

如果使用 gRPC 服务器初始化 TLS 时遇到任何问题(例如密钥库或信任库问题),则会出现此错误。

steps.externalcallout.[error_code] 500

[error_code] 由故障消息的 errorCode 字段确定。错误的故障字符串是故障消息的 faultstring 字段。

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

<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 代理配置了 <Authentication> 元素,则会发生此错误。可能的原因:

  • 使用代理部署的服务账号:
    • 在您的项目中不存在(部署时存在,但部署后删除了)
    • 已停用
    • (仅限 Apigee Hybrid)尚未向 apigee-runtime 服务账号授予 roles/iam.serviceAccountTokenCreator 角色。
  • (仅限 Apigee Hybrid)apigee-runtime 服务账号的源项目中已停用 IAMCredentials API。

    注意:仅针对 Apigee Hybrid,请检查运行时容器的日志并搜索 externalcallout.ExecutionError,以查找可能有助于调试该问题的详细错误消息。

带有包含 PERMISSION DENIED 的故障字符串的 steps.externalcallout.ExecutionError

例如,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 代理配置了 <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

相关主题