Message templates

This topic discusses how to use message templates in API proxies and provides a function reference.

What is a message template?

A message template permits you to perform variable string substitution in certain policy and TargetEndpoint elements. This feature, where supported, lets you populate strings dynamically when a proxy executes.

You can include any combination of flow variable references and literal text in a message template. Flow variable names must be enclosed in curly braces, while any text not in curly braces is output as literal text.

See also Where can you use message templates?

Example

For example, the Assign Message policy lets you use a message template within in the <Payload> element:

<AssignMessage name="set-dynamic-content">
  <AssignTo createNew="false" type="response"></AssignTo>
  <Set>
    <Payload contentType="application/json">
      {"name":"Alert", "message":"You entered an invalid username: {user.name}"}
    </Payload>
  </Set>
  <IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
</AssignMessage>

In the above example, the value of flow variable user.name (in curly braces) will be evaluated and substituted into the payload string at runtime. So, for example, if user.name=jdoe, then the resulting message output in the payload will be: You entered an invalid username: jdoe. If the variable cannot be resolved, then an empty string is output.

Example

When a quota is exceeded, it is a good practice to return a meaningful message to the caller. This pattern is commonly used with a "fault rule" to provide output to give the caller information about the quota violation. In the following Assign Message policy, message templates are used to populate quota information dynamically in several XML elements:

<AssignMessage name='AM-QuotaViolationMessage'>
  <Description>message for quota exceeded</Description>
  <IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
  <Set>
    <Headers>
      <Header name='X-Quota-Reset'>{ratelimit.Quota-1.expiry.time}</Header>
      <Header name='X-Quota-Allowed'>{ratelimit.Quota-1.allowed.count}</Header>
      <Header name='X-Quota-Available'>{ratelimit.Quota-1.available.count}</Header>
    </Headers>
    <Payload contentType='application/json'>{
  "error" : {
    "message" : "you have exceeded your quota",
    "clientId" : "{request.queryparam.apikey}"
  }
}
    </Payload>
    <StatusCode>429</StatusCode>
    <ReasonPhrase>Quota Exceeded</ReasonPhrase>
  </Set>
</AssignMessage>

In the AssignMessage policy, the following elements in the <Set> element support message templating:

  • Header
  • QueryParam
  • FormParam
  • PayLoad
  • Version
  • Verb
  • Path
  • StatusCode
  • ReasonPhrase

Again, note that flow variables in a message template must be enclosed in curly braces.

When this policy executes:

  • The Header elements receive values of the specified flow variables.
  • The Payload includes a mix of literal text and variables (the client_id is populated dynamically).
  • The StatusCode and ReasonPhrase only include literal text; however, these elements also support message templating if you wish to use it.

Example

In a proxy TargetEndpoint definition, child-elements of <SSLInfo> support message templating. Following the same pattern used in policies, the flow variables in curly braces are replaced when the proxy executes.

<TargetEndpoint name="default">
  …
  <HTTPTargetConnection>
    <SSLInfo>
        <Enabled>{myvars.ssl.enabled}</Enabled>
        <ClientAuthEnabled>{myvars.ssl.client.auth.enabled}</ClientAuthEnabled>
        <KeyStore>{myvars.ssl.keystore}</KeyStore>
        <KeyAlias>{myvars.ssl.keyAlias}</KeyAlias>
        <TrustStore>{myvars.ssl.trustStore}</TrustStore>
    </SSLInfo>

  </HTTPTargetConnection>
  …
</TargetEndpoint>

Where can you use message templates?

Message templates are supported in several policies as well as certain elements used in the TargetEndpoint configuration.

Policies that accept message templates

Policy Elements and child-elements that support message templates
AssignMessage policy <Set> child elements: Payload, ContentType, Verb, Version, Path, StatusCode, ReasonPhrase, Headers, QueryParams, FormParams

<Add> child elements: Headers, QueryParams, FormParams

<AssignVariable> child element: <Template>

ExtensionCallout policy <Input>
ExtractVariables policy <JsonPath>
GenerateJWT policy
VerifyJWTpolicy
<AdditionalClaims><Claim>

<AdditionalHeaders><Claim>

* These elements support message template only when type=map.

