Functions reference
The Cloudflare Rules language provides functions for manipulating and validating values in an expression:
- Transformation functions manipulate values extracted from an HTTP request.
- The HMAC validation function 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, thelower() 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 for more information.
The Rules language supports these transformation functions:
- any(- Array<Boolean>)- Boolean- Returns - truewhen the comparison operator in the argument returns- truefor any of the values in the argument array. Returns- falseotherwise.
- Example: - any(url_decode(http.request.body.form.values[*])[*] contains "an xss attack")
 
- all(- Array<Boolean>)- Boolean- Returns - truewhen the comparison operator in the argument returns- truefor all values in the argument array. Returns- falseotherwise.
- Example: - all(http.request.headers["content-type"][*] == "application/json")
 
- cidr(addressIP address, ipv4_network_bitsInteger, ipv6_network_bitsInteger)- 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 addressparameter must be a field, that is, it cannot be a literal String.
- The ipv4_network_bitsvalue must be between 1 and 32, and theipv6_network_bitsvalue must be between 1 and 128.
- Examples:
 A) Ifip.srcis113.10.0.2,cidr(ip.src, 24, 24)will return113.10.0.0.
 B) Ifip.srcis2001:0000:130F:0000:0000:09C0:876A:130B,cidr(ip.src, 24, 24)will return2001:0000:0000:0000:0000:0000:0000:0000.
 
- cidr6(addressIP address, ipv6_network_bitsInteger)- 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 addressparameter must be a field, that is, it cannot be a literal String.
- The ipv6_network_bitsvalue must be between 1 and 128.
- This function is equivalent to: cidr(<address>, 32, <ipv6_network_bits>).
- Examples:
 A) Ifip.srcis2001:0000:130F:0000:0000:09C0:876A:130B,cidr6(ip.src, 24)will return2001:0000:0000:0000:0000:0000:0000:0000.
 B) Ifip.srcis113.10.0.2,cidr6(ip.src, 24)will return113.10.0.2(unchanged).
 
- concat(- String | Integer | bytes | Array elements)- String- Takes a comma-separated list of values. Concatenates the argument values into a single String. 
- For example, - concat("String1", " ", "String", 2)will return- "String1 String2".
 
- decode_base64(sourceString)- String- Decodes a Base64-encoded String specified in - source.
- sourcemust be a field, that is, it cannot be a literal String.
- Example: 
 With the following HTTP request header:- client_id: MTIzYWJj,- (any(decode_base64(http.request.headers["client_id"][*])[*] eq "123abc"))would return- true.
 
- ends_with(sourceString, substringString)- Boolean- Returns - truewhen the source ends with a given substring. Returns- falseotherwise. The source cannot be a literal value (like- "foo").
- For example, if - http.request.uri.pathis- "/welcome.html", then- ends_with(http.request.uri.path, ".html")will return- true.
 
- len(- String | bytes)- Integer- Returns the byte length of a String or Bytes field. 
- For example, if - http.hostis- "example.com", then- len(http.host)will return- 11.
 
- lookup_json_integer(fieldString, keyString | Integer [, keyString | Integer, …])- Integer- Returns the integer value associated with the supplied - keyin- field.
 The- fieldmust be a string representation of a valid JSON document.
 The- keycan 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: - A) Given the following JSON object contained in the - http.request.body.rawfield:- { "record_id": "aed53a", "version": 2 }
 Then- lookup_json_integer(http.request.body.raw, "version")will return- 2.- B) Given the following nested object: - { "product": { "id": 356 } }
 Then- lookup_json_integer(http.request.body.raw, "product", "id")will return- 356.- C) Given the following JSON array at the root level: - ["first_item", -234]
 Then- lookup_json_integer(http.request.body.raw, 1)will return- -234.- D) 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.- E) 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(fieldString, keyString | Integer [, keyString | Integer, …])- String- Returns the string value associated with the supplied - keyin- field.
 The- fieldmust be a string representation of a valid JSON document.
 The- keycan 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: - A) Given the following JSON object contained in the - http.request.body.rawfield:- { "company": "cloudflare", "product": "rulesets" }
 Then- lookup_json_string(http.request.body.raw, "company") == "cloudflare"will return- true.- B) Given the following nested object: - { "network": { "name": "cloudflare" } }
 Then- lookup_json_string(http.request.body.raw, "network", "name") == "cloudflare"will return- true.- C) 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.- D) 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.- E) 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(- String)- String- Converts a string field to lowercase. Only uppercase ASCII bytes are converted. All other bytes are unaffected. 
