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:

  1. Request Phase: takes place when a user submits a request to the edge application.
  2. 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.

Edge Application first stepsFirst steps
Creating a ruleCreating rules using Rules Engine for Edge Application
Creating a cache settingHow to configure cache policies for Edge Application
Mitigating HTTPoxy using rulesHow to mitigate the HTTPOxy vulnerability

When creating a rule, you’ll be prompted to select one of the two available processing phases: Request Phase or Response 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.

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.

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.

The Criteria section of Rules Engine is where you define the conditions for executing the rule. Criteria are composed of:

  • variables
  • comparison 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:

VariableComparison operatorArgument

Check the full list of variables available and their processing phase:

${arg_name}Value of the parameter name in the query string of the URL${arg_search} assumes test for /path?search=testRequest
${args}All parameter name and values sent in the query string of the URL${args} assumes Search=test for /path?search=testRequest
${cookie_name}Value of the cookie name${cookie_icl_current_language} assumes pt-br for icl_current_language = pt-brRequest
${device_group}Device group name. You can customize your device groups in the Device Groups tab of your edge applicationMobileRequest
${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 for
${geoip_city}Name of the city, using the geolocation base geoip_citySao PauloRequest
${geoip_city_continent_code}2-letter continent code, using the geolocation base geoip_cityEU for EuropeRequest
${geoip_city_country_code}2-letter country code, using the geolocation base geoip_cityBR for BrazilRequest
${geoip_city_country_name}Name of the country, using the geolocation base geoip_cityUnited StatesRequest
${geoip_continent_code}2-letter continent codeNA for North AmericaRequest
${geoip_country_code}2-letter country code, using the geolocation base geoip_countryRU for RussiaRequest
${geoip_country_name}Name of the country, using the geolocation base geoip_countryBrazilRequest
${geoip_region}2-letter region codeRS for Rio Grande do SulRequest
${geoip_region_name}Name of the region, using the geolocation base geoip_regionOntarioRequest
${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 requestblog.domain.comRequest
${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/apngRequest
${remote_addr}The IP address of the client performing the HTTP request200.10.2.50Request
${remote_port}The HTTP port being used in the request URL of the client443Request
${remote_user}The username provided by basic authentication, if anyusernameRequest
${request}Original first request line of the client request. It’s composed of the request method, the request URI, and the HTTP versionGET /path HTTP/2.0Request
${request_method}The HTTP method of the requestGETRequest
${request_uri}The complete URI of the request, with arguments (query string). Special UTF-8 characters are URL encoded/path?var=value%20of%20varRequest
${scheme}The scheme of the requesthttpsRequest
${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: 9593Response
${server_addr}The IP address of the server that receives the HTTP request200.0.0.0Request
${server_port}The HTTP port of the server that’ll be receiving the request8080Request
${status}Status code of the response200Response
${tcpinfo_rtt}Round-Trip Time (RTT) of the client’s TCP connection, in microseconds24763Response
${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 (:),, :,
${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 = 12345Response
${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: UploadServerResponse
${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
${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.txtRequest

Mutual Transport Layer Security (mTLS) variables

Section titled 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.

${ssl_client_fingerprint}The Secure Hash Algorithm 1 (SHA-1) of the client certificate2fd4e1c67a2d28fced849
${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/
${ssl_client_s_dn_parsed}Returns the extracted subject CN value of the client certificate as a
${ssl_client_cert}This variable is deprecated. Use ${ssl_client_escaped_cert} instead

Returns the client certificate (PEM format)
${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/
${ssl_client_serial}Returns the serial number of the client certificate6C: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 format20230115120000
${ssl_client_v_remain}Returns the number of days until the client certificate expires100
${ssl_client_v_start}Returns the start date of the client certificate20230115120000
${ssl_client_verify} Returns the result of the client certificate verificationSUCCESS
Learn more about support for mTLS

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:

VariableComparison operatorArgument
ThenAdd Response Cookiecookie-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:

Azion also provides special variables that act as functions and take arguments. The following variables can be used to compose Behaviors arguments:

${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 cookieUse 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(} assumes d3d3LmRvbWFpbi5jb20K

OperatorDescriptionArgument type
is equalThe value of the variable is exactly the same as the argumentstring
is not equalThe value of the variable isn’t the same as the argumentstring
starts withThe value of the variable starts with the argumentstring
does not start withThe value of the variable doesn’t start with the argumentstring
matchesThe value of the variable matches the regular expression entered as an argumentregular expression
does not matchThe value of the variable doesn’t match the regular expression entered as an argumentregular expression
existsThe variable has a defined value. Example: ${arg_search} exists if a search parameter was sent in the query string-
does not existThe variable doesn’t have a defined value. Example: ${arg_search} doesn’t exist if a search parameter wasn’t sent in the query string-

Multiple criteria can be defined using the logical operators AND and OR.

The operator AND has implicit precedence over the operator OR. If explicit precedence is required, you can add more criteria groups using the AND operator only.

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:

Redirect To (302 Found)/en-us/faq

Request Phase Response Phase Requires Application Accelerator

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
  • Domain=domain-value
  • Path=path-value
  • Max-age=number (TTL in seconds, takes precedence over Expires)
  • 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}.

Request Phase Response Phase

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.

Request Phase Requires Application Accelerator

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

Section titled 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.

Request Phase Requires Application Accelerator

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>[^/]*)$
Request Phase Response Phase

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.

Request Phase

Delivers a 403 Forbidden page to the user. Ends the request processing.

Request Phase Response Phase

Enables Gzip data compression, if supported by the user’s browser. See the guide on How to enable gzip compression for more information.

Request Phase Requires Live Ingest

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).

Request Phase Response Phase Requires Application Accelerator

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.

Request Phase Response Phase

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.

Request Phase

Finishes the request phase. Any behavior or other rules under this behavior won’t be executed.

Request Phase Requires Application Accelerator

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.

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:

document.cookie = "username=John Doe; expires=Thu, 18 Dec 2020 12:00:00 UTC; path=/";

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.

Request Phase

Returns a 204 code when accessing the edge application instead of the code received from the origin.

Request Phase Requires Image Processor

Enables Image Processor.

Request Phase Requires HTTPS application

Redirects the HTTP request to HTTPS. If the request is already made through HTTPS, the behavior isn’t executed.

Request Phase Response Phase

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.

Request Phase Requires Application Accelerator

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:

  1. Use the Capture Match Groups behavior with the arguments:
  • captured array name: capture
  • subject: ${uri}
  • regex: /original/(.)
  1. Use the Rewrite Request behavior with the argument /new/%{capture[1]}.

Request Phase Response Phase Requires Application Accelerator Requires Edge Functions

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.

Request Phase

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.

Request Phase

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.

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.

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.

These are the default limits:

Criteria per rule5
Behaviors per rule10
Variables per criteria10