LDAP policy <SearchQuery>
MessageLogging policy <Syslog><Message>

<File><Message>

RaiseFault policy <Set> elements: Payload, ContentType, Verb, Version, Path, StatusCode, ReasonPhrase, Headers, QueryParams, FormParams

<Add> elements: Headers, QueryParams, FormParams

SAMLAssertion policy <Template>

* Only when the policy signature is <GenerateSAMLAssertion>

ServiceCallout policy <Set> elements: Payload, ContentType, Verb, Version, Path, StatusCode, ReasonPhrase, /Headers, QueryParams, FormParams

<Add> elements: Headers, QueryParams, FormParams

<HTTPTargetConnection>/<URL>: Note that the first part of the string must be http or https.

TargetEndpoint elements that accept message templates

HTTPTargetConnection elements Child-elements that support message templates
SSLInfo Enabled, KeyAlias, KeyStore, TrustStore, ClientAuthEnabled, CLRStore
LocalTargetConnection ApiProxy, ProxyEndpoint
Path N/A

Message template syntax

This section explains the rules you must follow to use message templates.

Use curly braces to denote variables

Enclose variable names in curly braces { }. If the variable does not exist, an empty string is returned in the output; however, you can specify default values in message templates (values that are substituted if the variable is unresolved). See Setting default values in message templates.

Note that enclosing the entire message template string in quotes is permitted, but optional. For example, the following two message templates are equivalent:

<Set>
    <Headers>
        <Header name="x-h1">"Hello {user.name}"</Header>
        <Header name="x-h1">Hello {user.name}</Header>
    </Headers>
</Set>

Setting default values in message templates

If a templated variable can't be resolved, Edge substitutes an empty string. However, you can specify a default value as follows:

 <Header name="x-h1">Test message. id = {request.header.id:Unknown}</Header>

In the above sample if the variable request.header.id cannot be resolved then its value is replaced by Unknown. For example:

Test message. Unknown

Legacy syntax for JSON payloads

In Edge versions before Cloud release 16.08.17, you could not use curly braces to denote variable references within JSON payloads. In those older versions, you needed to use the variablePrefix and variableSuffix attributes to specify delimiter characters, and use those to wrap variable names, like so:

<Set>
    <Payload contentType="application/json" variablePrefix="@" variableSuffix="#">
        {"name":"foo", "type":"@variable_name#"}
    </Payload>
</Set>

Although Apigee recommends that you use the newer curly-brace syntax, the older syntax still works.

Using message template functions

Edge provides a set of functions that you can use within message templates to escape, encode, hash, and format string variables.

The message template functions are described in detail in Message template function reference.

Example: toLowerCase()

Use the built-in toLowerCase() function to transform a string variable to lowercase:

<AssignMessage name="AM-Set-Custom-Response">
    <AssignTo createNew="false" type="response"/>
    <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
    <Set>
        <Headers>
            <Header name="x-h1">Test header: {toLowerCase(foo.bar:FOO)}</Header>
        </Headers>
    </Set>
</AssignMessage>

If the foo.bar flow variable resolves, then its characters will be all lowercase. If foo.bar is unresolved and the default value FOO is substituted and converted to lowercase characters. For example:

Test header: foo

Example: escapeJSON()

Here's an interesting use case: Let's say your backend app returns a JSON response that contains valid escape characters. For example:

{
      "code": "INVALID",
      "user_message": "Invalid value for \"logonId\" check your input."
}

Then, let's say you want to return this message to the client caller in a custom payload. The usual way to do this is to extract the message from the target response payload and use Assign Message to add it to a custom proxy response (that is, send it back to the client).

Here's the Extract Variables policy that extracts the user_message information into a variable called standard.systemMessage:

<ExtractVariables name="EV-BackendErrorResponse">
    <DisplayName>EV-BackendErrorResponse</DisplayName>
    <JSONPayload>
        <Variable name="standard.systemMessage">
            <JSONPath>$.user_message</JSONPath>
        </Variable>
    </JSONPayload>
</ExtractVariables>

Now, here's a perfectly valid Assign Message policy that adds the extracted variable to the response payload (the proxy response):

