This page applies to Apigee and Apigee hybrid.
  
    View 
    Apigee Edge documentation.
  
  
       
 
  
What
The ExternalCallout policy enables you to send gRPC requests to your gRPC server to implement custom behavior that isn't supported by Apigee policies. In your server's code, you can easily access and modify flow variables within a proxy's flow.
Apigee communicates with a gRPC server through an ExternalCallout policy via an API. Apigee uses the API to send flow variables to the gRPC server. Within your gRPC server, you can read—and depending on the variable, modify— the flow variables listed in the Flow variables reference page, as well as additional variables you specify within the policy's XML.
If you configure the gRPC server with Apigee and include this policy in a proxy, Apigee will handle API requests as follows:
- Apigee sends a message containing the flow variables to your gRPC server.
- Your gRPC server code executes, accessing and modifying variables as defined in the code. The gRPC server then sends a response containing all the flow variables back to Apigee.
- Apigee reads the response from your gRPC server. If any variables are added or modifiable flow variables are modified, they are updated in Apigee.
This policy is a Standard policy and can be deployed to any environment type. For information on policy types and availability with each environment type, see Policy types.
To learn more about sending gRPC requests, see the following links:
<ExternalCallout>
  Defines an ExternalCallout policy.
<ExternalCallout async="true" continueOnError="true" enabled="true" name="EC">
This element has the following attributes that are common to all policies:
| Attribute | Default | Required? | Description | 
|---|---|---|---|
| name | N/A | Required | The internal name of the policy. The value of the  Optionally, use the  | 
| continueOnError | false | Optional | Set to falseto return an error when a policy fails. This is expected behavior for
          most policies. Set totrueto have flow execution continue even after a policy
            fails. See also: | 
| enabled | true | Optional | Set to trueto enforce the policy. Set tofalseto turn off the
          policy. The policy will not be enforced even if it remains attached to a flow. | 
| async | false | Deprecated | This attribute is deprecated. | 
The following table describes the child elements of
    <ExternalCallout>.
| Child Element | Required | Description | 
|---|---|---|
| <TimeoutMs> | Required | The request timeout in milliseconds for gRPC requests. | 
| <GrpcConnection> | Required | Specifies the name of an existing TargetServerto be the gRPC server to
        send requests to. | 
| <Configurations> | Optional | Allows you to configure various aspects of the ExternalCallout policy,
        including the <Property>and<FlowVariable>elements. | 
Example 1
Working examples of ExternalCallout are available at External Callout Samples on GitHub.
The following example illustrates an ExternalCallout policy configuration.
<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>
The example sends a request to an external gRPC server represented by the
  
  TargetServer named external-target-server, with the following configurations:
- <Property>: Include request and response content, but not the request and response headers, in the request sent to the gRPC server.
- <FlowVariable>: Include additional flow variables- example1.flow.variableand- example2.flow.variable, specified by the- FlowVariableelements, in the request sent to the gRPC server.
Example 2
In the following example, the useTargetUrl attribute of the Audience
  element is set to true. When useTargetUrl is true,
  the hostname of the gRPC target server is used as the audience. For
example, if the host of the server is my-grpc-server-java.a.run.app, then the audience
used will be 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>
Child element reference
The following sections describe the child elements of ExternalCallout.
<TimeoutMs>
  The request timeout in milliseconds for gRPC requests. <TimeoutMs> must be
  a positive number.
<GrpcConnection>
The <GrpcConnection> element sets the gRPC server to be an existing
     TargetServer, specified by the name attribute. See the
     
     TargetServer resource reference page.
Note: The
    
    protocol for the TargetServer must be GRPC.
For example, the following code
<GrpcConnection> <Server name="external-target-server"/> </GrpcConnection>
specifies the gRPC server to be an existing TargetServer named
    external-target-server.
  Use the <Authentication> element (described later in this section) to generate a Google-issued
  OpenID Connect token
  to make authenticated calls to gRPC-based services, such as custom services hosted in
  Cloud Run.
The following table describes the child elements of
    <GrpcConnection>.