- For example, if - http.hostis- "WWW.cloudflare.com", then- lower(http.host) == "www.cloudflare.com"will return- true.
 
- regex_replace(sourceString, regular_expressionString, replacementString)- 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. 
- 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 - ${<num>}in the replacement string, where- <num>is the number of the capture group.
 
- remove_bytes(- bytes)- bytes- Returns a new byte array with all the occurrences of the given bytes removed. 
- For example, if - http.hostis- "www.cloudflare.com", then- remove_bytes(http.host, "\x2e\x77")will return- "cloudflarecom".
 
- starts_with(sourceString, substringString)- Boolean- Returns - truewhen the source starts with a given substring. Returns- falseotherwise. The source cannot be a literal value (like- "foo").
- For example, if - http.request.uri.pathis- "/blog/first-post", then- starts_with(http.request.uri.path, "/blog")will return- true.
 
- substring(fieldString | Bytes, startInteger [, endInteger])- String- Returns part of the - fieldvalue (the value of a String or Bytes field) from the- startbyte index up to (but excluding) the- endbyte index. The first byte in- fieldhas index- 0. If you do not provide the optional- endindex, the function returns the part of the string from- startindex to the end of the string.
- The - startand- endindexes 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(- 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"
 
- upper(- String)- String- Converts a string field to uppercase. Only lowercase ASCII bytes are converted. All other bytes are unaffected. 
- For example, if - http.hostis- "www.cloudflare.com", then- upper(http.host)will return- "WWW.CLOUDFLARE.COM".
 
- url_decode(sourceString[, optionsString])- String- Decodes a URL-formatted string defined in - source, as in the following:- %20and- +decode to a space character (- %E4%BDdecodes to- ä½.
 
- The - sourcemust be a field, that is, it cannot be a literal string.
- The - optionsparameter 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,- %2520will 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")
 
- uuidv4(- 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_seedfield.
- For example, - uuidv4(cf.random_seed)will return a UUIDv4 similar to- 49887398-6bcf-485f-8899-f15dbef4d1d5.
 
- wildcard_replace(sourceBytes, wildcard_patternBytes, replacementBytes [, flagsBytes])- String- Replaces a - sourcestring, 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}).
- If there is no match, the function will return - sourceunchanged.
- The - sourceparameter must be a field (it cannot be a literal string). Additionally, the entire- sourcevalue must match the- wildcard_patternparameter (it cannot match only part of the field value).
- To enter a literal - *character in the- wildcard_patternparameter, 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 for the- wildcard_patternparameter.
- To enter a literal - $character in the- replacementparameter, you must escape it using- $$.
- To perform case-sensitive wildcard matching, set the - flagsparameter to- "s".
- This function uses lazy matching, that is, it tries to match each - *metacharacter with the shortest possible string.
- 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.pathfield 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. 
 
 Magic Firewall Functions
- 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_startto64.
- This is primarily intended for use with ip,udp, andtcp.
- The slice (offset_end—offset_start) cannot be longer than 32 bits, but multiple calls can be joined together via logical expressions.
- The bit_sliceoffset cannot exceed 2,040 bits.
 
 HMAC validation
 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.
 
- Contains a concatenation of these HMAC elements: 
- 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.secfield as an approximate value to this argument.
 
- Represents the UNIX timestamp when Cloudflare received the request, expressed in seconds. Pass the 
- lengthOfSeparator- Integer literal- Specifies the length of the separatorbetween thetimestampand themessagein theMessageMAC. Expressed in bytes, with a default value of0.
 
- Specifies the length of the 
- flags- String literal- When you set this optional argument to - 's', the function expects the value of the Base64-encoded- macin the- MessageMACargument to use the URL-safe character set with no padding.
- When you do not set the value of - flagsto- 's', you must URL encode the Base64 value for- macin the- MessageMACargument.
 
 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 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 messageto validate. | /download/cat.jpg | 
| (.*) | The separatorbetween message and timestamp, commonly a parameter name. | &verify= | 
| (\d{10}) | The 10-digit UNIX timestampwhen the MAC was issued, expressed in seconds. | 1484063137 | 
| (.{43,}) | A Base64-encoded version of the  When the Base64 MAC encoding is URL-safe, the  | IaLGSmELTvlhfd0ItdN6PhhHTFhzx | 
For details on generating a MessageMAC, refer to HMAC token generation.
 HMAC validation examples
 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%3DNote how the URI maps to the elements of the MessageMAC:
| Element | Value | 
|---|---|
| message | /download/cat.jpg | 
| separator | ?verify=(with length8) | 
| 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() 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
)