<AssignMessage name="AM-SetStandardFaultResponse">
    <DisplayName>AM-SetStandardFaultResponse</DisplayName>
    <Set>
        <Payload contentType="application/json">
           {
              "systemMessage": "{standard.systemMessage}"
           }
        </Payload>
    </Set>
    <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
    <AssignTo createNew="false" transport="http" type="response"/>
</AssignMessage>


Unfortunately, there's a problem. The Extract Variables policy removed the escaped quotation characters around part of the message. This means that the response returned to the client is invalid JSON. This is clearly not what you intended!

{
    "systemMessage": "Invalid value for "logonId" check your input."
}

To work around this problem, you can modify the Assign Message policy to use a message template function that escapes the quotes within the JSON for you. This function, escapeJSON(), escapes any quotes or other special characters that occur within a JSON expression:

<AssignMessage name="AM-SetStandardFaultResponse">
    <DisplayName>AM-SetStandardFaultResponse</DisplayName>
    <Set>
        <Payload contentType="application/json">
           {
              "systemMessage": "{escapeJSON(standard.systemMessage)}"
           }
        </Payload>
    </Set>
    <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
    <AssignTo createNew="false" transport="http" type="response"/>
</AssignMessage>


The function escapes the embedded quotes, resulting in valid JSON, which is exactly what you wanted:

{
      "systemMessage": "Invalid value for \"logonId\" check your input.",
}

A message template is a dynamic string substitution feature that you can use in certain policies and in TargetEndpoint definitions. Message template functions let you perform useful operations such as hashing, string manipulation, character escaping, and others within a message template.

For example, in the following AssignMessage policy, the function toLowerCase() is used in a message template:

<AssignMessage name="AM-Set-Custom-Response">
    <AssignTo createNew="false" type="response"/>
    <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
    <Set>
       <Headers>
         <Header name="x-h1">Test header: {Hello, toLowerCase(user.name)}</Header>
       </Headers>
    </Set>
</AssignMessage>

This topic describes the message template functions, their arguments, and outputs. This topic assumes that you are familiar with message templates and the contexts in which they are used.

Hash functions

Compute a hash value and return the string representation of that hash.

Hexadecimal hash functions

Compute a hash value and return the string representation of that hash as a hexadecimal number.

Syntax

Function Description
md5Hex(string) Computes an MD5 hash expressed as a hexadecimal number.
sha1Hex(string) Computes a SHA1 hash expressed as a hexadecimal number.
sha256Hex(string) Computes a SHA256 hash expressed as a hexadecimal number.
sha384Hex(string) Computes a SHA384 hash expressed as a hexadecimal number.
sha512Hex(string) Computes a SHA512 hash expressed as a hexadecimal number.

Arguments

string - The Hash functions take a single string argument upon which the hash algorithm is computed. The argument can be a literal string or a string flow variable.

Examples

Function call:

sha256Hex('abc')

Result:

ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad

Function call:

var str = 'abc';
sha256Hex(str)

Result:

ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad

Base64 hash functions

Compute a hash value and return the string representation of that hash as a Base64 encoded value.

Syntax

Function Description
md5Base64(string) Computes an MD5 hash expressed as a Base64 encoded value.
sha1Base64(string) Computes a SHA1 hash expressed as a Base64 encoded value.
sha256Base64(string) Computes a SHA256 hash expressed as a Base64 encoded value.
sha384Base64(string) Computes a SHA384 hash expressed as a Base64 encoded valuer.
sha512Base64(string) Computes a SHA512 hash expressed as a Base64 encoded value.

Arguments

string - The Hash functions take a single string argument upon which the hash algorithm is computed. The argument can be a literal string or a string flow variable.

Examples

Function call:

sha256Base64('abc')

Result:

OghSaGiHHx1fTv3y8SKdZYAoGHcqBUpKjNJyGDJ11T215Acw1orz3N2L/NlbwelxZ5R2kuPHuNDb1ZzttKplCg==

Function call:

var str = 'abc';
sha256Base64(str)

Result:

OghSaGiHHx1fTv3y8SKdZYAoGHcqBUpKjNJyGDJ11T215Acw1orz3N2L/NlbwelxZ5R2kuPHuNDb1ZzttKplCg==

String functions

