# Rules Engine for Applications

import DocButton from '~/components/webkit/DocButton.vue';
import Tag from '~/components/webkit/Tag.vue';
import TableContainer from "~/components/Table/TableContainer.astro";
import RulesExecution from '~/includes/snippets/RulesEngineExecution/en/snippet.mdx';

**Rules Engine** is an **Applications** 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](https://console.azion.com/) is processed in a fixed sequence of two phases:

1. **Request Phase**: takes place when a user submits a request to the application.
2. **Response Phase**: occurs when a user receives a response from the 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.

:::caution
Before you create a rule, you should enable the [Application Accelerator](/en/documentation/products/build/applications/application-accelerator/) module, which extends the usability of **Rules Engine** by applying serverless computing features to **Applications**. If the module is disabled, only some variables and behaviors will be available for your rule.
:::

## Implementation

| Scope | Resource |
| --- | --- |
| Applications first steps | [First steps](/en/documentation/products/build/applications/first-steps/) |
| Creating a rule | [Creating rules using Rules Engine for Applications](/en/documentation/products/guides/rules-engine/) |
| Creating a cache setting | [How to configure cache policies for Applications](/en/documentation/products/guides/cache-settings/) |
| Mitigating HTTPoxy using rules | [How to mitigate the HTTPOxy vulnerability](/en/documentation/products/guides/mitigating-a-vulnerability-httpoxy/) |

---

## 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](#variables) and [comparison operators](#comparison-operators) sections below. You can also add [logical operators](#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:

<TableContainer>
| 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<br />Response |
| `${args}` | All parameter name and values sent in the query string of the URL | `${args}` assumes `Search=test` for `/path?search=test` | Request <br />Response |
| `${cookie_name}` | Value of the cookie name | `${cookie_icl_current_language}` assumes `pt-br` for `icl_current_language = pt-br` | Request <br />Response |
| `${device_group}` | Device group name. You can customize your [device groups](/en/documentation/products/build/applications/device-groups/) in the **Device Groups** tab of your application | `Mobile` | Request <br />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 <br />Response |
| `${geoip_city}` | Name of the city, using the geolocation base `geoip_city` | `Sao Paulo` | Request <br />Response |
| `${geoip_city_continent_code}` | 2-letter continent code, using the geolocation base `geoip_city` | `EU` for Europe | Request <br />Response |
| `${geoip_city_country_code}` | 2-letter country code, using the geolocation base `geoip_city` | `BR` for Brazil | Request <br />Response |
| `${geoip_city_country_name}` | Name of the country, using the geolocation base `geoip_city` | `United States` | Request <br />Response |
| `${geoip_continent_code}` | 2-letter continent code | `NA` for North America | Request <br />Response |
| `${geoip_country_code}` | 2-letter country code, using the geolocation base `geoip_country` | `RU` for Russia | Request <br />Response |
| `${geoip_country_name}` | Name of the country, using the geolocation base `geoip_country` | `Brazil` | Request <br />Response |
| `${geoip_region}` | 2-letter region code | `RS` for Rio Grande do Sul | Request <br />Response |
| `${geoip_region_name}` | Name of the region, using the geolocation base `geoip_region` | `Ontario` | Request <br />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 <br />Response |
| `${http_name}` | The value of a request header. `name` must be a valid [HTTP request header](https://developer.mozilla.org/en-US/docs/Glossary/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 <br />Response |
| `${remote_addr}` | The IP address of the client performing the HTTP request | `200.10.2.50` | Request <br />Response |
| `${remote_port}` | The HTTP port being used in the request URL of the client | `443` | Request <br />Response |
| `${remote_user}` | The username provided by basic authentication, if any | `username` | Request <br />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 <br />Response |
| `${request_body}` | The body content of the HTTP request. | `{"name": "azion", "action": "login"}` | Request <br />Response |
| `${request_method}` | The HTTP method of the request | `GET` | Request <br />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 <br />Response |
| `${scheme}` | The scheme of the request | `https` | Request <br />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` <br />`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` <br />`500, 502 : 200, 200` | Response |
| `${uri}` | The normalized (URL decoded) URI of the request. <br /><br />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 <br />Response |
</TableContainer>

### Mutual Transport Layer Security (mTLS) variables

Add these variables inside the **Rules Engine** of your 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}` instead<br /><br />Returns the client certificate (PEM format) | `-----BEGIN CERTIFICATE-----`<br />`MIICnz...`<br />`-----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`<br />`FAILED:reason`<br />`NONE` |

:::tip
Most mTLS services rely on receiving the user certificate. By using [Azion Console](https://console.azion.com), you can send the `${ssl_client_escaped_cert}` variable in the `X-Forward-Client-Cert` (XFCC) header in the request to the origin, and then configure your application to use this header with the certificate data.
:::

<DocButton href="/en/documentation/products/build/applications/domains/mtls/" label="Learn more about support for mTLS" kind="secondary" size="medium" />

### 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](#add-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 | - |

:::note
These operators may vary according to the selected Criteria.
:::

### Logical operators

Multiple criteria can be defined using the logical operators `and` and `or`. 

:::note
The operator `and` has implicit precedence over the operator `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
<Tag severity="info">Request Phase</Tag> <Tag severity="info">Response Phase</Tag>
[<Tag severity="info">Requires Application Accelerator</Tag>](/en/documentation/products/build/applications/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](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie) can be added to the argument, after the cookie value and separated by a semicolon (`;`):

- `Expires=date` (EEE, d MMM yyyy HH:mm:ss Z)
- `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}`.

### Add Header
<Tag severity="info">Request Phase</Tag> <Tag severity="info">Response Phase</Tag>

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

:::tip
The `name` field may contain only letters (a-z, A-Z), numbers (0-9), hyphens (-), and/or underscores (_). Using any other characters will result in an invalid header.
:::

| Header field | Allowed characters                                    |
| ------------ | ----------------------------------------------------- |
| Name         | (a-z, A-Z, 0-9), (-, _ )                              |
| Value        | (a-z, A-Z, 0-9), (\_ :;.,\/"'?!(){}[]@&lt;&gt;=-+*#$&`\|~^%) |

:::caution
The argument value is limited to **1,600 characters**. Exceeding this limit returns an `Argument too long` error.
:::

For example, this would be a valid header:

```bash
example-field: example-value!
```

### Bypass Cache
<Tag severity="info">Request Phase</Tag>
[<Tag severity="info">Requires Application Accelerator</Tag>](/en/documentation/products/build/applications/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](#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.

:::tip
See the guide on [How to configure cache policies for Applications](/en/documentation/products/guides/cache-settings/#bypass-cache) for more information on Bypass Cache.
:::

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

:::tip
You can set TTL to zero if the dynamic content, which varies from time to time, can be delivered identically to all users who make simultaneous requests.
:::

### Capture Match Groups
<Tag severity="info">Request Phase</Tag> <Tag severity="info">Response Phase</Tag>
[<Tag severity="info">Requires Application Accelerator</Tag>](/en/documentation/products/build/applications/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 `?&lt;name&gt;` notation as in the example:

- *captured array name*: `capture`
- *subject*: `${uri}`
- *regex*: `^(?<path>.*/)(?<filename>[^/]*)$`

### Deliver
<Tag severity="info">Request Phase</Tag> <Tag severity="info">Response Phase</Tag>

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)
<Tag severity="info">Request Phase</Tag>

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

### Enable Gzip
<Tag severity="info">Request Phase</Tag> <Tag severity="info">Response Phase</Tag>

Enables Gzip data compression, if supported by the user's browser. See the guide on [How to enable gzip compression](/en/documentation/products/guides/gzip-compression/) for more information.

### Enforce HLS cache
<Tag severity="info">Request Phase</Tag>
<Tag severity="info">Requires Live Ingest</Tag>

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

<DocButton href="/en/documentation/products/guides/enforce-hls-cache/" label="go to enforce HLS cache guide" kind="secondary" size="medium" />

### Filter Cookie
<Tag severity="info">Request Phase</Tag> <Tag severity="info">Response Phase</Tag>
[<Tag severity="info">Requires Application Accelerator</Tag>](/en/documentation/products/build/applications/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`.

### Filter Header
<Tag severity="info">Request Phase</Tag> <Tag severity="info">Response Phase</Tag>

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

:::caution 
The following headers cannot be overwritten nor filtered:
- Host
- Connection
- Range
- X-Forward-For
- Cdn-Loop
:::

### Finish Request Phase
<Tag severity="info">Request Phase</Tag>

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

### Forward Cookies 
<Tag severity="info">Request Phase</Tag>
[<Tag severity="info">Requires Application Accelerator</Tag>](/en/documentation/products/build/applications/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](/en/documentation/products/guides/cache-settings/#creating-a-rule-to-forward-cookies-from-the-origin-to-the-user).

#### 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](https://www.w3schools.com/js/js_cookies.asp) should have the following format:

```js
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.

### No Content (204)
<Tag severity="info">Request Phase</Tag>

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

### Optimize Images
<Tag severity="info">Request Phase</Tag>
[<Tag severity="info">Requires Image Processor</Tag>](/en/documentation/products/build/applications/image-processor/)

Enables [Image Processor](/en/documentation/products/build/applications/image-processor/).

### Redirect HTTP to HTTPS
<Tag severity="info">Request Phase</Tag>
[<Tag severity="info">Requires HTTPS application</Tag>](/en/documentation/products/build/applications/main-settings/)

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

### Redirect To
<Tag severity="info">Request Phase</Tag> <Tag severity="info">Response Phase</Tag>

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

:::caution
In the Response Phase, **Redirect To** behaviors are only executed when the origin returns a 404 error.
:::

### Rewrite Request
<Tag severity="info">Request Phase</Tag>
[<Tag severity="info">Requires Application Accelerator</Tag>](/en/documentation/products/build/applications/application-accelerator/)

Modifies the resource path that will be requested from the origin. You can rewrite the resource path using:

- A string.
- Request 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](#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/(.)`

2. Use the **Rewrite Request** behavior with the argument `/new/%{capture[1]}`.

### Run Function
<Tag severity="info">Request Phase</Tag> <Tag severity="info">Response Phase</Tag>
[<Tag severity="info">Requires Application Accelerator</Tag>](/en/documentation/products/build/applications/application-accelerator/)
[<Tag severity="info">Requires Functions</Tag>](/en/documentation/products/build/applications/functions/)

Runs a function created using **Functions** and instantiated in the **Functions** tab for the application. See the guide on [How to run serverless functions](/en/documentation/products/guides/serverless-functions/) for more information.

### Set Cache Policy 
<Tag severity="info">Request Phase</Tag>

Assigns the cache policy that should be used for the request. You must first set up the cache policies in [Cache Settings](/en/documentation/products/build/applications/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](/en/documentation/products/build/applications/cache-settings/#advanced-cache-key). 

### Set Origin
<Tag severity="info">Request Phase</Tag>

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](/en/documentation/products/build/applications/origins/).

---

## Behaviors execution and logic

<RulesExecution />

---

## Debugging rules

You can [debug rules created with Rules Engine](/en/documentation/products/guides/debug-rules/) created in **Rules Engine for Applications** through the **GraphQL API**, **Data Stream**, or **Real-Time Events**.

---

## Limits

:::tip
**Increase limits** <br></br>
You can request to increase the limits based on your plan. Contact the [technical support team](/en/documentation/services/support/) to request it.
:::

These are the **default limits**:

| Scope | Limits |
| --- | --- |
| Rules (request or response) | 200 |
| Criteria per rule | 5 |
| Behaviors per rule | 10 |
| Variables per criteria | 10 |
| Behavior argument | 1,600 characters |

:::tip
The total limit is 200 rules, distributed between **requests** and **responses**. For example, you can have 150 request rules and 50 response rules.
:::