Rules Engine for Edge Application
Rules Engine is an Edge Application feature that handles the conditional execution of behaviors through logical operators. By using Rules Engine, you can build an architecture that provides better performance to your users while consuming fewer resources by processing at the edge.
Each request made to an application built with Azion Azion Console is processed in a fixed sequence of two phases:
- Request Phase: takes place when a user submits a request to the edge application.
- Response Phase: occurs when a user receives a response from the edge application.
At each processing phase, you can define a set of rules to handle the request according to the needs of your application. Once you’ve selected in which of the two phases your rule will be executed, you’ll be able to create a new rule.
Rules are designed to follow a conditional if-then logic. Every rule is composed of Criteria (if) that will define the set of conditions that must be met for the execution of Behaviors (then).
To trigger the intended behaviors for your application, you may employ variables, comparison operators, and logical operators. If the given conditions are met, the behaviors associated with each rule are executed sequentially until all the rules have been processed.
Implementation
Scope | Resource |
---|---|
Edge Application first steps | First steps |
Creating a rule | Creating rules using Rules Engine for Edge Application |
Creating a cache setting | How to configure cache policies for Edge Application |
Mitigating HTTPoxy using rules | How to mitigate the HTTPOxy vulnerability |
Processing phases
When creating a rule, you’ll be prompted to select one of the two available processing phases: Request Phase or Response Phase.
Request Phase
During the Request Phase, the edge handles end-user requests. For Request Phase rules, any variables associated with the data provided by the user in the request can be utilized. However, variables related to the content that will be delivered to the user in this phase aren’t accessible, as the response hasn’t been processed by the application yet.
Additionally, it’s in the Request Phase that you determine how your application will cache the content. If your application doesn’t permit any form of caching, you have the option to define the conditions under which caching should be disregarded.
Response Phase
During the Response Phase, your application delivers data to end-users. All handling processes in this phase are dynamic, and each user’s delivery is performed independently based on their specific requirements.
Name
Each rule must have a unique and easy-to-remember name, allowing you to easily reference and manage it within your system.
Description
Aside from the name of the rule, you can add a description to your rule using the Description field. Your description will be visible from the rule list and can be used to help you identify what the rule does.
Criteria
The Criteria section of Rules Engine is where you define the conditions for executing the rule. Criteria are composed of:
- Variables
- Comparison operators
- Logic operators
- Arguments, when applicable
The inclusion of arguments in a criteria depends on the comparison operators chosen. The format of the arguments is described in the variables and comparison operators sections below. You can also add logical operators to increase the amount of comparisons that the rule will execute.
For example, this criteria identifies whether a user is accessing your application via a desktop web browser using a regular expression as an argument:
Variable | Comparison operator | Argument | |
---|---|---|---|
If | ${http_user_agent} | matches | (Chrome|Mozilla) |
Variables
Check the full list of variables available and their processing phase:
Variable | Description | Example | Phase |
---|---|---|---|
${arg_name} | Value of the parameter name in the query string of the URL | ${arg_search} assumes test for /path?search=test | Request Response |
${args} | All parameter name and values sent in the query string of the URL | ${args} assumes Search=test for /path?search=test | Request Response |
${cookie_name} | Value of the cookie name | ${cookie_icl_current_language} assumes pt-br for icl_current_language = pt-br | Request Response |
${device_group} | Device group name. You can customize your device groups in the Device Groups tab of your edge application | Mobile | Request Response |
${domain} | Similar to the ${host} variable. Stores the host name or the Host header from the request, excluding the last subdomain after the second-level domain | ${domain} assumes blog.domain.com for az.blog.domain.com | Request Response |
${geoip_city} | Name of the city, using the geolocation base geoip_city | Sao Paulo | Request Response |
${geoip_city_continent_code} | 2-letter continent code, using the geolocation base geoip_city | EU for Europe | Request Response |
${geoip_city_country_code} | 2-letter country code, using the geolocation base geoip_city | BR for Brazil | Request Response |
${geoip_city_country_name} | Name of the country, using the geolocation base geoip_city | United States | Request Response |
${geoip_continent_code} | 2-letter continent code | NA for North America | Request Response |
${geoip_country_code} | 2-letter country code, using the geolocation base geoip_country | RU for Russia | Request Response |
${geoip_country_name} | Name of the country, using the geolocation base geoip_country | Brazil | Request Response |
${geoip_region} | 2-letter region code | RS for Rio Grande do Sul | Request Response |
${geoip_region_name} | Name of the region, using the geolocation base geoip_region | Ontario | Request Response |
${host} | In order of precedence: the host name of the request line, or the value of the Host header, or the name of the server serving the request | blog.domain.com | Request Response |
${http_name} | The value of a request header. name must be a valid HTTP request header converted to lowercase; hyphens must be converted to underscore | ${http_accept} assumes image/webp,image/apng for Accept: image/webp,image/apng | Request Response |
${remote_addr} | The IP address of the client performing the HTTP request | 200.10.2.50 | Request Response |
${remote_port} | The HTTP port being used in the request URL of the client | 443 | Request Response |
${remote_user} | The username provided by basic authentication, if any | username | Request Response |
${request} | Original first request line of the client request. It’s composed of the request method, the request URI, and the HTTP version | GET /path HTTP/2.0 | Request Response |
${request_body} | The body content of the HTTP request. | {"name": "azion", "action": "login"} | Request Response |
${request_method} | The HTTP method of the request | GET | Request Response |
${request_uri} | The complete URI of the request, with arguments (query string). Special UTF-8 characters are URL encoded | /path?var=value%20of%20var | Request Response |
${scheme} | The scheme of the request | https | Request Response |
${sent_http_name} | The value of the response header name. The name argument must be converted to lowercase and the hyphens must be converted to underscore (_ ) | ${sent_http_content_length} assumes 9593 for Content-Length: 9593 | Response |
${server_addr} | The IP address of the server that receives the HTTP request | 200.0.0.0 | Request |
${server_port} | The HTTP port of the server that’ll be receiving the request | 8080 | Request |
${status} | Status code of the response | 200 | Response |
${tcpinfo_rtt} | Round-Trip Time (RTT) of the client’s TCP connection, in microseconds | 24763 | Response |
${upstream_addr} | The IP address and port of the queried origin for obtaining the response. If many origins are consulted during the processing of the request, the addresses will be separated by a comma (, ). If an internal redirect from one group of servers to another occurs, initiated by an X-Accel-Redirect or an error page, the addresses of the different groups will be separated by a colon (: ) | 192.168.1.1:80, 192.168.1.2:80 192.168.1.1:80, 192.168.1.2:80 : 192.168.10.1:80, 192.168.10.2:80 | Response |
${upstream_cookie_name} | Value of cookie sent by the origin in the Set-Cookie header. If many origins are consulted while the request is processed, only cookies from the last origin are stored | ${upstream_cookie_uuid} assumes 12345 for Set-Cookie: uuid = 12345 | Response |
${upstream_http_name} | Value of the header sent by the origin. The name argument must be converted to lowercase and the hyphens must be converted to underscore. If many origins are consulted while the request is processed, only headers from the last origin are stored | ${upstream_http_server} assumes UploadServer for Server: UploadServer | Response |
${upstream_status} | Status code of the origin response sent to Azion Console. If many origins are consulted while the request is processed, the status codes will be separated by a comma (, ). If an internal redirect from one group of servers to another is initiated by an X-Accel-Redirect or an error page, the status codes of the different groups will be separated by a colon (: ) | 200, 201 500, 502 : 200, 200 | Response |
${uri} | The normalized (URL decoded) URI of the request. The value of ${uri} can change during the processing of a request, for example, when an internal redirect occurs or when index files are used. For query string parameters and URL encoded characters, use ${request_uri} | /path/my file.txt | Request Response |
Mutual Transport Layer Security (mTLS) variables
Add these variables inside the Rules Engine of your edge application to configure Mutual Transport Layer Security (mTLS). mTLS variables are only available for the Request Phase.
Variable | Description | Example |
---|---|---|
${ssl_client_fingerprint} | The Secure Hash Algorithm 1 (SHA-1) of the client certificate | 2fd4e1c67a2d28fced849 |
${ssl_client_escaped_cert} | The client certificate in Private Enhanced Mail (PEM) formatted as an URL encoded string | -----BEGIN%20CERTIFICATE-----%0AMIICnz...%0A-----END%20CERTIFICATE----- |
${ssl_client_s_dn} | Returns the subject DN string of the client certificate as a string | /C=US/ST=California/L=San Francisco/O=Example CA/CN=example.com |
${ssl_client_s_dn_parsed} | Returns the extracted subject CN value of the client certificate as a string | example.com |
${ssl_client_cert} | This variable is deprecated. Use ${ssl_client_escaped_cert} insteadReturns the client certificate (PEM format) | -----BEGIN CERTIFICATE----- MIICnz... -----END CERTIFICATE----- |
${ssl_client_i_dn} | Returns the issuer DN string of the client certificate as a string | /C=US/ST=California/L=San Francisco/O=Example CA/CN=issuer.com |
${ssl_client_serial} | Returns the serial number of the client certificate | 6C:0A:83:7E:92:3B:D6:C6:E3:56:50:E7 |
${ssl_client_v_end} | Returns the end date (expiration date) of the client certificate in YYYYMMDDHHmmSS format | 20230115120000 |
${ssl_client_v_remain} | Returns the number of days until the client certificate expires | 100 |
${ssl_client_v_start} | Returns the start date of the client certificate | 20230115120000 |
${ssl_client_verify} | Returns the result of the client certificate verification | SUCCESS FAILED:reason NONE |
Variables as arguments
For behaviors that require an argument, you can use the same variables available for the processing phase. This way, you can, for example, compose request cookies or HTTP headers using data collected during the request phase, such as the user’s device group or their geolocation.
For example, for the following rule in the Response Phase:
Variable | Comparison operator | Argument | |
---|---|---|---|
If | ${host} | is equal | host.com |
Behavior | Argument | |
---|---|---|
Then | Add Response Cookie | cookie-host-value=${host} |
When this rule is active, if the request is made from the host determined in the criteria, the response will return the following header: Set-Cookie: cookie-host-value=host.com
.
Azion also provides special variables that act as functions and take arguments. The following variables can be used to compose Behaviors arguments:
Variable | Description | Example |
---|---|---|
${cookie_time_offset(number)} | Returns the current date plus an offset in seconds, entered as an argument, to be used to define the expiration time of a cookie | Use the Add Response Cookie behavior with the argument cookie-name=cookie-value; Expires=${cookie_time_offset(3600)} to set the cookie TTL to 1 hour from the time it’s created |
${encode_base64(string)} | Returns the arguments coded in base64 | ${encode_base64(http://www.yourdomain.com/)} assumes d3d3LmRvbWFpbi5jb20K |
Comparison operators
Operator | Description | Argument type |
---|---|---|
is equal | The value of the variable is exactly the same as the argument | string |
is not equal | The value of the variable isn’t the same as the argument | string |
starts with | The value of the variable starts with the argument | string |
does not start with | The value of the variable doesn’t start with the argument | string |
matches | The value of the variable matches the regular expression entered as an argument | regular expression |
does not match | The value of the variable doesn’t match the regular expression entered as an argument | regular expression |
exists | The variable has a defined value. Example: ${arg_search} exists if a search parameter was sent in the query string | - |
does not exist | The variable doesn’t have a defined value. Example: ${arg_search} doesn’t exist if a search parameter wasn’t sent in the query string | - |
Logical operators
Multiple criteria can be defined using the logical operators and
and or
.
If explicit precedence is required, you can add multiple criteria groups under the and
logic.
Behaviors
In the Behaviors section of the Rules Engine, you must add the behaviors you want your rule to perform if the conditions defined in the criteria are met.
For example, this behavior redirects the user to an English version of an FAQ location:
Behavior | Argument |
---|---|
Redirect To (302 Found) | /en-us/faq |
Add Cookie
Allows you to add a cookie in the Set-Cookie
HTTP header. The cookie must be inputted as an argument in the format cookie-name=cookie-value
. You may use a variable as a cookie value in the format cookie-name=${arg_cookie}
.
For cookies in the Response Phase, the following Set-Cookie policies can be added to the argument, after the cookie value and separated by a semicolon (;
):
Expires=date
(EEE, d MMM yyyy HH:mm Z)Domain=domain-value
Path=path-value
Max-age=number
(TTL in seconds, takes precedence overExpires
)SameSite=value; Secure
HttpOnly
Multiple policies for the same cookie can be separated by semicolons (;
). For example: cookie-name=cookie-value; Domain=domain-value; Path=path-value; SameSite=value
.
You may also use variables as a cookie or policy value, for example: Path=${uri}; Domain=${host}
.
Add Header
Adds a header field to the request that will be sent to the origin or to the response that will be sent to the user.
The header field must be informed as an argument in the format Field: value
.
Bypass Cache
Defines that Azion shouldn’t cache the response from its origin. The execution of this rule has no impact on the cache in the users’ browser, which must be defined using the Set Cache Policy behavior.
By using Bypass Cache, you’ll configure Azion’s service to forward all requests to a path directly to their origin. However, you’ll count on important protocol optimizations to speed up your application and a keepalive connection between Azion edge nodes and their origin whenever possible.
Difference between Bypass Cache and TTL 0
While both the Bypass Cache behavior and Maximum TTL at zero seconds allow you to optimize content delivery and reduce load times at the origin, their effects are a bit different.
By using the Bypass Cache behavior, all HTTP and HTTPS requests received by Azion’s edge nodes will be sent to the origin, without caching any content. Use Bypass Cache if you want to deliver different content for each user request.
However, when setting TTL to 0 (zero) seconds, multiple requests in parallel to Azion’s edge nodes will be sent as a single request to their origin. In this case, Azion’s edge nodes also validate changes to the content with its origin by using the If-Modified-Since parameter. If the object hasn’t changed since the last request, the content won’t need to be transferred again, which could result in a much faster 304 Not Modified response. Also, setting maximum cache TTL to 0 will still generate a cache object that lives for 999 milliseconds.
Capture Match Groups
Support behavior for handling strings. Stores in a temporary variable the result of capturing correspondence groups defined by a regex applied to one of the available HTTP request fields. This temporary variable can be referenced later in the behavior Rewrite Request to assemble the rewrite string.
This behavior requires three arguments:
- captured array name: the name you want to give to the temporary variable where the array of captured strings will be stored.
- subject: the HTTP request field where you want to capture a string.
- regex: the regular expression used to capture the strings. Each captured group must be represented in parentheses.
For example, to capture the path and name of a file in an HTTP request, you could use:
- captured array name:
capture
- subject:
${uri}
- regex:
^(./)([^/])$
You may reference the capture variable as an array by using the notation %{variable[index]}
. Because it’s a local variable, you can only use it within the same rule you are setting up. In this example, if the URI is /path/image.jpg
, the capture variable will have the following values:
%{capture[0]} = "/path/image.jpg"
%{capture[1]} = "/path/"
%{capture[2]} = "image.jpg"
You can also name the indexes to reference them using names instead of a numeric index. To do so, use the ?<name>
notation as in the example:
- captured array name:
capture
- subject:
${uri}
- regex:
^(?<path>.*/)(?<filename>[^/]*)$
Deliver
Finishes processing the request and delivers the content to the user, without executing any of the rules added later. You’re forcing the processing to end immediately.
Deny (403 Forbidden)
Delivers a 403 Forbidden page to the user. Ends the request processing.
Enable Gzip
Enables Gzip data compression, if supported by the user’s browser. See the guide on How to enable gzip compression for more information.
Enforce HLS cache
This behavior is automatically included by Azion every time you select a Live Ingest source. Two actions are performed in this situation: the bypass of all your Cache Phase rules and the imposition of the cache policy defined by Azion for live transmissions in HLS.
Azion’s cache policy for live HLS streams is 5 seconds of cache for playlists (.m3u8
) and 60 seconds of cache for chunks (.ts
).
Filter Cookie
Removes a cookie from the request header that would be sent to the origin or from the response header that would be sent to the user. As an argument, add the name of the cookie you want to remove as cookie-name
.
To remove only specific values, you must inform the name and value of the cookie as cookie-name=cookie-value
.
Filter Header
Removes a request header that would be sent to the origin or a response header that would be sent to the user. The name of the header field must be entered as an argument, for example: Header-Name
.
Finish Request Phase
Finishes the request phase. Any behavior or other rules under this behavior won’t be executed.
Forward Cookies
By using the Forward Cookies behavior, you’re determining that Azion forwards to its users the Set-Cookie
header received from its origin, even when cached content is identified (HIT).
To prevent a user from receiving the Set-Cookie
header from another user’s session, see the guide on cache policies.
JavaScript Cookies
An alternative to sending the response header Set-Cookie
is to create cookies using JavaScript, which allows you to create, read, and expire cookies through the document.cookie
property.
A JavaScript cookie should have the following format:
By default, Azion won’t filter the request header Cookie
regardless of its Forward Cookies configuration and therefore JavaScript Cookies may be sent to the origin to enable the management of your application.
No Content (204)
Returns a 204
code when accessing the edge application instead of the code received from the origin.
Optimize Images
Enables Image Processor.
Redirect HTTP to HTTPS
Redirects the HTTP request to HTTPS. If the request is already made through HTTPS, the behavior isn’t executed.
Redirect To
Redirect to (301 Moved Permanently) and Redirect To (302 Found) redirect the user to the URL or URI entered as an argument, returning the corresponding status code.
It’s recommended using these behaviors for path changes; 301 Moved Permanently for permanent changes and 302 Found for temporary changes.
Both behaviors end the request processing phase.
Rewrite Request
Modifies the resource path that will be requested for the origin. You can rewrite the resource path using:
- A string.
- The requisition variables (which can also be used in Criteria).
- The local variables, in the format
%{name [index]}
, with the result of capturing strings, when using the auxiliary behavior Capture Match Groups.
For example, to rewrite a user request for the /original/image.jpg
resource to be sent to its origin as /new/image.jpg
:
- Use the Capture Match Groups behavior with the arguments:
- captured array name:
capture
- subject:
${uri}
- regex:
/original/(.)
- Use the Rewrite Request behavior with the argument
/new/%{capture[1]}
.
Run Function
Runs a function created using Edge Functions and instantiated in the Edge Functions tab for the edge application. See the guide on How to run serverless functions for more information.
Set Cache Policy
Assigns the cache policy that should be used for the request. You must first set up the cache policies in Cache Settings.
You can set up the time that an object will be stored in cache and the rules for the variation of objects in cache with the Advanced Cache Key.
Set Origin
Assigns an origin that must be consulted by the edge node for the request.
Before configuring this behavior, you must set up your origins using Origins.
Behaviors execution and logic
While behaviors and rules are executed in the order they’re arranged, some behaviors can’t be stacked.
If a behavior of the type Set, such as Set Custom Response in Edge Firewall and Set Origin in Edge Application, is added multiple times to the rules in Rules Engine, only the last behavior from the last rule in which the criteria was met will be executed.
Behaviors of the type Add are cumulative and can be added multiple times to rules. This means that if Add Cookie and Add Header are executed multiple times for the same key-value pairs, multiple identical entries will be added.
However, for unique headers such as Host
, the last behavior of type Add Header that is executed will overwrite the previous value, since there can’t be more than one Host
header in a request.
Some behaviors, such as Deny, can finish the execution of rules. If a sequence of rules includes such behavior, any rules or behaviors that follow this type of finalizing behavior won’t be executed.
Debugging rules
You can debug rules created with Rules Engine created in Rules Engine for Edge Application through the GraphQL API, Data Stream, or Real-Time Events.
Limits
These are the default limits:
Scope | Limits |
---|---|
Criteria per rule | 5 |
Behaviors per rule | 10 |
Variables per criteria | 10 |