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

# Traffic Policy Macros Reference

> Reference documentation for CEL macros available in Traffic Policy for simplifying expressions and dynamic configuration.

ngrok offers a variety of CEL macros that can be used within the Traffic Policy engine to simplify [traffic management](../concepts/expressions) and [dynamic configuration](../concepts/cel-interpolation).\
These macros help you streamline traffic handling by referencing common values and conditions, making it easier to manage complex logic in your Traffic Policies.

You can use these macros in combination with [expressions](../concepts/expressions) and [actions](../actions) to create dynamic, condition-based traffic flows.

## Base64

### `base64.decode() -> bytes`

Decodes base64-encoded string to bytes.

This function will return an error if the string input is not base64-encoded.

#### Signatures

* `base64.decode(<string>) -> <bytes>`

#### Example

```go theme={null}
base64.decode('aGVsbG8=')  // return b'hello'
base64.decode('aGVsbG8')   // error
```

### `base64.encode() -> string`

Encodes bytes to a base64-encoded string.

#### Signatures

* `base64.encode(<bytes>) -> <string>`

#### Example

```go theme={null}
base64.encode(b'hello') // return 'aGVsbG8='
```

## Basic Auth

### `basic_auth.encode(username, password) -> string`

Encodes the passed username and password strings into a Base64 string for use in HTTP Basic Authentication.\
Appends the prefix `Basic ` to the encoded string.

#### Example

```go theme={null}
basic_auth.encode('username', 'password1')  // Basic dXNlcm5hbWU6cGFzc3dvcmQx
```

#### Example (in expression)

<CodeGroup>
  ```yaml policy.yml theme={null}
  expressions:
    - basic_auth.encode('username', 'password1') == 'Basic dXNlcm5hbWU6cGFzc3dvcmQx'
  ```

  ```json policy.json theme={null}
  {
    "expressions": [
      "basic_auth.encode('username', 'password1') == 'Basic dXNlcm5hbWU6cGFzc3dvcmQx'"
    ]
  }
  ```
</CodeGroup>

## Bytes

### `bytes.size() -> int`

Determines the number of bytes in a sequence.

#### Signatures

* `bytes.size() -> int`
* `size(bytes) -> int`

#### Example

```go theme={null}
b'hello'.size() // 5
size(b'world!') // 6
```

## HTTP requests

