---
title: Functions
description: Functions available for transforming values in rule expressions.
image: https://developers.cloudflare.com/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/ruleset-engine/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Functions

The Cloudflare Rules language provides functions for manipulating and validating values in an expression:

* [Transformation functions](#transformation-functions) manipulate values extracted from an HTTP request.
* The [HMAC validation function](#hmac-validation) tests the validity of an HMAC token. Use it to write expressions that target requests based on the presence of a valid HMAC token.

## Transformation functions

The Rules language supports several functions that transform values extracted from HTTP requests. A common use case for transformation functions is the conversion of a string of characters to uppercase or lowercase, since by default, string evaluation is case-sensitive.

For example, the `lower()` function converts all uppercase characters in a string to lowercase.

In the expression below, the `lower()` function transforms `http.host` values to lowercase so that they match the target value `"www.cloudflare.com"`:

```

lower(http.host) == "www.cloudflare.com"


```

Transformation functions that do not take arrays as an argument type require the `[*]` index notation. Refer to [Arrays](https://developers.cloudflare.com/ruleset-engine/rules-language/values/#arrays) for more information.

The Rules language supports these transformation functions:

### `any`

`` any(` Array<Boolean> `) ``: ` Boolean `

Returns `true` when the comparison operator in the argument returns `true` for _any_ of the values in the argument array. Returns `false` otherwise.

Example:

```

any(url_decode(http.request.body.form.values[*])[*] contains "an xss attack")


```

### `all`

`` all(` Array<Boolean> `) ``: ` Boolean `

Returns `true` when the comparison operator in the argument returns `true` for _all_ values in the argument array. Returns `false` otherwise.

Example:

```

all(http.request.headers["content-type"][*] == "application/json")


```

### `encode_base64`

`` encode_base64(input ` String | Bytes ` [, flags ` String `]) ``: ` String `

Encodes an `input` string or byte array to Base64 format.

The `flags` parameter is optional. You can provide one or more flags as a single string. The available flags are the following:

* `u`: Uses URL-safe Base64 encoding (uses `-` and `_` instead of `+` and `/`).
* `p`: Adds padding (appends `=` characters to make the output length a multiple of 4, as required by some systems).

By default, the output uses standard Base64 encoding without padding.

Examples:

```

encode_base64("hello world")          will return "aGVsbG8gd29ybGQ"

encode_base64("hello world", "p")     will return "aGVsbG8gd29ybGQ="

encode_base64("hello world", "u")     will return "aGVsbG8gd29ybGQ"

encode_base64("hello world", "up")    will return "aGVsbG8gd29ybGQ="


```

You can combine `encode_base64()` with other functions to create signed request headers:

```

encode_base64(sha256(concat(to_string(ip.src), http.host, "my-secret")))


```

Note

You can only use the `encode_base64()` function in [request/response header transform rules](https://developers.cloudflare.com/rules/transform/).

### `cidr`

`` cidr(address ` IP address `, ipv4_network_bits ` Integer `, ipv6_network_bits ` Integer `) ``: ` IP address `

Returns the network address corresponding to an IP address (IPv4 or IPv6), given the provided IPv4 and IPv6 network bits (which determine the corresponding netmasks).

The `address` parameter must be a field, that is, it cannot be a literal String.

The `ipv4_network_bits` value must be between 1 and 32, and the `ipv6_network_bits` value must be between 1 and 128.

Examples:

* If `ip.src` is `113.10.0.2`, `cidr(ip.src, 24, 24)` will return `113.10.0.0`.
* If `ip.src` is `2001:0000:130F:0000:0000:09C0:876A:130B`, `cidr(ip.src, 24, 24)` will return `2001:0000:0000:0000:0000:0000:0000:0000`.

Note

You can only use the `cidr()` function in [custom rules](https://developers.cloudflare.com/waf/custom-rules/) and [rate limiting rules](https://developers.cloudflare.com/waf/rate-limiting-rules/).

### `cidr6`

`` cidr6(address ` IP address `, ipv6_network_bits ` Integer `) ``: ` IP address `

Returns the IPv6 network address corresponding to an IPv6 address, given the provided network bits (which determine the netmask). If you provide an IPv4 address in the first parameter, it will be returned unchanged.

The `address` parameter must be a field, that is, it cannot be a literal String.

The `ipv6_network_bits` value must be between 1 and 128.

This function is equivalent to: `cidr(<address>, 32, <ipv6_network_bits>)`.

Examples:

* If `ip.src` is `2001:0000:130F:0000:0000:09C0:876A:130B`, `cidr6(ip.src, 24)` will return `2001:0000:0000:0000:0000:0000:0000:0000`.
* If `ip.src` is `113.10.0.2`, `cidr6(ip.src, 24)` will return `113.10.0.2` (unchanged).

Note

You can only use the `cidr6()` function in [custom rules](https://developers.cloudflare.com/waf/custom-rules/) and [rate limiting rules](https://developers.cloudflare.com/waf/rate-limiting-rules/).

### `concat`

`` concat(` String | Bytes | Array `) ``: ` String | Array `

Takes a comma-separated list of values. Concatenates the argument values into a single String or array.

The return type depends on the type of input arguments. For example, if you concatenate arrays, the function will return an array.

For example, `concat("String1", " ", "String", "2")` will return `"String1 String2"`.

### `decode_base64`

`` decode_base64(source ` String `) ``: ` String `

Decodes a Base64-encoded String specified in `source`.

`source` must be a field, that is, it cannot be a literal String.

For example, with the following HTTP request header: `client_id: MTIzYWJj`, `(any(decode_base64(http.request.headers["client_id"][*])[*] eq "123abc"))` would return `true`.

Note

You can only use the `decode_base64()` function in [Transform Rules](https://developers.cloudflare.com/rules/transform/), [custom rules](https://developers.cloudflare.com/waf/custom-rules/), and [rate limiting rules](https://developers.cloudflare.com/waf/rate-limiting-rules/).

### `ends_with`

`` ends_with(source ` String `, substring ` String `) ``: ` Boolean `

Returns `true` when the source ends with a given substring. Returns `false` otherwise. The source cannot be a literal value (like `"foo"`).

For example, if `http.request.uri.path` is `"/welcome.html"`, then `ends_with(http.request.uri.path, ".html")` will return `true`.

### `join`

`` join(items ` Array<String> `, separator ` String `) ``: ` String `

Returns a string which is the concatenation of the strings in `items` with the `separator` between each item.

If any of the arguments is nil, the returned value will be nil.  
If the `items` array is empty, the returned value will be an empty string.  
If the `items` array contains a single item, then no concatenation occurs and the (single) item will be returned as is.

This function does the opposite of the [split()](#split) function.

Example:

```

# Joins all HTTP request header names into a single string, with names separated by commas

join(http.request.headers.names, ",")


```

Note

The `join()` function is only available in [Transform Rules](https://developers.cloudflare.com/rules/transform/), [custom rules](https://developers.cloudflare.com/waf/custom-rules/), and [Custom Error Rules](https://developers.cloudflare.com/rules/custom-errors/#custom-error-rules).

### `has_key`

`` has_key(map: ` Map<T> `, key: ` String `) ``: ` Boolean `

Returns true if the `key` specified in the second argument, which can be a literal or a dynamic string, is an existing key in the `map` provided as first argument; returns false otherwise.

The data type of the values in `map` (indicated by `T`) can be any type.

If any of the arguments is nil, the returned value will be nil.

Examples:

```

# Check if an HTTP request header exists:

has_key(http.request.headers, "x-my-header")


# Check if a request header exists based on the name of the first query argument:

has_key(http.request.headers, lower(http.request.uri.args.names[0]))


```

### `has_value`

`` has_value(collection: ` Map<T> | Array<T> `, value: ` T `) ``: ` Boolean `

Returns true if the `value` specified in the second argument, which can be a literal or a dynamic value, is found in the `collection` provided as first argument; returns false otherwise.

The data type of the values in the `collection` (indicated by `T`) must match the data type of the provided `value`. Additionally, `T` must be a primitive data type, that is, it must be one of `Boolean`, `Integer`, `String`, `Bytes`, or `IP address`.

If any of the arguments is nil, the returned value will be nil.

Examples:

```

# Check if there is an HTTP request header with the exact name 'X-My-Header'

has_value(http.request.headers.names, "X-My-Header")


# Check if there is a request header with the exact name provided as the first query argument:

has_value(http.request.headers.names, http.request.uri.args.names[0])


```

### `is_jwt_present`

`` is_jwt_present(token_configuration_id: ` String `) ``: ` Boolean `

Returns true if the request has a token as configured in the token configuration with the ID `token_configuration_id`.

`token_configuration_id` must be the ID of an existing [token configuration](https://developers.cloudflare.com/api-shield/security/jwt-validation/api/#token-configurations).

Example:

```

is_jwt_present("51231d16-01f1-48e3-93f8-91c99e81288e")


```

Note

This function is only available in [API JWT validation rules](https://developers.cloudflare.com/api-shield/security/jwt-validation/).

### `is_jwt_valid`

`` is_jwt_valid(token_configuration_id: ` String `) ``: ` Boolean `

Returns true if the request has a valid token according to the token configuration with the ID `token_configuration_id`.

`token_configuration_id` must be the ID of an existing [token configuration](https://developers.cloudflare.com/api-shield/security/jwt-validation/api/#token-configurations). The function returns false if the token is missing from the request.

```

is_jwt_valid("51231d16-01f1-48e3-93f8-91c99e81288e")


```

Note

This function is only available in [API JWT validation rules](https://developers.cloudflare.com/api-shield/security/jwt-validation/).

### `len`

`` len(` String | Bytes | Array `) ``: ` Integer `

Returns the byte length of a String or Bytes value, or the number of elements in an array.

For example, if the value of `http.host` is `"example.com"`, then `len(http.host)` will return `11`.

### `lookup_json_integer`

`` lookup_json_integer(field ` String `, key ` String | Integer `, key ` String | Integer ` optional, ...) ``: ` Integer `

Returns the integer value associated with the supplied `key` in `field`.

The `field` must be a string representation of a valid JSON document.

The `key` can be an attribute name, a zero-based position number in a JSON array, or a combination of these two options (as extra function parameters), while following the hierarchy of the JSON document to obtain a specific integer value.  

Note: This function only works for plain integers. For example, it will not work for floating numbers with a zero decimal part such as `42.0`.

Examples:

* Given the following JSON object contained in the `http.request.body.raw` field:  
`{ "record_id": "aed53a", "version": 2 }`  
Then `lookup_json_integer(http.request.body.raw, "version")` will return `2`.
* Given the following nested object:  
`{ "product": { "id": 356 } }`  
Then `lookup_json_integer(http.request.body.raw, "product", "id")` will return `356`.
* Given the following JSON array at the root level:  
`["first_item", -234]`  
Then `lookup_json_integer(http.request.body.raw, 1)` will return `-234`.
* Given the following array in a JSON object attribute:  
`{ "network_ids": [123, 456] }`  
Then `lookup_json_integer(http.request.body.raw, "network_ids", 0)` will return `123`.
* Given the following root-level array of JSON objects:  
`[{ "product_id": 123 }, { "product_id": 456 }]`  
Then `lookup_json_integer(http.request.body.raw, 1, "product_id")` will return `456`.

### `lookup_json_string`

`` lookup_json_string(field ` String `, key ` String | Integer `, key ` String | Integer ` optional, ...) ``: ` String `

Returns the string value associated with the supplied `key` in `field`.

The `field` must be a string representation of a valid JSON document.

The `key` can be an attribute name, a zero-based position number in a JSON array, or a combination of these two options (as extra function parameters), while following the hierarchy of the JSON document to obtain a specific value.

Examples:

* Given the following JSON object contained in the `http.request.body.raw` field:  
`{ "company": "cloudflare", "product": "rulesets" }`  
Then `lookup_json_string(http.request.body.raw, "company") == "cloudflare"` will return `true`.
* Given the following nested object:  
`{ "network": { "name": "cloudflare" } }`  
Then `lookup_json_string(http.request.body.raw, "network", "name") == "cloudflare"` will return `true`.
* Given the following JSON array at the root level:  
`["other_company", "cloudflare"]`  
Then `lookup_json_string(http.request.body.raw, 1) == "cloudflare"` will return `true`.
* Given the following array in a JSON object attribute:  
`{ "networks": ["other_company", "cloudflare"] }`  
Then `lookup_json_string(http.request.body.raw, "networks", 1) == "cloudflare"` will return `true`.
* Given the following root-level array of JSON objects:  
`[{ "network": "other_company" }, { "network": "cloudflare" }]`  
Then `lookup_json_string(http.request.body.raw, 1, "network") == "cloudflare"` will return `true`.

### `lower`

`` lower(` String `) ``: ` String `

Converts a string field to lowercase. Only uppercase ASCII bytes are converted. All other bytes are unaffected.

For example, if `http.host` is `"WWW.cloudflare.com"`, then `lower(http.host) == "www.cloudflare.com"` will return `true`.

### `regex_replace`

`` regex_replace(source ` String `, regular_expression ` String `, replacement ` String `) ``: ` String `

Replaces a part of a source string matched by a regular expression with a replacement string, returning the result. The replacement string can contain references to regular expression capture groups (for example, `${1}` and `${2}`), up to eight replacement references.

Examples:

* Literal match replace:  
`regex_replace("/foo/bar", "/bar$", "/baz") == "/foo/baz"`
* If there is no match, the input string does not change:  
`regex_replace("/x", "^/y$", "/mumble") == "/x"`
* Match is case-sensitive by default:  
`regex_replace("/foo", "^/FOO$", "/x") == "/foo"`
* When there are multiple matches, only one replacement occurs (the first one):  
`regex_replace("/a/a", "/a", "/b") == "/b/a"`
* Escape a `$` in the replacement string by prefixing it with another `$`:  
`regex_replace("/b", "^/b$", "/b$$") == "/b$"`
* Replace with capture groups:  
`regex_replace("/foo/a/path", "^/foo/([^/]*)/(.*)$", "/bar/${2}/${1}") == "/bar/path/a/"`

Create capture groups by putting part of the regular expression in parentheses. Then, reference a capture group using `${<NUMBER>}` in the replacement string, where `<NUMBER>` is the number of the capture group.

You can only use the `regex_replace()` function once in an expression, and you cannot nest it with the [wildcard\_replace()](https://developers.cloudflare.com/ruleset-engine/rules-language/functions/#wildcard%5Freplace) function.

Note

Currently, the `regex_replace()` function is only available in rewrite expressions of [Transform Rules](https://developers.cloudflare.com/rules/transform/) and target URL expressions of [dynamic URL redirects](https://developers.cloudflare.com/rules/url-forwarding/single-redirects/).

### `remove_bytes`

`` remove_bytes(` Bytes `) ``: ` Bytes `

Returns a new byte array with all the occurrences of the given bytes removed.

For example, if `http.host` is `"www.cloudflare.com"`, then `remove_bytes(http.host, "\x2e\x77")` will return `"cloudflarecom"`.

### `remove_query_args`

`` remove_query_args(field ` String `, query_param1 ` String `, query_param2 ` String `, ...) ``: ` String `

Removes one or more query string parameters from a URI query string. Returns a string without the specified parameters.

The `field` must be one of the following:

* `http.request.uri.query`
* `raw.http.request.uri.query`

The `field` cannot be a literal value such as `"search=foo&order=asc"`.

The `remove_query_args()` function will remove all specified parameters (as `query_param1`, `query_param2`, etc.) , including repeated occurrences of the same parameter.

The ordering of unaffected query parameters will be preserved.

Examples:

```

// If http.request.uri.query is "order=asc&country=GB":


remove_query_args(http.request.uri.query, "country")  will return "order=asc"

remove_query_args(http.request.uri.query, "order")    will return "country=GB"

remove_query_args(http.request.uri.query, "search")   will return "order=asc&country=GB" (unchanged)


// If http.request.uri.query is "category=Foo&order=desc&category=Bar":


remove_query_args(http.request.uri.query, "order")    will return "category=Foo&category=Bar"

remove_query_args(http.request.uri.query, "category") will return "order=desc"


```

Note

You can only use the `remove_query_args()` function in [rewrite expressions of Transform Rules](https://developers.cloudflare.com/rules/transform/).

### `sha256`

`` sha256(input ` String | Bytes `) ``: ` Bytes `

Computes the SHA-256 cryptographic hash of the `input` string or byte array. Returns a 32-byte hash value.

Use this function to generate signed request headers, validate request integrity, or create secure tokens directly in rule expressions.

Examples:

```

sha256("my-token")


```

The example above returns a 32-byte hash that your origin can validate to authenticate requests.

You can combine `sha256()` with [encode\_base64()](#encode%5Fbase64) to create Base64-encoded signatures:

```

encode_base64(sha256("my-token"))


```

To create a signed header value from request attributes:

```

encode_base64(sha256(concat(to_string(ip.src), to_string(http.request.timestamp.sec), "my-secret-key")))


```

Notes

The `sha256()` function is available as an Enterprise add-on and requires a specific entitlement. Contact your account team to enable it.

You can only use the `sha256()` function in rewrite expressions of [Transform Rules](https://developers.cloudflare.com/rules/transform/).

### `split`

`` split(input ` String `, separator ` String `, limit ` Integer `) ``: ` Array<String> `

Splits the `input` string into an array of strings by breaking the initial string at every occurrence of the `separator` string. The returned array will contain at most `limit` number of elements.

If you provide a `limit` value lower than the actual number of substrings in the split string, the last element of the returned array will contain the remainder of the string.

The `separator` must be a non-empty literal string.

The `limit` is mandatory, and it must be a literal integer between 1 and 128.

If `input` is nil, the returned value will be nil.

This function does the opposite of the [join()](#join) function.

Examples:

```

# Split a comma-separated list of categories obtained from an HTTP request header.


# A) Consider the following HTTP request header:

x-categories: groceries,electronics,diy,auto


split(http.request.headers["x-categories"][0], ",", 64)  will return ["groceries", "electronics", "diy", "auto"]

split(http.request.headers["x-categories"][0], ",", 3)   will return ["groceries", "electronics", "diy,auto"]


# B) Consider the following HTTP request header:

x-categories: groceries,,electronics


split(http.request.headers["x-categories"][0], ",", 64)  will return ["groceries", "", "electronics"]


```

Note

The `split()` function is only available in [response header transform rules](https://developers.cloudflare.com/rules/transform/response-header-modification/) and [Custom Error Rules](https://developers.cloudflare.com/rules/custom-errors/#custom-error-rules).

### `starts_with`

`` starts_with(source ` String `, substring ` String `) ``: ` Boolean `

Returns `true` when the source starts with a given substring. Returns `false` otherwise. The source cannot be a literal value (like `"foo"`).

For example, if `http.request.uri.path` is `"/blog/first-post"`, then `starts_with(http.request.uri.path, "/blog")` will return `true`.

### `substring`

`` substring(field ` String | Bytes `, start ` Integer `, end ` Integer ` optional) ``: ` String `

Returns part of the `field` value (the value of a String or Bytes [field](https://developers.cloudflare.com/ruleset-engine/rules-language/fields/reference/)) from the `start` byte index up to (but excluding) the `end` byte index. The first byte in `field` has index `0`. If you do not provide the optional `end` index, the function returns the part of the string from `start` index to the end of the string.

The `start` and `end` indexes can be negative integer values, which allows you to access characters from the end of the string instead of the beginning.

Examples:

```

// If http.request.body.raw is "asdfghjk":


substring(http.request.body.raw, 2, 5)   will return "dfg"

substring(http.request.body.raw, 2)      will return "dfghjk"

substring(http.request.body.raw, -2)     will return "jk"

substring(http.request.body.raw, 0, -2)  will return "asdfgh"


```

### `to_string`

`` to_string(` Integer | Boolean | IP address `) ``: ` String `

Returns the string representation of an Integer, Boolean, or IP address value.

Examples:

```

// If cf.bot_management.score is 5:

to_string(cf.bot_management.score)   will return "5"


// If ssl is true:

to_string(ssl)                       will return "true"


```

Note

You can only use the `to_string()` function in rewrite expressions of [Transform Rules](https://developers.cloudflare.com/rules/transform/) and target URL expressions of [dynamic URL redirects](https://developers.cloudflare.com/rules/url-forwarding/single-redirects/).

### `upper`

`` upper(` String `) ``: ` String `

Converts a string field to uppercase. Only lowercase ASCII bytes are converted. All other bytes are unaffected.

For example, if `http.host` is`"www.cloudflare.com"`, then `upper(http.host)` will return `"WWW.CLOUDFLARE.COM"`.

### `url_decode`

`` url_decode(source ` String `, options ` String ` optional) ``: ` String `

Decodes a URL-formatted string defined in `source`, as in the following:

* `%20` and `+` decode to a space character (` `).
* `%E4%BD` decodes to `ä½`.

The `source` must be a field, that is, it cannot be a literal string.

The `options` parameter is optional. You must provide any options as a single string wrapped in quotes, such as `"r"` or `"ur"`. The available options are the following:

* `r`: Applies recursive decoding. For example, `%2520` will be decoded twice (recursively) to a space character (` `).
* `u`: Enables Unicode percent decoding. The result will be encoded in UTF-8\. For example, `"%u2601"` would be decoded to a cloud emoji (`☁️`) encoded in UTF-8 (`"\xe2\x98\x81"`, with a size of 3 bytes).

Examples:

```

url_decode("John%20Doe")   will return "John Doe"

url_decode("John+Doe")     will return "John Doe"

url_decode("%2520")        will return "%20"

url_decode("%2520", "r")   will return " "


// Using url_decode() with the any() function:

any(url_decode(http.request.body.form.values[*])[*] contains "an xss attack")


// Using the u option to match a specific alphabet

url_decode(http.request.uri.path) matches "(?u)\p{Hangul}+"


```

### `uuidv4`

`` uuidv4(source ` Bytes `) ``: ` String `

Generates a random UUIDv4 (Universally Unique Identifier, version 4) based on the given argument (a source of randomness). To obtain an array of random bytes, use the [cf.random\_seed](https://developers.cloudflare.com/ruleset-engine/rules-language/fields/reference/cf.random%5Fseed/) field.

For example, `uuidv4(cf.random_seed)` will return a UUIDv4 similar to `49887398-6bcf-485f-8899-f15dbef4d1d5`.

Note

You can only use the `uuidv4()` function in [rewrite expressions of Transform Rules](https://developers.cloudflare.com/rules/transform/).

### `wildcard_replace`

`` wildcard_replace(source ` Bytes `, wildcard_pattern ` Bytes `, replacement ` Bytes `, flags ` Bytes ` optional) ``: ` String `

Replaces a `source` string, matched by a literal with zero or more `*` wildcard metacharacters, with a replacement string, returning the result. The replacement string can contain references to wildcard capture groups (for example, `${1}` and `${2}`), up to eight replacement references.

If there is no match, the function will return `source` unchanged.

The `source` parameter must be a field (it cannot be a literal string). Additionally, the entire `source` value must match the `wildcard_pattern` parameter (it cannot match only part of the field value).

To enter a literal `*` character in the `wildcard_pattern` parameter, you must escape it using `\*`. Additionally, you must also escape `\` using `\\`. Two unescaped `*` characters in a row (`**`) in this parameter are considered invalid and cannot be used. If you need to perform character escaping, it is recommended that you use the [raw string syntax](https://developers.cloudflare.com/ruleset-engine/rules-language/values/#raw-string-syntax) for the `wildcard_pattern` parameter.

To enter a literal `$` character in the `replacement` parameter, you must escape it using `$$`.

To perform case-sensitive wildcard matching, set the `flags` parameter to `"s"`.

This function uses lazy matching, that is, it tries to match each `*` metacharacter with the shortest possible string.

You can only use the `wildcard_replace()` function once in an expression, and you cannot nest it with the [regex\_replace()](https://developers.cloudflare.com/ruleset-engine/rules-language/functions/#regex%5Freplace) function.

Examples:

* If the full URI is `https://apps.example.com/calendar/admin?expand=true`,  
`wildcard_replace(http.request.full_uri, "https://*.example.com/*/*", "https://example.com/${1}/${2}/${3}")` will return `https://example.com/apps/calendar/admin?expand=true`
* If the full URI is `https://example.com/applications/app1`,  
`wildcard_replace(http.request.full_uri, "/applications/*", "/apps/${1}")` will return `https://example.com/applications/app1` (unchanged value, since there is no match for the full URI value; you should use the `http.request.uri.path` field for URI path matching).
* If the URI path is `/calendar`,  
`wildcard_replace(http.request.uri.path, "/*", "/apps/${1}")` will return `/apps/calendar`.
* If the URI path is `/Apps/calendar`,  
`wildcard_replace(http.request.uri.path, "/apps/*", "/${1}")` will return `/calendar` (case-insensitive match by default).
* If the URI path is `/Apps/calendar`,  
`wildcard_replace(http.request.uri.path, "/apps/*", "/${1}", "s")` will return `/Apps/calendar` (unchanged value) because there is no case-sensitive match.
* If the URI path is `/apps/calendar/login`,  
`wildcard_replace(http.request.uri.path, "/apps/*/login", "/${1}/login")` will return `/calendar/login`.

For more examples of wildcard matching, refer to [Wildcard matching](https://developers.cloudflare.com/ruleset-engine/rules-language/operators/#wildcard-matching).

Note

Currently, you can only use the `wildcard_replace()` function in rewrite expressions of [URL rewrites](https://developers.cloudflare.com/rules/transform/url-rewrite/) and target URL expressions of [dynamic URL redirects](https://developers.cloudflare.com/rules/url-forwarding/single-redirects/).

## Cloudflare Network Firewall Functions

### `bit_slice`

`` bit_slice(protocol ` String `, offset_start ` Number `, offset_end ` Number `) ``: ` Number `

This function looks for matches on a given slice of bits.

The offset starts on the given protocol header. For example, to match on the first bit of payload for a UDP packet, you must set `offset_start` to `64`.

This is primarily intended for use with `ip`, `udp`, and `tcp`.

The slice (`offset_end` – `offset_start`) cannot be longer than 32 bits, but multiple calls can be joined together by using logical expressions.

The `bit_slice` offset cannot exceed 2,040 bits.

## HMAC validation

Note

Access to the HMAC validation function requires a Cloudflare Pro, Business, or Enterprise plan.

### Overview

You can validate hash-based message authentication code (HMAC) tokens in a rule expression by using the `is_timed_hmac_valid_v0()` function, which has this signature:

```

is_timed_hmac_valid_v0(

  <String literal as Key>,

  <String field as MessageMAC>,

  <Integer literal as ttl>,

  <Integer as currentTimeStamp>,

  <Optional Integer literal as lengthOfSeparator, default: 0>,

  <Optional String literal as flags>

) -> <Bool as result>


```

The `is_timed_hmac_valid_v0()` function has these parameter definitions:

* `Key` ` String literal `  
   * Specifies the secret cryptographic key for validating the HMAC.
* `MessageMAC` ` String `  
   * Contains a concatenation of these HMAC elements: `message`, `separator`, `timestamp`, `mac`. For a definition and an example, refer to [MessageMAC](#messagemac).
* `ttl` ` Integer literal `  
   * Defines the time-to-live for the HMAC token, expressed in seconds. Determines how long the token is valid, relative to the time it was issued.
* `currentTimeStamp` ` Integer `  
   * Represents the UNIX timestamp when Cloudflare received the request, expressed in seconds. Pass the `http.request.timestamp.sec` field as an approximate value to this argument.
* `lengthOfSeparator` ` Integer literal ` optional  
   * Specifies the length of the `separator` between the `timestamp` and the `message` in the `MessageMAC`. Expressed in bytes, with a default value of `0`.
* `flags` ` String literal ` optional  
   * When you set this optional argument to `'s'`, the function expects the value of the Base64-encoded `mac` in the `MessageMAC` argument to use the URL-safe character set with no padding.  
   * When you do **not** set the value of `flags` to `'s'`, you must URL encode the Base64 value for `mac` in the `MessageMAC` argument.

### Usage

The `is_timed_hmac_valid_v0()` function uses the supplied _Key_ to generate a message authentication code (MAC) from the `message` and the `timestamp` regions of the MessageMAC. When the generated MAC matches the `mac` region of the MessageMAC and the token has not expired, the HMAC is valid and the function returns `true`.

For example, the following expression matches requests to `downloads.example.com` that do not include valid HMAC tokens:

```

http.host == "downloads.example.com"

and not is_timed_hmac_valid_v0("mysecretkey", http.request.uri, 100000, http.request.timestamp.sec, 8)


```

For examples of rules that use HMAC validation, refer to [Configure token authentication](https://developers.cloudflare.com/waf/custom-rules/use-cases/configure-token-authentication/) in the WAF documentation.

### MessageMAC

A valid MessageMAC satisfies the following regular expression:

```

(.+)(.*)(\d{10})-(.{43,})


```

and is composed of these parentheses-delimited expressions:

| Expression | Description                                                                                                                                                                                                                                                                                                                         | Example                                          |
| ---------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------ |
| (.+)       | The message to validate.                                                                                                                                                                                                                                                                                                            | /download/cat.jpg                                |
| (.\*)      | The separator between message and timestamp, commonly a parameter name.                                                                                                                                                                                                                                                             | &verify=                                         |
| (\\d{10})  | The 10-digit UNIX timestamp when the MAC was issued, expressed in seconds.                                                                                                                                                                                                                                                          | 1484063137                                       |
| (.{43,})   | A Base64-encoded version of the mac. When you do not set the value of the urlSafe argument in the HMAC validation function to 's', you must URL-encode the Base64 value for mac. When the Base64 MAC encoding is URL-safe, the mac value contains 43 bytes. Otherwise, the value will be 44 bytes or more, because of URL encoding. | IaLGSmELTvlhfd0ItdN6PhhHTFhzx73EX8uy%2FcSDiIU%3D |

For details on generating a MessageMAC, refer to [HMAC token generation](https://developers.cloudflare.com/waf/custom-rules/use-cases/configure-token-authentication/#hmac-token-generation).

## HMAC validation examples

Note

When you do not use the optional `flags` argument for `is_timed_hmac_valid_v0()`, you must URL-encode the Base64 value for `mac` in the `MessageMAC` argument.

For more information, refer to [HMAC Validation: Overview](#overview).

### MessageMAC in a single field

Consider the case where the MessageMAC is contained entirely within a single field, as in this example URI path:

```

/download/cat.jpg?verify=1484063787-IaLGSmELTvlhfd0ItdN6PhhHTFhzx73EX8uy%2FcSDiIU%3D


```

Note how the URI maps to the elements of the MessageMAC:

| Element   | Value                                            |
| --------- | ------------------------------------------------ |
| message   | /download/cat.jpg                                |
| separator | ?verify= (with length 8)                         |
| timestamp | 1484063787                                       |
| mac       | IaLGSmELTvlhfd0ItdN6PhhHTFhzx73EX8uy%2FcSDiIU%3D |

When the MessageMAC is contained entirely within a single field such as `http.request.uri`, pass the field name to the `MessageMAC` argument of the HMAC validation function:

```

is_timed_hmac_valid_v0(

  "mysecretkey",

  http.request.uri,

  100000,

  http.request.timestamp.sec,

  8

)


```

### Concatenated MessageMAC argument

To compose a MessageMAC from more than one field, use the [concat()](#concat) function.

This example constructs the value of the `MessageMAC` argument by concatenating the request URI and two header fields:

```

is_timed_hmac_valid_v0(

  "mysecretkey",

  concat(

    http.request.uri,

    http.request.headers["timestamp"][0],

    "-",

    http.request.headers["mac"][0]),

  100000,

  http.request.timestamp.sec,

  0

)


```

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ruleset-engine/","name":"Ruleset Engine"}},{"@type":"ListItem","position":3,"item":{"@id":"/ruleset-engine/rules-language/","name":"Rules language"}},{"@type":"ListItem","position":4,"item":{"@id":"/ruleset-engine/rules-language/functions/","name":"Functions"}}]}
```
