> ## Documentation Index
> Fetch the complete documentation index at: https://docs.fingerprint.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Expression language reference

Rule expressions are written using a simple expression language. It provides a rich set of operators and builtin functions, and allows you to create flexible conditions and criteria.

You can use available data fields with available operators and functions.

## **Data fields**

| **Key**                          | **Type**       | **Notes**                                                                                  |
| :------------------------------- | :------------- | :----------------------------------------------------------------------------------------- |
| `http.user_agent.is_ai_bot`      | `bool`         | Whether the UserAgent string matches the criteria for AI Bots.                             |
| `http.user_agent.is_crawler_bot` | `bool`         | Whether the UserAgent string matches the criteria for Crawler Bots.                        |
| `http.user_agent.string`         | `string`       | The full UserAgent string.                                                                 |
| `http.request.headers`           | `http_headers` | The map of HTTP request headers.                                                           |
| `http.request.ip`                | `ip`           | IP address of the client making the request.                                               |
| `sdk.platform.name`              | `string`       | Name of the SDK platform (i.e. one of `js`, `android`, `ios`, `unknown`).                  |
| `sdk.version`                    | `string`       | Version of the SDK platform. Example value: `1.2.3`.                                       |
| `sdk.platform.app_package_name`  | `string`       | Name of the mobile app bundle, if the request came from a mobile SDK (`android` or `ios`). |
| `sdk.platform.is_android`        | `bool`         | Flag indicating if request came from Android device.                                       |
| `sdk.platform.is_browser`        | `bool`         | Flag indicating if request came from a web browser.                                        |
| `sdk.platform.is_ios`            | `bool`         | Flag indicating if request came from iOS device.                                           |
| `sdk.platform.is_unknown`        | `bool`         | Flag indicating if request came from an unknown platform.                                  |

## **Operators**

`LHS` stands for left-hand side of the operation, `RHS` stands for right-hand side of the operation.

### Equality

* `LHS == RHS` - returns `true` if both sides are equal
* `LHS != RHS` - returns `true` if both sides are different

### Numerical

When `LHS` and `RHS`are numerical values.

* `LHS < RHS` - returns `true` if `LHS` is less than `RHS`
* `LHS > RHS` - returns `true` if `LHS` is more than `RHS`
* `LHS <= RHS` - returns `true` if `LHS` is less than or equal to `RHS`
* `LHS >= RHS` - returns `true` if `LHS` is more than or equal to `RHS`

### Logical

When `LHS` and `RHS`are boolean values.

* `!LHS` - returns the opposite boolean value of `LHS`
* `LHS && RHS` - returns `true` if both `LHS` and `RHS` are `true`
* `LHS || RHS` - returns `true` if either `LHS` or `RHS` are `true`

### Strings

When `LHS` and `RHS`are strings.

* `LHS contains RHS` - returns `true` if `RHS` is a contained in `LHS`
* `LHS not contains RHS` - returns `true` if `RHS` is not contained in `LHS`

### RegEx matching

When `LHS` is a string, and `RHS` is a string literal with a [RegEx](https://github.com/google/re2/wiki/Syntax) pattern. Pattern needs to be enclosed with backticks (\`).

* `LHS matches RHS` - returns `true` if `LHS` matches the regular expression in the `RHS`
* `LHS not matches RHS` - returns `true` if `LHS` does not match the regular expression in the `RHS`

### Arrays

When `LHS`is an array.

* `LHS in RHS` - returns `true` whether `LHS` is in (or belongs to) `RHS`
* `LHS not in RHS` - returns the opposite of `LHS in RHS`
* `LHS[RHS]` - returns the value at *numeric* index `RHS` in the array `LHS`, returns `nil` for missing values

### Objects

When `LHS`is an object.

* `LHS in RHS` - returns `true` whether `LHS` is in (or belongs to)
* `RHS`:`LHS not in RHS` - returns the opposite of `LHS in RHS`.
* `LHS[RHS]` - returns the value at string field `RHS` in the object `LHS`. Returns `nil` for missing values
* `LHS.RHS` is equivalent to `LHS[RHS]` where `LHS` is an `object`, and `RHS` is an unquoted `string` literal that can be used as an identifier.

*Examples:*

1. `http.request` is equivalent to `http["request"]`.
2. `http.request.headers.origin.0` produces an error because the unquoted `string` literal `0` cannot be used as an identifier.

## **Functions and custom data types**

Describes additional functions and special data types available during rule evaluation.

### Strings

* `upper(string) -> string` - transforms the string to all uppercase characters
* `lower(string) -> string` - - transforms the string to all lowercase characters
* `starts_with(source string, substring string) -> bool`
* `ends_with(source string, substring string) -> bool`

### HTTP headers

The *Custom Type* `http_headers` behaves similar to an `object`, but it’s keys are normalized to be in MIME Header format in all operations (so usage is case-insensitive), and its values are of type `array` and contain the values for the given header name, preserving the original order.  \
\
*Examples*:

1. Check if a header was set: `"cOnTeNt-TyPe" in http.request.headers`
2. Get the first cookie that was set: `http.request.headers["accept"][0]`

### IP address and CIDR

The *Custom Type* `ip` represents an IPv4 or IPv6 address.

The *Custom Type* `cidr` represents an IPv4 or IPv6 CIDR range.

* `cidr(string) -> cidr` parses an IPv4 or IPv6 CIDR.
  * The `in` operator can be used to check if an `ip` is in a given `cidr`.

*Example*:

1. Check if IP address belongs to a CIDR range: `http.request.ip in cidr("1.1.1.1/10")`

### Semantic versioning

* `semver_is_valid(string) -> bool` - checks if given string is a valid semver string
* `semver_compare(s1, s2) -> int` - compares two semver strings
  * returns `-1` if `s2 < s1`, `1` if `s2 > s1`, or `0` if they are equal