| Child Element | Required? | Description | 
|---|---|---|
| <Server>element | Required | Specifies the gRPC server. | 
| <Authentication>element | Optional | Generates a Google-issued OpenID Connect token to make authenticated calls to gRPC-based services, such as Cloud Run. | 
<Server> element
  Specifies the gRPC server.
The following table describes the attributes of the <Server>
  element.
| Attribute | Description | Default | Presence | Type | 
|---|---|---|---|---|
| name | The name of an existing  | N/A | Required | String | 
<Authentication> element
Generates a Google-issued OpenID Connect token to make authenticated calls to gRPC-based services, such as custom services hosted in Cloud Run. Use of this element requires setup and deployment steps described in Using Google authentication. With proper setup, the policy creates an authentication token for you and adds it to the service request.
This element has one required child element: GoogleIDToken.
| Default | N/A | 
| Required? | Optional. | 
| Type | Complex type | 
| Parent Element | <GrpcConnection> | 
| Child Elements | <GoogleIDToken> | 
The Authentication element uses the following syntax:
Syntax
<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>
Example
The following example shows the GoogleIDToken element:
<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>
Attributes
None.
<HeaderName> child element
By default, when an Authentication configuration is present, Apigee generates a bearer
    token and injects it into the Authorization header in the message sent to the target system.
    The HeaderName element allows you to specify the name of a different header
    to hold that bearer token. This feature is particularly useful when the target is a Cloud Run
    service that uses the X-Serverless-Authorization header. The Authorization header,
    if present, is left unmodified and also sent in the request.
| Default | N/A | 
| Required? | No | 
| Type | String | 
| Parent Element | <Authentication> | 
| Child Elements | None | 
The HeaderName element uses the following syntax:
Syntax
<ExternalCallout>
...
  <Authentication>
    <HeaderName ref="FLOW_VARIABLE">STRING</HeaderName>
    <GoogleIDToken>
    ... 
    </GoogleIDToken>
  </Authentication>
  ...
</ExternalCallout>With static string
In this example, the generated bearer token is added, by default, to a header named X-Serverless-Authorization
        that is sent to the target system. The Authorization header,
        if present, is left unmodified and also sent in the request.
<Authentication>
  <HeaderName>X-Serverless-Authorization</HeaderName>
  <GoogleIDToken>
    <Audience>https://cloudrun-hostname.a.run.app</Audience>
  </GoogleIDToken>
</Authentication>With variable reference
In this example, the generated bearer token is added, by default, to a header named X-Serverless-Authorization
        that is sent to the target system. If my-variable has a value, that value is used
        instead of the default string. The Authorization header,
        if present, is left unmodified and also sent in the request.
<Authentication> <HeaderName ref='my-variable'>X-Serverless-Authorization</HeaderName> <GoogleIDToken> <Audience>https://cloudrun-hostname.a.run.app</Audience> </GoogleIDToken> </Authentication>
<GoogleIDToken> child element
Generates Google-issued OpenID Connect tokens to make authenticated calls to Google services, such as custom services hosted in Cloud Run.
| Default | N/A | 
| Required? | Required | 
| Type | String | 
| Parent Element | <Authentication> | 
| Child Elements | <Audience><IncludeEmail> | 
The GoogleIDToken element uses the following syntax:
Syntax
<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>
Example
The following example shows the GoogleIDToken element:
<Authentication>
  <GoogleIDToken>
      <Audience>https://httpserver0-bar.run.app</Audience>
      <IncludeEmail>true</IncludeEmail>
  </GoogleIDToken>
</Authentication>
<Audience> child element
The audience for the generated authentication token, such as the API or account that the token grants access to.
  If the value of Audience is empty, the ref is empty or resolves to an
  empty value, and useTargetUrl is true, then "https://" +
  (hostname of the gRPC target server) is used as the audience.
  For example, if the host of the server is my-grpc-server-java.a.run.app, then the
  audience used will be https://my-grpc-server-java.a.run.app.
By default, useTargetUrl is 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'/>
| Default | N/A | 
| Required? | Required | 
| Type | String | 
| Parent Element | <GoogleIDToken> | 
| Child Elements | None. | 
<IncludeEmail> child element
  If set to true, the generated authentication token will contain the
  service account email and email_verified claims.