Perform operations on strings within a message template.

Base64 encoding functions

Encode and decode strings using the Base64 encoding scheme.

Syntax

Function Description
encodeBase64(string) Encodes a string using Base64 encoding. For example: encodeBase64(value), when value holds abc, the function returns the string: YWJj
decodeBase64(string) Decodes a Base64 encoded string. For example: decodeBase64(value) when value holds aGVsbG8sIHdvcmxk, the function returns the string hello, world.

Arguments

string - The string to encode or decode. Can be a literal string or a string flow variable.

Example

<AssignMessage name="AM-Set-Custom-Response">
    <AssignTo createNew="false" type="response"/>
    <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
    <Set>
       <Headers>
         <Header name="x-h1">Hello, {decodeBase64('d29ybGQK')}</Header>
       </Headers>
    </Set>
</AssignMessage>

Case conversion functions

Convert a string to all uppercase or all lowercase letters.

Syntax

Function Description
toUpperCase(string) Convert a string to uppercase.
toLowerCase(string) Convert a string to lowercase.
encodeBase64(string) Encodes a string using Base64 encoding. For example: encodeBase64(value), when value holds abc, the function returns the string: YWJj
decodeBase64(string) Decodes a Base64 encoded string. For example: decodeBase64(value) when value holds aGVsbG8sIHdvcmxk, the function returns the string hello, world.


Arguments

string - The string to convert. Can be a literal string or a string flow variable.

Example

<AssignMessage name="AM-Set-Custom-Response">
    <AssignTo createNew="false" type="response"/>
    <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
    <Set>
       <Headers>
         <Header name="x-h1">Hello, {toLowerCase(user.name)}</Header>
       </Headers>
    </Set>
</AssignMessage>

Substring function

Replaces characters between the starting and ending index with the specified string.

Syntax

substring(str, start_index, end_index)

Arguments

  • str - A literal string or string flow variable.
  • start_index - The starting index into the string. Character replacement begins here.
  • end_index - (Optional) The ending index into the string. If not supplied, the replacement occurs between the starting index and the end of the string.

Examples

For the following examples, suppose that these flow variables exist:

Variable name Value
alpha ABCDEFGHIJKLMNOPQRSTUVWXYZ
seven 7


Here are results of function calls that use these variables:

Message template expression Result
{substring(alpha, 22)} WXYZ
hello {substring(alpha, 22)} hello WXYZ
{substring(alpha, -4)} WXYZ
{substring(alpha, -8, -4)} STUV
{substring(alpha, 0, 10)} ABCDEFGHIJ
{substring(alpha, 0, seven)} ABCDEFG

Replace All function

Applies a regular expression to a string and for any matches, replaces the match with a replacement value.

Syntax

replaceAll(string, regex, value)

Arguments

  • string - A literal string or string flow variable in which to make replacements.
  • regex - A regular expression.
  • value - The value to replace all regex matches within the string.

Examples

For the following examples, suppose these flow variables exist:

Variable name Value
header Bearer ABCDEFGHIJKLMNOPQRSTUVWXYZ-9993
regex1 "^Bearer "
replacement "TOKEN: "

Here are results of function calls that use these variables:

Message template expression Result
{replaceAll(header, "9993", '')} Bearer ABCDEFGHIJKLMNOPQRSTUVWXYZ-
{replaceAll(header, regex1, '')} ABCDEFGHIJKLMNOPQRSTUVWXYZ-9993
{replaceAll(header, regex1, replacement)} TOKEN: ABCDEFGHIJKLMNOPQRSTUVWXYZ-9993

Replace First function

Replaces only the first occurrence of the specified regular expression match in the string.

Syntax

replaceFirst(string, regex, value)

Arguments

  • string - A literal string or string flow variable in which to make replacements.
  • regex - A regular expression.
  • value - The value to replace regex matches within the string.

Character escape and encoding functions

Functions that escape or encode special characters in a string.

Syntax

Function Description
escapeJSON(string) Backslash-escapes double-quotes.
escapeXML(string) Replaces angle brackets, apostrophe, double-quote and ampersands with the respective XML entities. Use for XML 1.0 documents.