Available in [`on_http_request`](/traffic-policy/how-it-works#phases) and [`on_http_response`](/traffic-policy/how-it-works#phases) phases.

### `getReqCookie(string) -> cookie`

Returns the cookie struct for the specified cookie name, if it exists on the request.\
If there are multiple cookies of the same name, the first from the ordering specified in the Cookie header will be returned.

#### Example

```go theme={null}
getReqCookie('session')
```

#### Example (expression)

<CodeGroup>
  ```yaml policy.yml theme={null}
  expressions:
    - getReqCookie('session').secure
  ```

  ```json policy.json theme={null}
  {
    "expressions": [
      "getReqCookie('session').secure"
    ]
  }
  ```
</CodeGroup>

### `getReqHeader(string) -> list`

Returns a list of header values for the provided key on the request.\
Header keys must be written in canonical format.\
Defaults to an empty list if the header is not present.

#### Example

```go theme={null}
getReqHeader('User-Agent')
```

#### Example (expression)

<CodeGroup>
  ```yaml policy.yml theme={null}
  expressions:
    - getReqHeader('User-Agent').exists(v, v.matches('(?i)google-images'))
  ```

  ```json policy.json theme={null}
  {
    "expressions": [
      "getReqHeader('User-Agent').exists(v, v.matches('(?i)google-images'))"
    ]
  }
  ```
</CodeGroup>

### `getQueryParam(string) -> list`

Returns a list of the query parameter values from the request URL for the specified key.\
Defaults to an empty list if the query param is not present.

#### Example

```go theme={null}
getQueryParam('search')
```

#### Example (expression)

<CodeGroup>
  ```yaml policy.yml theme={null}
  expressions:
    - size(getQueryParam('q')) == 0
  ```

  ```json policy.json theme={null}
  {
    "expressions": [
      "size(getQueryParam('q')) == 0"
    ]
  }
  ```
</CodeGroup>

### `hasQueryParam(string) -> bool`

Returns `true` or `false` if the specified query parameter key is part of the request URL.

#### Example

```go theme={null}
hasQueryParam('query')
```

#### Example (expression)

<CodeGroup>
  ```yaml policy.yml theme={null}
  expressions:
    - hasQueryParam('q')
  ```

  ```json policy.json theme={null}
  {
    "expressions": [
      "hasQueryParam('q')"
    ]
  }
  ```
</CodeGroup>

### `hasReqCookie(string) -> bool`

Returns `true` or `false` if a cookie exists on the request with the specified name.

#### Example

```go theme={null}
hasReqCookie('session')
```

#### Example (expression)

<CodeGroup>
  ```yaml policy.yml theme={null}
  expressions:
    - hasReqCookie('session')
  ```

  ```json policy.json theme={null}
  {
    "expressions": [
      "hasReqCookie('session')"
    ]
  }
  ```
</CodeGroup>

### `hasReqHeader(string) -> bool`

Returns `true` or `false` if the provided header key is present on the request.\
Header keys must be written in canonical format.

#### Example

```go theme={null}
hasReqHeader('Authorization')
```

#### Example (expression)

<CodeGroup>
  ```yaml policy.yml theme={null}
  expressions:
    - hasReqHeader('X-Version-Id')
  ```

  ```json policy.json theme={null}
  {
    "expressions": [
      "hasReqHeader('X-Version-Id')"
    ]
  }
  ```
</CodeGroup>

## HTTP responses

Available in [`on_http_response`](/traffic-policy/how-it-works#phases) phase only.

### `getResCookie(string) -> cookie`

Returns the cookie struct for the specified cookie name, if it exists on the response.\
If there are multiple cookies of the same name, the cookie with the longest path will be returned.

#### Example

```go theme={null}
getResCookie('_device_id')
```

#### Example (expression)

<CodeGroup>
  ```yaml policy.yml theme={null}
  expressions:
    - getResCookie('_device_id').value == 'mobile-phone-14'
  ```

  ```json policy.json theme={null}
  {
    "expressions": [
      "getResCookie('_device_id').value == 'mobile-phone-14'"
    ]
  }
  ```
</CodeGroup>

### `getResHeader(string) -> list`

Returns a list of header values for the provided key on the response.\
Header keys must be written in canonical format.

#### Example

```go theme={null}
getResHeader('Content-Type')
```

#### Example (expression)

<CodeGroup>
  ```yaml policy.yml theme={null}
  expressions:
    - size(getResHeader('Content-Type').filter(v, v.matches('application/json'))) > 0
  ```

  ```json policy.json theme={null}
  {
    "expressions": [
      "size(getResHeader('Content-Type').filter(v, v.matches('application/json'))) > 0"
    ]
  }
  ```
</CodeGroup>

### `hasResCookie(string) -> bool`

Returns `true` or `false` if a cookie exists on the response with the specified name.

#### Example

```go theme={null}
hasResCookie('_device_id')
```

#### Example (expression)

<CodeGroup>
  ```yaml policy.yml theme={null}
  expressions:
    - hasResCookie('_device_id')
  ```

  ```json policy.json theme={null}
  {
    "expressions": [
      "hasResCookie('_device_id')"
    ]
  }
  ```
</CodeGroup>

### `hasResHeader(string) -> bool`

Returns `true` or `false` if the provided header key is present on the response.\
Header keys must be written in canonical format.\
Defaults to an empty list if the header is not present.

#### Example

```go theme={null}
hasResHeader('Content-Type')
```

#### Example (expression)

<CodeGroup>
  ```yaml policy.yml theme={null}
  expressions:
    - hasResHeader('Content-Type')
  ```

  ```json policy.json theme={null}
  {
    "expressions": [
      "hasResHeader('Content-Type')"
    ]
  }
  ```
</CodeGroup>

## Hash

### `hash.crc32(string) -> string`

Computes the CRC32 checksum of a string using the IEEE polynomial.\
Returns the checksum in hexadecimal format by default.

#### Signatures

* `hash.crc32(string) -> string` (returns hex)
* `hash.crc32(string, format) -> string` (format: "hex" or "base64")

#### Examples

```go theme={null}
hash.crc32('hello')           // '3610a686'
hash.crc32('hello', 'hex')    // '3610a686'
hash.crc32('hello', 'base64') // 'NhCmhg=='
```

### `hash.crc64(string) -> string`

Computes the CRC64 checksum of a string using the ISO polynomial.\
Returns the checksum in hexadecimal format by default.

#### Signatures

* `hash.crc64(string) -> string` (returns hex)
* `hash.crc64(string, format) -> string` (format: "hex" or "base64")

#### Examples

```go theme={null}
hash.crc64('hello')           // '3c3eeee2d8100000'
hash.crc64('hello', 'hex')    // '3c3eeee2d8100000'
hash.crc64('hello', 'base64') // 'PD7u4tgQAAA='
```

### `hash.md5(string) -> string`

<Warning title="Security Notice">
  MD5 is considered cryptographically broken and should not be used for security purposes.
  Use SHA-256 or higher for security-sensitive applications.
</Warning>

Computes the MD5 hash of a string.\
Returns the hash in hexadecimal format by default.

#### Signatures

* `hash.md5(string) -> string` (returns hex)
* `hash.md5(string, format) -> string` (format: "hex" or "base64")

#### Examples

```go theme={null}
hash.md5('hello')           // '5d41402abc4b2a76b9719d911017c592'
hash.md5('hello', 'hex')    // '5d41402abc4b2a76b9719d911017c592'
hash.md5('hello', 'base64') // 'XUFAKrxLKna5cZ2REBfFkg=='
```

### `hash.sha1(string) -> string`

<Warning title="Security Notice">
  SHA-1 is considered cryptographically weak and should not be used for security purposes.
  Use SHA-256 or higher for security-sensitive applications.
</Warning>

Computes the SHA-1 hash of a string.\
Returns the hash in hexadecimal format by default.

#### Signatures

* `hash.sha1(string) -> string` (returns hex)
* `hash.sha1(string, format) -> string` (format: "hex" or "base64")

#### Examples

```go theme={null}
hash.sha1('hello')           // 'aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d'
hash.sha1('hello', 'hex')    // 'aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d'
hash.sha1('hello', 'base64') // 'qvTGHdzF6KLavt4PO0gs2a6pQ00='
```

### `hash.sha256(string) -> string`

Computes the SHA-256 hash of a string.\
Returns the hash in hexadecimal format by default.

#### Signatures

* `hash.sha256(string) -> string` (returns hex)
* `hash.sha256(string, format) -> string` (format: "hex" or "base64")

#### Examples

```go theme={null}
hash.sha256('hello')           // '2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824'
hash.sha256('hello', 'hex')    // '2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824'
hash.sha256('hello', 'base64') // 'LPJNul+wow4m6DsqxbninhsWHlwfp0JecwQzYpOLmCQ='
```

### `hash.sha512(string) -> string`

Computes the SHA-512 hash of a string.\
Returns the hash in hexadecimal format by default.

#### Signatures

* `hash.sha512(string) -> string` (returns hex)
* `hash.sha512(string, format) -> string` (format: "hex" or "base64")

#### Examples

```go theme={null}
hash.sha512('hello')           // '9b71d224bd62f3785d96d46ad3ea3d73319bfbc2890caadae2dff72519673ca72323c3d99ba5c11d7c7acc6e14b8c5da0c4663475c2e5c3adef46f73bcdec043'
hash.sha512('hello', 'hex')    // '9b71d224bd62f3785d96d46ad3ea3d73319bfbc2890caadae2dff72519673ca72323c3d99ba5c11d7c7acc6e14b8c5da0c4663475c2e5c3adef46f73bcdec043'
hash.sha512('hello', 'base64') // 'm3HSJL1i83hdltRq0+o9czGb+8KJDKra4t/3JRlnPKcjI8PZm6XBHXx6zG4UuMXaDEZjR1wuXDre9G9zvN7AQw=='
```

### `hash.xxhash64(string) -> string`

Computes the XXHash64 hash of a string.\
XXHash is a fast, high-quality hash function.\
Returns the hash in hexadecimal format by default.

#### Signatures

* `hash.xxhash64(string) -> string` (returns hex)
* `hash.xxhash64(string, format) -> string` (format: "hex" or "base64")

#### Examples

```go theme={null}
hash.xxhash64('hello')           // '26c7827d889f6da3'
hash.xxhash64('hello', 'hex')    // '26c7827d889f6da3'
hash.xxhash64('hello', 'base64') // 'JseCfYifbaM='
```

## JSON

### `json.decode(string) -> list | map`

Decodes the passed JSON string into a list or map.

#### Example

```go theme={null}
json.decode('{"a":"b"}')  // map[a:b]
json.decode('["a","b","c"]')  // string["a","b","c"]
```

#### Example (in expression)

<CodeGroup>
  ```yaml policy.yml theme={null}
  expressions:
    - json.decode(getReqHeader('x-json-array')[0])[0] == "first entry"
  ```

  ```json policy.json theme={null}
  {
    "expressions": [
      "json.decode(getReqHeader('x-json-array')[0])[0] == \"first entry\""
    ]
  }
  ```
</CodeGroup>

### `json.encode(list | map) -> string`

Encodes the passed string into a JSON string.

#### Example

```go theme={null}
json.encode({a:b})  // {"a":"b"}
json.encode(["a","b","c"])  // ["a","b","c"]
```

#### Example (in expression)

<CodeGroup>
  ```yaml policy.yml theme={null}
  expressions:
    - json.encode(req.content_type.parameters) == '{"charset":"UTF-8"}'
  ```

  ```json policy.json theme={null}
  {
    "expressions": [
      "json.encode(req.content_type.parameters) == '{\"charset\":\"UTF-8\"}'"
    ]
  }
  ```
</CodeGroup>

## Lists

### `list.all(x,p) -> bool`

Checks if a predicate `p` holds for all elements of a list, where `x` is a variable name to be used in `p` as a reference to the element.

#### Example

```go theme={null}
[1, 2, 3].all(x, x > 0) // true
```

### `list.encodeJson() -> string`

Encodes the list as a JSON string.

#### Example

```go theme={null}
["a","b","c"].encodeJson()  // "[\"a\",\"b\",\"c\"]"
```

### `list.exists(x,p) -> bool`

Checks if a predicate `p` holds for at least one element of a list, where `x` is a variable name to be used in `p` as a reference to the element.

#### Example

```go theme={null}
[1, -2, 3].exists(x, x > 0) // true
```

### `list.exists_one(x,p) -> bool`

Checks if a predicate `p` holds for exactly one element of a list, where `x` is a variable name to be used in `p` as a reference to the element.

#### Example

```go theme={null}
[1, 2, 3].exists_one(x, x == 2) // true
```

### `list.filter(x,p) -> list`

Filters a list to include only elements that satisfy a condition, where `x` is a variable name to be used in `p` as a reference to the element.

#### Example

```go theme={null}
[1, 2, 3].filter(x, x > 1) // [2, 3]
```

### `list.join() -> string`

Returns a new string with the elements of the list concatenated.\
Optionally, a separator can be specified to insert between elements.

#### Signatures

* `<list<string>>.join(<string?>) -> <string>`

#### Example

```go theme={null}
['hello', 'mellow'].join()        // returns 'hellomellow'
['hello', 'mellow'].join(' ')     // returns 'hello mellow'
[].join()                         // returns ''
[].join('/')                      // returns ''
```

### `list.map(x,t) -> list`

Transforms each element in a list by applying the function defined in the expression `t`,where `x` is a variable name to be used in `t` as a reference to the element.

#### Example

```go theme={null}
[1, 2, 3].map(n, n * n) // [1, 4, 9]
```

### `list.map(x,p,t) -> list`

Transforms each element in a list by applying the function defined in the expression `t` to elements that satisfy predicate `p`, where `x` is a variable name to be used in `p` as a reference to the element.

#### Example

```go theme={null}
[1, 2, 3, 4].map(num, num % 2 == 0, num * 2) // [4, 8]
```

### `list.size() -> int`

Determines the number of elements in a list.

#### Signatures

* `list.size() -> int`
* `size(list) -> int`

#### Example

```go theme={null}
['hello', 'world'].size() // 2
size(['hello', 'world'])  // 2
```

### `list.slice() -> list`

Returns a new sub-list using the indexes provided.

#### Signatures

* `<list>.slice(<int>, <int>) -> <list>`

#### Example

```go theme={null}
[1,2,3,4].slice(1, 3) // return [2, 3]
[1,2,3,4].slice(2, 4) // return [3 ,4]
```

### `list.flatten() -> list`

Flattens a list recursively.
If an optional depth is provided, the list is flattened to the specified level.
A negative depth value will result in an error.

#### Signatures

* `<list>.flatten() -> <list>`
* `<list>.flatten(<int>) -> <list>`

#### Example

```go theme={null}
[1,[2,3],[4]].flatten()         // returns [1, 2, 3, 4]
[1,[2,[3,4]]].flatten()         // returns [1, 2, [3, 4]]
[1,2,[],[],[3,4]].flatten()     // returns [1, 2, 3, 4]
[1,[2,[3,[4]]]].flatten(2)      // returns [1, 2, 3, [4]]
[1,[2,[3,[4]]]].flatten(-1)     // error
```

### `list.sort() -> list`

Sorts a list with comparable elements.
If the element type is not comparable or the element types are not the same, the function will produce an error.

Comparable types include: int, uint, double, bool, duration, timestamp, string, bytes.

#### Signatures

* `<list(T)>.sort() -> <list(T)>`

#### Example

```go theme={null}
[3, 2, 1].sort()        // returns [1, 2, 3]
["b", "c", "a"].sort()  // returns ["a", "b", "c"]
[1, "b"].sort()         // error
[[1, 2, 3]].sort()      // error
```

### `list.sortBy(x, keyExpr) -> list`

Sorts a list by a key value.
The order is determined by the result of an expression applied to each element of the list.
The output of the key expression must be a comparable type, otherwise the function will return an error.

#### Signatures

* `<list(T)>.sortBy(<bindingName>, <keyExpr>) -> <list(T)>`

#### Example

```go theme={null}
[
  Player { name: "foo", score: 0 },
  Player { name: "bar", score: -10 },
  Player { name: "baz", score: 1000 },
].sortBy(e, e.score).map(e, e.name)  // returns ["bar", "foo", "baz"]
```

### `list.distinct() -> list`

Returns the distinct elements of a list.

#### Signatures

* `<list(T)>.distinct() -> <list(T)>`

#### Example

```go theme={null}
[1, 2, 2, 3, 3, 3].distinct()      // returns [1, 2, 3]
["b", "b", "c", "a", "c"].distinct() // returns ["b", "c", "a"]
[1, "b", 2, "b"].distinct()        // returns [1, "b", 2]
```

### `lists.range() -> list`

Returns a list of integers from 0 to n-1.

#### Signatures

* `lists.range(<int>) -> <list(int)>`

#### Example

```go theme={null}
lists.range(5)  // returns [0, 1, 2, 3, 4]
```

## Maps

### `map.all(x,p) -> bool`

Checks if a predicate `p` holds for all elements of a map, where `x` is a variable name to be used in `p` as a reference to the key.

#### Example

```go theme={null}
{'one': 1, 'two': 2}.all(x, x.startsWith('o')) // false
```

### `map.encodeJson() -> string`

Encodes the map as a JSON string.

#### Example

```go theme={null}
{a:"b",c:"d"}.encodeJson()  // "{\"a\":\"b\",\"c\":\"d\"}"
```

### `map.encodeQueryString() -> string`

Encodes the map as a URL query string.

#### Example

```go theme={null}
{a:"b",c:"d"}.encodeQueryString()  // "a=b&c=d"
```

### `map.exists(x,p) -> bool`

Checks if a predicate `p` holds for at least one element of a map, where `x` is a variable name to be used in `p` as a reference to the key.

#### Example

```go theme={null}
{'one': 1, 'two': 2}.exists(x, x.startsWith('o')) // true
```

### `map.exists_one(x,p) -> bool`

Checks if a predicate `p` holds for exactly one element of a map, where `x` is a variable name to be used in `p` as a reference to the key.

#### Example

```go theme={null}
{'one': 1, 'two': 2}.exists_one(x, x == 'one') // true
```

### `map.filter(x,p) -> list`

Filters a map to include only keys that satisfy a condition, where `x` is a variable name to be used in `p` as a reference to the key.

#### Example

```go theme={null}
{'one': 1, 'two': 2}.filter(x, x.startsWith('o')) // ['one']
```

### `map.map(x,t) -> list`

Transforms each key in a map by applying the function defined in the expression `t`, where `x` is a variable name to be used in `t` as a reference to the key.

#### Example

```go theme={null}
{'one': 1, 'two': 2}.map(k, k) // ['one', 'two']
```

### `map.map(x,p,t) -> list`

Transforms each key in a map by applying the function defined in the expression `t` to keys that satisfy predicate `p`, where `x` is a variable name to be used in `p` as a reference to the key.

#### Example

```go theme={null}
{'one': 1, 'two': 2, 'three': 3}.map(k, k.startsWith('t'), k.upper()) // ['TWO', 'THREE']
```

### `map.size() -> int`

Determines the number of entries in a map.

#### Signatures

* `map.size() -> int`
* `size(map) -> int`

#### Example

```go theme={null}
{'hello': 'world'}.size() // 1
size({1: true, 2: false}) // 2
```

## Query string

### `queryString.decode(string) -> map`

Decodes the supplied query string into a map.

#### Example

```go theme={null}
queryString.decode("a=b&c=d")  // {a:b,c:d}
```

#### Example (in expression)

<CodeGroup>
  ```yaml policy.yml theme={null}
  expressions:
    - queryString.decode(req.url.query)["q"] == "hello"
  ```

  ```json policy.json theme={null}
  {
    "expressions": [
      "queryString.decode(req.url.query)[\"q\"] == \"hello\""
    ]
  }
  ```
</CodeGroup>

### `queryString.encode(map) -> string`

Encodes the passed map into a query string.

#### Example

```go theme={null}
queryString.encode({a:b,c:d})  // a=b&c=d
```

#### Example (in expression)

<CodeGroup>
  ```yaml policy.yml theme={null}
  expressions:
    - queryString.encode({"q":"policy"}) == req.url.query
  ```

  ```json policy.json theme={null}
  {
    "expressions": [
      "queryString.encode({\"q\":\"policy\"}) == req.url.query"
    ]
  }
  ```
</CodeGroup>

## Random

### `rand.double() -> double`

Returns a random `double` between `0` and `1`.

#### Example

```go theme={null}
rand.double() >= 0.5
```

#### Example (in expression)

<CodeGroup>
  ```yaml policy.yml theme={null}
  expressions:
    - rand.double() >= 0.5
  ```

  ```json policy.json theme={null}
  {
    "expressions": [
      "rand.double() >= 0.5"
    ]
  }
  ```
</CodeGroup>

### `rand.int(min,max) -> int`

Returns a random `int` between the provided `min` and `max` values.\
Only supports positive integers and `min` must be larger than the provided `max`.\
By default, `min` is `0` and `max` is `1`.

#### Example

```go theme={null}
rand.int() == 1
rand.int(0, 10) >= 5
```

#### Examples (in expression)

The following is an example of using `rand.int` with the default values:

<CodeGroup>
  ```yaml policy.yml theme={null}
  expressions:
    - rand.int() == 1
  ```

  ```json policy.json theme={null}
  {
    "expressions": [
      "rand.int() == 1"
    ]
  }
  ```
</CodeGroup>

The following is an example of using `rand.int` with custom values:

<CodeGroup>
  ```yaml policy.yml theme={null}
  expressions:
    - rand.int(0, 10) >= 5
  ```

  ```json policy.json theme={null}
  {
    "expressions": [
      "rand.int(0, 10) >= 5"
    ]
  }
  ```
</CodeGroup>

## Secrets

### `secrets.get(string, string) -> string`

Takes the vault name as the first argument and the secret name as the second argument.\
Returns the secret value.

Security Macros allow you to access sensitive information directly in your Traffic Policies.\
Your ngrok account has a Vault that can store Secrets.\
Any secrets that you add to your vault will be available across your account on all Traffic Policies.\
Updates to these secrets will be reflected across all Traffic Policies automatically.

#### How secrets are secured

* Secrets are protected at rest using industry standard `AES-256` encryption
* ngrok's REST API does not return secrets as part of any of its response payloads
* REST API traffic is encrypted in-transit using `HTTP/S` and `TLS 1.2+`

For more information on secrets, see [Traffic Policy Secrets](/traffic-policy/secrets/).

#### Example

```yaml theme={null}
secrets.get("vault-name", "secret-name")
```

## String

### `string.matches() -> bool`

Tests whether a string matches a given RE2 regular expression.\
This function provides a simple way to validate patterns in strings.

#### Signatures

* `matches(string, regex) -> bool`
* `string.matches(regex) -> bool`

#### Example

```go theme={null}
matches("foobar", "foo.*")  // true
"foobar".matches("foo.*")  // true

matches("hello", "^h.*o$") // true
"hello".matches("^h.*o$") // true

matches("test", "fail")    // false
"test".matches("fail")    // false
```

### `string.startsWith() -> bool`

Tests whether a string starts with the specified prefix.

#### Signatures

* `string.startsWith(prefix) -> bool`

#### Example

```go theme={null}
"hello world".startsWith("hello") // true
"foobar".startsWith("foo")        // true
"ngrok".startsWith("rocks")       // false
"test".startsWith("")             // true
```

### `string.endsWith() -> bool`

Tests whether a string ends with the specified suffix.

#### Signatures

* `string.endsWith(suffix) -> bool`

#### Example

```go theme={null}
"hello world".endsWith("world") // true
"foobar".endsWith("bar")        // true
"ngrok".endsWith("rocks")       // false
"test".endsWith("")             // true
```

### `string.contains() -> bool`

Tests whether a string contains the specified substring.

#### Signatures

* `string.contains(substring) -> bool`

#### Example

```go theme={null}
"hello world".contains("world") // true
"foobar".contains("baz")        // false
"ngrok".contains("gro")         // true
"test".contains("")             // true
```

### `string.charAt() -> string`

Returns the character at the given position.
If the position is negative, or greater than the length of the string, the function will produce an error.

#### Signatures

* `<string>.charAt(<int>) -> <string>`

#### Example

```go theme={null}
'hello'.charAt(4)  // returns 'o'
'hello'.charAt(5)  // returns ''
'hello'.charAt(-1) // error
```

### `string.size() -> int`

Determines the length of a string in terms of the number of Unicode codepoints.

#### Signatures

* `string.size() -> int`
* `size(string) -> int`

#### Example

```go theme={null}
"hello".size() // 5
size("world!") // 6
```

### `string.indexOf() -> int`

Returns the index of the first occurrence of a substring within the string.\
The function also accepts an optional position argument to start the search.

#### Signatures

* `<string>.indexOf(<string>, <int?>) -> <int>`

#### Example

```go theme={null}
'hello mellow'.indexOf('')         // returns 0
'hello mellow'.indexOf('ello')     // returns 1
'hello mellow'.indexOf('jello')    // returns -1
'hello mellow'.indexOf('', 2)      // returns 2
'hello mellow'.indexOf('ello', 2)  // returns 7
```

### `string.format() -> string`

Returns a new string with substitutions being performed, printf-style.
The valid formatting clauses are `%s` (string), `%d` (integer), `%f` (double with fixed-point precision), `%e` (double in scientific notation), `%b` (binary integer or boolean), `%x` (lowercase hex), `%X` (uppercase hex), and `%o` (octal).

#### Signatures

* `<string>.format(<list>) -> <string>`

#### Example

```go theme={null}
"hello %s".format(["world"])                    // returns "hello world"
"integer: %d".format([42])                      // returns "integer: 42"
"%f".format([3.14])                             // returns "3.140000"
"%x".format([26])                               // returns "1a"
"binary: %b".format([5])                        // returns "binary: 101"
"bool: %b".format([true])                       // returns "bool: 1"
```

### `string.lastIndexOf() -> int`

Returns the integer index at the start of the last occurrence of the search string.
If the search string is not found the function returns -1.

The function also accepts an optional position which represents the last index to be considered as the beginning of the substring match.
If the substring is the empty string, the index where the search starts is returned (string length or custom).

#### Signatures

* `<string>.lastIndexOf(<string>) -> <int>`
* `<string>.lastIndexOf(<string>, <int>) -> <int>`

#### Example

```go theme={null}
'hello mellow'.lastIndexOf('')         // returns 12
'hello mellow'.lastIndexOf('ello')     // returns 7
'hello mellow'.lastIndexOf('jello')    // returns -1
'hello mellow'.lastIndexOf('ello', 6)  // returns 1
'hello mellow'.lastIndexOf('ello', 20) // error
'hello mellow'.lastIndexOf('ello', -1) // error
```

### `string.split() -> list`

Splits a string into a list of substrings using a specified separator.\
Optionally, a maximum number of splits can be defined.

#### Signatures

* `<string>.split(<string?>, <int?>) -> list<string>`

#### Example

```go theme={null}
'hello mellow'.split()             // returns ['hello', 'mellow']
'hello mellow'.split(' ', 1)       // returns ['hello']
'hello,mellow,hi'.split(',')       // returns ['hello', 'mellow', 'hi']
'hello,mellow,hi'.split(',', 2)    // returns ['hello', 'mellow']
```

### `string.replace() -> string`

Replaces occurrences of a substring with another string.\
Optionally, limits the number of replacements.

#### Signatures

* `<string>.replace(<string>, <string>, <int?>) -> <string>`

#### Example

```go theme={null}
'hello mellow'.replace('l', 'L')        // returns 'heLLo meLLow'
'hello mellow'.replace('l', 'L', 2)     // returns 'heLLo mellow'
'hello mellow'.replace('x', 'X')        // returns 'hello mellow' (no changes)
```

### `string.decodeBase64() -> string`

Decodes the Base64 string and returns it as a string.

#### Example

```go theme={null}
"c29tZTp0aGluZw==".decodeBase64()  // "some:thing"
```

### `string.decodeJson() -> map | list`

Decodes the JSON string and returns it as a map or list.

#### Example

```go theme={null}
"{\"a\":\"b\"}".decodeJson()  // map{a:b}
```

### `string.decodeQueryString() -> map`

Decodes the string as a URL query and returns a map with the query parameters.

#### Example

```go theme={null}
"a=b&c=d".decodeQueryString()  // map{a:b,c:d}
```

### `string.encodeBase64() -> string`

Encodes the string and returns it as a base64 encoded string.

#### Example

```go theme={null}
"some:thing".encodeBase64()  // "c29tZTp0aGluZw=="
```

### `string.escapeUrl() -> string`

Returns the string with percent encoding applied.

#### Example

```go theme={null}
"i;md/r/$y".escapeUrl()
// returns i%3Bmd%2Fr%2F%24y
```

### `string.isJson() -> bool`

Checks if the string is valid JSON and returns true if so, otherwise false.

#### Example

```go theme={null}
'{"a":"b","c":"d"}'.isJson() // true
'not json'.isJson() // false
```

### `string.isPrivateIp() -> bool`

Checks if the string is a valid private IP address falling in the range of

```
10.0.0.0 – 10.255.255.255
172.16.0.0 – 172.31.255.255
192.168.0.0 – 192.168.255.255
```

as per [RFC 1918](https://tools.ietf.org/html/rfc1918).\
It returns true if so, otherwise false.

#### Example

```go theme={null}
'192.168.1.1'.isPrivateIp() // true
```

### `string.isQueryString() -> bool`

Checks if the string is valid Query String and returns true if so, otherwise false.

#### Example

```go theme={null}
'a=b&c=d'.isQueryString() // true
'not a query string'.isQueryString() // false
```

### `string.isURL() -> bool`

Checks if the string is a valid URL and returns true if so, otherwise false.

#### Example

```go theme={null}
'https://ngrok.com'.isURL() // true
'not a url'.isURL() // false
```

### `string.lower() -> string`

Lowercases a UTF-8 string.

#### Example

```go theme={null}
"Ärger in Österreich, ÉCOLE, İSTANBUL, ЙОГА!".lower()
// returns "ärger in österreich, école, istanbul, йога!"
```

### `string.upper() -> string`

Uppercases a UTF-8 string.

#### Example

```go theme={null}
"Ärger in Österreich, ÉCOLE, İSTANBUL, ЙОГА!".upper()
// returns "ÄRGER IN ÖSTERREICH, ÉCOLE, İSTANBUL, ЙОГА!"
```

### `string.parseUrl() -> URL`

Returns the provided string as a net [URL map](https://pkg.go.dev/net/url#URL) structure.

#### Example

```go theme={null}
"https://ngrok.com".parseUrl()
// returns {host:ngrok.com, scheme:https}
```

### `string.unescapeUrl() -> string`

Decodes a percent-encoded string back to its original form.

#### Example

```go theme={null}
"i%3Bmd%2Fr%2F%24y".unescapeUrl()
// returns i;md/r/$y
```

### `string.md5() -> string`

<Warning title="Security Notice">
  MD5 is considered cryptographically broken and should not be used for security purposes.
  Use SHA-256 or higher for security-sensitive applications.
</Warning>

Computes the MD5 hash of the string.\
Returns the hash in hexadecimal format by default.

#### Signatures

* `string.md5() -> string` (returns hex)
* `string.md5(format) -> string` (format: "hex" or "base64")

#### Examples

```go theme={null}
'hello'.md5()           // '5d41402abc4b2a76b9719d911017c592'
'hello'.md5('hex')      // '5d41402abc4b2a76b9719d911017c592'
'hello'.md5('base64')   // 'XUFAKrxLKna5cZ2REBfFkg=='
```

### `string.sha1() -> string`

<Warning title="Security Notice">
  SHA-1 is considered cryptographically weak and should not be used for security purposes.
  Use SHA-256 or higher for security-sensitive applications.
</Warning>

Computes the SHA-1 hash of the string.\
Returns the hash in hexadecimal format by default.

#### Signatures

* `string.sha1() -> string` (returns hex)
* `string.sha1(format) -> string` (format: "hex" or "base64")

#### Examples

```go theme={null}
'hello'.sha1()           // 'aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d'
'hello'.sha1('hex')      // 'aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d'
'hello'.sha1('base64')   // 'qvTGHdzF6KLavt4PO0gs2a6pQ00='
```

### `string.sha256() -> string`

Computes the SHA-256 hash of the string.\
Returns the hash in hexadecimal format by default.

#### Signatures

* `string.sha256() -> string` (returns hex)
* `string.sha256(format) -> string` (format: "hex" or "base64")

#### Examples

```go theme={null}
'hello'.sha256()           // '2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824'
'hello'.sha256('hex')      // '2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824'
'hello'.sha256('base64')   // 'LPJNul+wow4m6DsqxbninhsWHlwfp0JecwQzYpOLmCQ='
```

### `string.sha512() -> string`

Computes the SHA-512 hash of the string.\
Returns the hash in hexadecimal format by default.

#### Signatures

* `string.sha512() -> string` (returns hex)
* `string.sha512(format) -> string` (format: "hex" or "base64")

#### Examples

```go theme={null}
'hello'.sha512()           // '9b71d224bd62f3785d96d46ad3ea3d73319bfbc2890caadae2dff72519673ca72323c3d99ba5c11d7c7acc6e14b8c5da0c4663475c2e5c3adef46f73bcdec043'
'hello'.sha512('hex')      // '9b71d224bd62f3785d96d46ad3ea3d73319bfbc2890caadae2dff72519673ca72323c3d99ba5c11d7c7acc6e14b8c5da0c4663475c2e5c3adef46f73bcdec043'
'hello'.sha512('base64')   // 'm3HSJL1i83hdltRq0+o9czGb+8KJDKra4t/3JRlnPKcjI8PZm6XBHXx6zG4UuMXaDEZjR1wuXDre9G9zvN7AQw=='
```

### `string.crc32() -> string`

Computes the CRC32 checksum of the string using the IEEE polynomial.\
Returns the checksum in hexadecimal format by default.

#### Signatures

* `string.crc32() -> string` (returns hex)
* `string.crc32(format) -> string` (format: "hex" or "base64")

#### Examples

```go theme={null}
'hello'.crc32()           // '3610a686'
'hello'.crc32('hex')      // '3610a686'
'hello'.crc32('base64')   // 'NhCmhg=='
```

### `string.crc64() -> string`

Computes the CRC64 checksum of the string using the ISO polynomial.\
Returns the checksum in hexadecimal format by default.

#### Signatures

* `string.crc64() -> string` (returns hex)
* `string.crc64(format) -> string` (format: "hex" or "base64")

#### Examples

```go theme={null}
'hello'.crc64()           // '3c3eeee2d8100000'
'hello'.crc64('hex')      // '3c3eeee2d8100000'
'hello'.crc64('base64')   // 'PD7u4tgQAAA='
```

### `string.xxhash64() -> string`

Computes the XXHash64 hash of the string.\
XXHash is a fast, high-quality hash function.\
Returns the hash in hexadecimal format by default.

#### Signatures

* `string.xxhash64() -> string` (returns hex)
* `string.xxhash64(format) -> string` (format: "hex" or "base64")

#### Examples

```go theme={null}
'hello'.xxhash64()           // '26c7827d889f6da3'
'hello'.xxhash64('hex')      // '26c7827d889f6da3'
'hello'.xxhash64('base64')   // 'JseCfYifbaM='
```

### `string.lowerAscii() -> string`

Returns a new string where all ASCII characters are lower-cased.

This function does not perform Unicode case-mapping for characters outside the ASCII range.

#### Signatures

* `<string>.lowerAscii() -> <string>`

#### Example

```go theme={null}
'TacoCat'.lowerAscii()      // returns 'tacocat'
'TacoCÆt Xii'.lowerAscii()  // returns 'tacocÆt xii'
```

### `string.upperAscii() -> string`

Returns a new string where all ASCII characters are upper-cased.

This function does not perform Unicode case-mapping for characters outside the ASCII range.

#### Signatures

* `<string>.upperAscii() -> <string>`

#### Example

```go theme={null}
'TacoCat'.upperAscii()      // returns 'TACOCAT'
'TacoCÆt Xii'.upperAscii()  // returns 'TACOCÆT XII'
```

### `string.substring() -> string`

Returns the substring given a numeric range corresponding to character positions.
Optionally may omit the trailing range for a substring from a given character position until the end of a string.

Character offsets are 0-based with an inclusive start range and exclusive end range.
It is an error to specify an end range that is lower than the start range, or for either the start or end index to be negative or exceed the string length.

#### Signatures

* `<string>.substring(<int>) -> <string>`
* `<string>.substring(<int>, <int>) -> <string>`

#### Example

```go theme={null}
'tacocat'.substring(4)    // returns 'cat'
'tacocat'.substring(0, 4) // returns 'taco'
'tacocat'.substring(-1)   // error
'tacocat'.substring(2, 1) // error
```

### `string.trim() -> string`

Returns a new string which removes the leading and trailing whitespace in the target string.
The trim function uses the Unicode definition of whitespace which does not include the zero-width spaces.

#### Signatures

* `<string>.trim() -> <string>`

#### Example

```go theme={null}
'  \ttrim\n    '.trim() // returns 'trim'
```

### `string.reverse() -> string`

Returns a new string whose characters are the same as the target string, only formatted in reverse order.

#### Signatures

* `<string>.reverse() -> <string>`

#### Example

```go theme={null}
'gums'.reverse()        // returns 'smug'
'John Smith'.reverse()  // returns 'htimS nhoJ'
```

### `strings.quote() -> string`

Takes the given string and makes it safe to print (without any formatting due to escape sequences).
If any invalid UTF-8 characters are encountered, they are replaced with \uFFFD.

#### Signatures

* `strings.quote(<string>) -> <string>`

#### Example

```go theme={null}
strings.quote('single-quote with "double quote"')  // returns '"single-quote with \"double quote\""'
strings.quote("two escape sequences \a\n")         // returns '"two escape sequences \\a\\n"'
```

## Timestamps

### `ts.getDate() -> int`

Extracts the day of the month (1-based indexing) from a timestamp.

#### Signatures

* `Timestamp.getDate() -> int` (in UTC)
* `Timestamp.getDate(string) -> int` (with timezone)

#### Example

```go theme={null}
timestamp("2023-12-25T00:00:00Z").getDate()                      // 25
timestamp("2023-12-25T00:00:00Z").getDate("America/Los_Angeles") // 24
timestamp("2024-01-01T10:00:00Z").getDate()                      // 1
timestamp("2024-01-01T10:00:00Z").getDate("Asia/Tokyo")          // 1
```

### `ts.getDayOfMonth() -> int`

Returns the day of the month from a timestamp, using zero-based indexing.

#### Signatures

* `Timestamp.getDayOfMonth() -> int` (in UTC)
* `Timestamp.getDayOfMonth(string) -> int` (with timezone)

#### Example

```go theme={null}
timestamp("2023-12-25T00:00:00Z").getDayOfMonth()                   // 24
timestamp("2023-12-25T00:00:00Z").getDayOfMonth("America/Los_Angeles") // 23
```

### `ts.getDayOfWeek() -> int`

Returns the day of the week from a timestamp, using zero-based indexing (0 for Sunday).

#### Signatures

* `Timestamp.getDayOfWeek() -> int` (in UTC)
* `Timestamp.getDayOfWeek(string) -> int` (with timezone)

#### Example

```go theme={null}
timestamp("2023-12-25T12:00:00Z").getDayOfWeek() // 1 (Monday)
```

### `ts.getDayOfYear() -> int`

Returns the day of the year from a timestamp, using zero-based indexing.

#### Signatures

* `Timestamp.getDayOfYear() -> int` (in UTC)
* `Timestamp.getDayOfYear(string) -> int` (with timezone)

#### Example

```go theme={null}
timestamp("2023-12-25T12:00:00Z").getDayOfYear() // 358
```

### `ts.getFullYear() -> int`

Returns the year from a timestamp.

#### Signatures

* `Timestamp.getFullYear() -> int` (in UTC)
* `Timestamp.getFullYear(string) -> int` (with timezone)

#### Example

```go theme={null}
timestamp("2023-12-25T12:00:00Z").getFullYear() // 2023
```

### `ts.getHours() -> int`

Returns the hour from a timestamp or converts a duration to hours.

#### Signatures

* `Timestamp.getHours() -> int` (in UTC)
* `Timestamp.getHours(string) -> int` (with timezone)
* `Duration.getHours() -> int` (convert the duration to hours)

#### Example

```go theme={null}
timestamp("2023-12-25T12:00:00Z").getHours() // 12
duration("3h").getHours()                    // 3
```

### `ts.getMilliseconds() -> int`

Returns the milliseconds from a timestamp or the milliseconds portion of a duration.

#### Signatures

* `Timestamp.getMilliseconds() -> int` (in UTC)
* `Timestamp.getMilliseconds(string) -> int` (with timezone)
* `Duration.getMilliseconds() -> int` (extracts the milliseconds portion)

#### Example

```go theme={null}
timestamp("2023-12-25T12:00:00.500Z").getMilliseconds() // 500
duration("1.234s").getMilliseconds()                   // 234
```

### `ts.getMinutes() -> int`

Returns the minutes from a timestamp or converts a duration to minutes.

#### Signatures

* `Timestamp.getMinutes() -> int` (in UTC)
* `Timestamp.getMinutes(string) -> int` (with timezone)
* `Duration.getMinutes() -> int` (convert the duration to minutes)

#### Example

```go theme={null}
timestamp("2023-12-25T12:30:00Z").getMinutes() // 30
duration("1h30m").getMinutes()                 // 90
```

### `ts.getMonth() -> int`

Returns the month from a timestamp, using zero-based indexing (0 for January).

#### Signatures

* `Timestamp.getMonth() -> int` (in UTC)
* `Timestamp.getMonth(string) -> int` (with timezone)

#### Example

```go theme={null}
timestamp("2023-12-25T12:00:00Z").getMonth() // 11 (December)
```

### `ts.getSeconds() -> int`

Returns the seconds from a timestamp or converts a duration to seconds.

#### Signatures

* `Timestamp.getSeconds() -> int` (in UTC)
* `Timestamp.getSeconds(string) -> int` (with timezone)
* `Duration.getSeconds() -> int` (convert the duration to seconds)

#### Example

```go theme={null}
timestamp("2023-12-25T12:30:30Z").getSeconds() // 30
duration("1m30s").getSeconds()                 // 90
```

## URL

### `url.escape(string) -> string`

Returns the string with percent encoding applied.

#### Example

```go theme={null}
url.escape("i;md/r/$y")
// returns i%3Bmd%2Fr%2F%24y
```

#### Example (in expression)

<CodeGroup>
  ```yaml policy.yml theme={null}
  expressions:
    - url.escape(req.raw) == '%2Ffoo'
  ```

  ```json policy.json theme={null}
  {
    "expressions": [
      "url.escape(req.raw) == '%2Ffoo'"
    ]
  }
  ```
</CodeGroup>

### `url.parse(string) -> URL`

Returns the provided URL string as a net [URL map](https://pkg.go.dev/net/url#URL) structure.

#### Example

```go theme={null}
url.parse("https://ngrok.com")
// returns {host:ngrok.com, scheme:https}
```

#### Example (in expression)

<CodeGroup>
  ```yaml policy.yml theme={null}
  expressions:
    - url.parse(req.url).host == 'ngrok.com'
  ```

  ```json policy.json theme={null}
  {
    "expressions": [
      "url.parse(req.url).host == 'ngrok.com'"
    ]
  }
  ```
</CodeGroup>

### `url.unescape(string) -> string`

Decodes a percent-encoded string back to its original form.

#### Example

```go theme={null}
url.unescape("i%3Bmd%2Fr%2F%24y")
// returns i;md/r/$y
```

#### Example (in expression)

<CodeGroup>
  ```yaml policy.yml theme={null}
  expressions:
    - url.unescape('%2Ffoo') == '/foo'
  ```

  ```json policy.json theme={null}
  {
    "expressions": [
      "url.unescape('%2Ffoo') == '/foo'"
    ]
  }
  ```
</CodeGroup>

## Utility

### `has(field) -> bool`

Checks whether a field or property exists in a list or map.

#### Example

```go theme={null}
has(req.headers['x-custom-header'])
```

### `inCidrRange(ip,cidr) -> bool`

Evaluates whether the given IP address falls within the specified CIDR range.

Returns `true` if the IP is within the range, and `false` if it is outside the range or if the provided CIDR is invalid.

#### Example

```go theme={null}
inCidrRange('192.168.1.100', '192.168.1.0/24')  // true
```

#### Example (in expression)

<CodeGroup>
  ```yaml policy.yml theme={null}
  expressions:
    - inCidrRange(conn.client_ip, '66.249.66.1/24')
  ```

  ```json policy.json theme={null}
  {
    "expressions": [
      "inCidrRange(conn.client_ip, '66.249.66.1/24')"
    ]
  }
  ```
</CodeGroup>

### `inCidrRanges(ip,cidrs) -> bool`

Checks if the given IP address falls within any of the specified CIDR ranges.

Returns `true` if the IP is within at least one valid CIDR range, and `false` if it is not within any valid range.\
Invalid CIDR ranges are ignored.

#### Example

```go theme={null}
inCidrRanges('192.168.1.100', ['192.168.1.0/24', '10.0.0.0/8']) // true
```

#### Example (in expression)

<CodeGroup>
  ```yaml policy.yml theme={null}
  expressions:
    - inCidrRanges(conn.client_ip, ['66.249.66.1/24', '2001:4860::/32'])
  ```

  ```json policy.json theme={null}
  {
    "expressions": [
      "inCidrRanges(conn.client_ip, ['66.249.66.1/24', '2001:4860::/32'])"
    ]
  }
  ```
</CodeGroup>