| Default | false | 
| Required? | Optional | 
| Type | Boolean | 
| Parent Element | <GoogleIDToken> | 
| Child Elements | None. | 
<Configurations>
The <Configurations> element allows you to configure various aspects of
   the ExternalCallout policy,
   including <Property> and <FlowVariable>.
The following table describes the child elements of
    <Configurations>.
| Child Element | Required? | Description | 
|---|---|---|
| <Property> | Required | Specifies whether request/response headers and/or content will be sent to
         the server. Possible values are  | 
| <FlowVariable> | Required | Specifies what additional flow variables should be sent to the server. | 
<Property>
The <Property> element specifies whether request/response
     headers and/or content will be sent to the server. Possible values are true
     (the item will be sent) or false (the item won't be sent). The default value
     is false.
The following table describes the attributes of the <Property>
  element.
| Attribute | Description | Default | Presence | Type | 
|---|---|---|---|---|
| name | Specifies what content will be sent to
         the server. Possible values for  
 | N/A | Required | String | 
<FlowVariable>
The <FlowVariable> element specifies what additional flow variables
   will be sent to the server. The value of
   <FlowVariable> is a prefix of a variable, rather than the full variable name.
    For example , if the a.b.c, the
    value of a variable named a.b.c will be sent to the server. Similarly, the value
    of a variable
    named a.b.c.my-variable will be sent to the server. But the value of a variable
    named a.x.another-variable will not be sent, because it does not have the
    prefix a.b.c. Here are some examples
<Configurations> <FlowVariable>a.b.c</FlowVariable> <FlowVariable>d.e.f</FlowVariable> </Configurations>
Error Reference
Deployment errors
| Error name | Cause | 
|---|---|
| FAILED_PRECONDITION | This error happens if the service account is missing when the proxy is
          configured with the <Authentication>tag.For example: Deployment of \"organizations/foo/apis/apiproxy/revisions/1\" requires a service account identity, but one was not provided with the request. | 
| PERMISSION_DENIED | This error happens if there is a permission problem with the service account if
           the proxy is
          configured with the <Authentication> tag. Possible causes: 
 | 
Runtime errors
The table below describes runtime errors, which can occur when the policy executes.
| Fault code | HTTP Status | Cause | 
|---|---|---|
| GrpcTlsInitFailed | 500 | This error will occur if there are any issues with initializing TLS with the gRPC server (such as Keystore or truststore issues). | 
| steps.externalcallout.[error_code] | 500 | 
 | 
| steps.externalcallout.ExecutionError | 500 | This error will occur if any other exception occurs during the execution of this policy. The underlying exception will be exposed in the faultstring. If there was an issue with the credentials to the gRPC server, the error will look something like this: 
{
  "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"
    }
  }
}You can look at the logs of the MP for further debugging pointers. | 
| googletoken.EmptyIDTokenAudience | 500 | 
 | 
| steps.externalcallout.ExecutionErrorwith fault string: 
 | 500 | 
            This error happens if the API proxy is configured with the  
 | 
| steps.externalcallout.ExecutionErrorwith faultstring containingPERMISSION DENIED.For example, the faultstring will look like the following for Cloud Run: 
 | 500 | 
            This error happens if the API proxy is configured with the  
 | 
Miscellaneous errors
The table below describes miscellaneous errors. See the cause for more details.
| Fault code | Cause | 
|---|---|
| ReferencesExistToGrpcServer | This error will occur if a user tries to delete a gRPC target server, but the server is still being used by other policies. | 
Faults
The fault variables in the following table are set for all policies by default. See Variables specific to policy errors.
| Variables | Where | Examples | 
|---|---|---|
| fault.name="fault_name" | fault_nameis the name of the fault, as listed in the Runtime errors
         table above. The fault name is the last part of the fault code. | fault.namematches "ExecutionError". | 
| externalcallout.[policy_name].failed | policy_nameis the user-specified name of the policy that threw the fault. | externalcallout.ExternalCallout-1.failed = true |