Skip to main content

CEL Interpolation

CEL Interpolation allows you to write dynamic configurations for traffic policy actions. It enables expressions to be embedded within string fields of a configuration object, making the traffic policy system more flexible and powerful.

When an action in a traffic policy requires a configuration object, some fields allow CEL expressions to be interpolated directly into strings. This means that you can define dynamic values that are computed based on traffic, connection, or previously executed action variables.

For example, when using the add-headers action, the headers field is a key-value map, where the header values can contain CEL expressions. This allows you to use real-time traffic data, such as the client's IP address, to populate header values dynamically.

How CEL Interpolation Works

In the context of traffic policy actions, CEL expressions can be written within strings using a special syntax: ${expression}. This tells the system to evaluate the expression at runtime and replace the placeholder with the resulting value.

For example, consider the following configuration for the add-headers action:

on_http_request:
- name: CEL Interpolation Example
actions:
- type: add-headers
config:
headers:
X-Client-IP: "${conn.client_ip}"
X-Request-Path: "${req.url.path}"

In this example:

  • The header X-Client-IP is set to the value of the client's IP address (conn.client_ip).
  • The header X-Request-Path dynamically reflects the path of the incoming request (req.url.path).

When the rule is executed, the system evaluates the CEL expressions and substitutes the results into the configuration. This allows for highly customizable behavior based on real-time data.

What Can Be Interpolated?

You can use the following inside of CEL interpolated expressions:

This dynamic configuration enables traffic policies to be tailored based on specific conditions at runtime.

Why Use CEL Interpolation?

  • Flexibility: Dynamically adjust action configurations based on traffic, headers, and more.
  • Power: Create complex, context-aware behaviors by utilizing real-time data and previous actions.
  • Efficiency: Avoid having to manually hard-code values or create separate policies for different traffic scenarios.

Example Use Cases

Custom Header Values

Set headers dynamically based on incoming traffic, such as client IP, request path, or even specific action results.

on_http_request:
- name: CEL Interpolation Example
actions:
- type: add-headers
config:
headers:
X-Country-Code: "${conn.geo.country_code}"
X-User-Agent: "${req.headers['User-Agent'][0]}"

Debugging

Take the result of an action and set it as metadata on the event stream log for the request or output the response as a custom response to see the result immediately, kind of like console.log.

on_http_request:
- actions:
- type: "restrict-ips"
config:
enforce: false
ip_policies:
- "ipp_2p2q5Yt85IKQQ7zbpR4XmUpyVIN"
- type: "log"
config:
metadata:
message: "Restrict IPs action would be ${actions.ngrok.restrict_ips.action} for ${conn.client_ip}."
matched_cidr: "${actions.ngrok.restrict_ips.matched_cidr}"
error_code: "${actions.ngrok.restrict_ips.error.code}"
error_message: "${actions.ngrok.restrict_ips.error.message}"
- type: "custom-response"
config:
status_code: 403
content: "Restrict IPs action would be ${actions.ngrok.restrict_ips.action} for ${conn.client_ip}. The matched CIDR is ${actions.ngrok.restrict_ips.matched_cidr}. Your error code is ${actions.ngrok.restrict_ips.error.code} and the error message is the following: ${actions.ngrok.restrict_ips.error.message}"
headers:
content-type: "text/html"