escapeXML11(string) Works the same way as escapeXML, but for XML v1.1 entities. See Usage notes below.
encodeHTML(string) Encodes apostrophe, angle brackets, and ampersand.

Arguments

string - The string to escape. Can be a literal string or a string flow variable.

Usage notes

XML 1.1 can represent certain control characters, but it cannot represent the null byte or unpaired Unicode surrogate codepoints, even after escaping. The escapeXML11() function removes characters that do not fit in the following ranges:

[#x1-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]

The escapeXML11() function escapes characters in the following ranges:

[#x1-#x8] | [#xB-#xC] | [#xE-#x1F] | [#x7F-#x84] | [#x86-#x9F]

Examples

Assume a flow variable called food exists with this value: "bread" & "butter". Then, the function:

{escapeHTML(food)}

results in:

&quot;bread&quot; &amp; &quot;butter&quot;

Time format functions

Return a string representation of the time, formatted in the local time zone, or in UTC.

Syntax

Function Description
timeFormat(format, str) Returns the date formatted in the local time zone.
timeFormatMS(format, str) Returns the date formatted in the local time zone.
timeFormatUTC(format, str) Returns the date formatted in UTC.
timeFormatUTCMs(format, str) Returns the date formatted in UTC.

Arguments

  • format - A date/time format string. Can be a literal string or a string variable.
  • str - A string or string flow variable containing a time value. The value can be in seconds-since-epoch or milliseconds-since-epoch for timeFormatMs.

Examples

Assume the following values and assume the local timezone is Pacific:

  • epoch_time_ms = 1494390266000
  • epoch_time = 1494390266
  • fmt1 = yyyy-MM-dd
  • fmt2 = yyyy-MM-dd HH-mm-ss
  • fmt3 = yyyyMMddHHmmss

The functions return the following results:

    Function Output
    timeFormatMs(fmt1,epoch_time_ms) 2017-05-09
    timeFormat(fmt1,epoch_time) 2017-05-09
    timeFormat(fmt2,epoch_time) 2017-05-09 21:24:26
    timeFormat(fmt3,epoch_time) 20170509212426
    timeFormatUTC(fmt1,epoch_time) 2017-05-10
    timeFormatUTC(fmt2,epoch_time) 2017-05-10 04:24:26
    timeFormatUTC(fmt3,epoch_time) 20170510042426

    Other functions

    Create UUID function

    Generates and returns a UUID.

    Syntax

    createUuid()
    

    Arguments

    None.

    Example

    {createUuid()}

    Sample result:

    ec3ca9be-d1e1-4ef4-aee4-4a58f3130db8
    

    Random Long Generator function

    Returns a random long integer.

    Syntax

    randomLong(args)
    

    Arguments

    • If no arguments are specified, the function returns a random long integer, as computed by the Java SecureRandom class.
    • If one argument is present, it is treated as the minimum value of the computation.
    • If a second argument is present, it is treated as the maximum value of the computation.

    Example

    {random()}
    

    results in something like this:

    5211338197474042880
    

    Regex text generator

    Generate a text string that matches a given regular expression.

    Syntax

    xeger(regex)
    

    Argument

    regex - A regular expression.

    Example

    This example generates a seven digit string with no zeros:

    xeger( '[1-9]{7}' )
    

    Example result:

    9857253
    

    JSON Path function

    Applies a JSON Path expression to a JSON variable.

    Syntax

    jsonPath(json-path, json-var)
    

    Arguments

    json-path - A JSON Path expression.

    json-var - A flow variable or string containing JSON.

    Example

    If this is the message template:

    The address is {jsonPath($.results[?(@.name == 'Mae West')].address.line1, the_json_variable)}
    

    and the_json_variable contains:

    {
          "results" : [
            {
              "address" : {
                "line1" : "18250 142ND AV NE",
                "city" : "Woodinville",
                "state" : "Washington",
                "zip" : "98072"
              },
              "name" : "Fred Meyer"
            },
            {
              "address" : {
                "line1" : "1060 West Addison Street",
                "city" : "Chicago",
                "state" : "Illinois",
                "zip" : "60613"
              },
              "name" : "Mae West"
            }
          ]
        } 

    The result of the function is:

    The address is 1060 West Addison Street