Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Expansion expressions can not contain logic (if/else/etc), but it is possible to iterate lists and include/exclude content based on specific conditions. This is enabled by using sections.
A section MUST:
start with tag {{#<name>}}
end with tag {{/<name>}}
reference a property by (path and) name
A section MAY:
contain expansion expressions (${...}
)
static text
Example of section referencing property 'path.name'
Sections behave different depending on the type of the referenced property:
If the property doesn't exist, has no value or is false nothing will be rendered
If the property is a list (multi-value) the content of the section will be rendered for each element in the list
Otherwise section content will be rendered once
When a section is rendered the current property value is referenced using '.'
(${.}
/ {{.}}
/ {{{.}}}
) and properties on the current property value (if it's an object) are referenced using the property name like in regular expansion (${name}
). Properties are first searched for at the current property and if not found in top level scopes.
Example of section listing all "users"
It is also possible to invert a section, making it render when a property doesn't exist, a list is empty or a value is false. To invert, section MUST start with tag {{^name}}
.
Example of inverted section
Given the following list of strings:
this expression:
will render (note the trailing comma):
To remove the trailing comma, we can embed an inverted section using the @last
property on the current list item (only rendered when element is not "last" in list):
This will render:
Given the following object:
this expression:
will render:
The Integrity platform has two types of expressions that can be used in configuration: expansions and predicates.
Expansions are expressions that contain a dot-separated path to a value and the expression itself will be replaced with the value. Expansions always result in string values and can be combined with static strings and other expressions to form the result.
Values exist in different scopes (first element of path) and different scopes are available in different situations depending on the context.
Expansion can be performed during startup (expansion of configuration values) or in runtime (expansion of data).
Expansion expressions has the following syntax: ${path.to.value}
Predicates are boolean javascript expressions that must return either true or false. Predicates are used for controlling execution and for filtering and are always evaluated during runtime.
Expansions and predicates operate on the same data structures but since they are evaluated in different environments, they will use slightly different syntax.
Expansion is basically a template rendering. The string containing one or more expressions and static values is the template and result is the rendered template.
Predicates are javascript expressions evaluated at runtime and must be valid javascript.
The biggest difference between expansions and predicates are when and how values are converted to strings. Since the goal of expansion is to produce a string, the template engine will treat all types but lists and maps as strings and if they aren’t they will be converted. In javascript all values are treated by type (object, string, array, number, etc).
Predicates are boolean JavaScript expressions that must return either true or false.
Predicates are primary used for controlling execution and for filtering and are always evaluated during runtime.
Context data that can be used in the expression are available in scopes, defined by the current context. Scopes follow the same structure as for expansion, but using JavaScript types.
A predicate MUST:
be a string ("..."
)
be valid JavaScript (ECMAScript 2023)
evaluate to a boolean value (true/false) or a function that returns a boolean value
Since predicates are JavaScript all features of JavaScript are supported including, but not limited to:
operators (==, !=, >, >=, <, <=
)
strict operators (===, !==
)
array indexing using bracket notation (arr[3]
)
property access using bracket notation (obj['property-name']
)
For more information about JavaScript, see: https://developer.mozilla.org/en-US/docs/Web/JavaScript
Extensions are libraries containing useful functions when working with predicates. For more information, see: Extensions
Scopes are the named top level objects containing context data (for example request
or session
). Available scopes depends on the context.
Data in scopes are accessed different depending on the type of objects included in the path, but adheres to the rules of JavaScript.
Property expansion is the process of replacing a value, or a part of a value, with the result of an expression.
The actual expression is a tag containing a (dot-separated) path to a named property.
Expansion expressions are written in the following format:
An expansion expression MUST:
be in string format ("..."
)
start with ${
end with }
contain only a (dot-separated) path to a property located in an available scope (depends on context).
Expansion expression MAY:
be embedded in a string
be combined
If an expansion expression path contains an array, elements are referenced using an index property (zero based, first element has index 0):
It is not recommended to use arrays in expansions since expressions becomes tied to the order of the array elements. Use objects instead with named properties (instead of index).
Scopes are the named top level objects containing expansion data (for example request
or session
). Available scopes depends on the context.
Data in scopes are accessed different depending on the type of objects included in the path. An expansion path can contain the following types of objects:
primitive types (string, number, etc)
objects
arrays
A primitive type is always a leaf (last element of an expansion path) and can only contain a value, not other primitives, object or arrays.
Objects can contain other objects, primitives and arrays. When objects are nested, we traverse them using a dot-separated path containing the
Arrays are list of primitives, objects or arrays. Elements in an array are referenced using index property notation, where the first element has index 0.
If an array contains complex types (objects or other arrays) and when properties in these elements are to be referenced, the following value-syntax must be used:
The value property of an array element is the actual value of the element whilst the index property of the array is the string representation of the element.
The value property is only used when traversing content of an array, not when targeting an element for expansion.
It is possible to type ("convert from string to specific type") the result of an expansion.
This is done by adding a type directive to the expansion expression:
The following types are currently supported
string (default)
number
int
long
float
double
boolean (alias: bool)
json
The primary use of typed expansion is when adding the result of an expansion (always a string) to a scope (session for example) where it is to be consumed by a component that requires a specific type. If the consumer is type agnostic, typed expansion is not necessary. In this case the consumer will handle the typing.
If an invalid type directive is specified, type will default to string (just like regular expansion).
Predicates and other script evaluation (like ScriptEvalValve) has support for extensions. An extension is a library of functions in a namespace.
The following extension are available by default:
str (common string operations)
mv (multi-value support)
dbg (debug)
Ipv4 (IPv4 address matching)
The str extension contains string helper function for validation and comparison.
Returns the size/length of a string. If the supplied value isn't a string, -1 is returned.
str.size(value)
Name | Type | Description |
---|
Returns true
if the supplied value is a string, otherwise false
.
str.isString(value)
Returns true
if the supplied value is null
/undefined
or an empty string (""
).
str.isNullOrEmpty(value)
Returns true
if the supplied value is a string and is not null
/undefined
or empty (""
).
str.isNotNullOrEmpty(value)
Returns true
if the supplied values are strings with identical content, possible with different case.
str.isEqual(s1, s2[, ignoreCase])
Returns true
if the supplied values are strings with identical content, always ignoring different case.
This function is equivalent to str.isEqual(s1, s2, true)
str.isEqualIgnoreCase(s1, s2)
Returns true
if the supplied value match any of the supplied regular expressions (regex).
str.matchAny(value, regex[,regex, ...])
Name | Type | Description |
---|
Name | Type | Description |
---|
Name | Type | Description |
---|
Name | Type | Description |
---|
Name | Type | Description |
---|
Name | Type | Description |
---|
|
| The value to check |
|
| The value to check |
|
| The value to check |
|
| The first string to compare for equality |
|
| The second string to compare for equality |
|
| Flag turning on case-insensitive compare (default: |
|
| The first string to compare for equality |
|
| The second string to compare for equality |
value |
| The value to match |
regex |
| One or more regular expressions used for matching. |
|
| The string whose length is calculated and returned. If empty, |
Extension for asserting IPv4 addresses
Returns true is the supplied IP belongs to the supplied subnet in CIDR notation.
Use this function to assert that a client belongs to a specific network.
IP-addresses should be octets in dotted-string format: '192.168.30.5'
Subnets are specified using CIDR notation containing an ip and the length of the subnet mask: '10.1.1.0/24'
ipv4.isInSubnet(ip, subnet)
Name | Type | Description |
---|---|---|
Script extension for multi value validation and comparison.
All functions operating on multi values will convert supplied value(s) to multi value if not already (see mv.from(value)
)
In JavaScript multi values are represented as arrays.
Converts a value to a multi value if not already.
Handles the following types of input values:
arrays (returned as is)
json arrays (parsed to array)
single values of any types (added as first element to new array)
mv.from(value)
Name | Type | Description |
---|
Returns the length of the supplied multi value.
mv.length(value)
Returns true
if the supplied multi value contains the supplied expected value, possibly ignoring the case (if values are strings).
Note: This function works exactly like mv.containsAny
but with support for only one expected value.
mv.contains(value, expected[, ignoreCase])
Returns true
if the supplied multi value contains at least one of the supplied expected values, possibly ignoring the case (if values are strings).
mv.containsAny(value, expected[, expected, ...][, ignoreCase])
Returns true
if the supplied multi value contains all of the supplied expected values, possibly ignoring the case (if values are strings).
mv.containsAll(value, expected[, expected, ...][, ignoreCase])
Returns true
if at least one value in the supplied multi value matches one or more of the supplied regex's.
Regex may be supplied as strings, regex-literals or RegExp objects.
Note: Case-insensitivity is controlled by regex flag ('i'
).
mv.matchAny(value, regex [,regex, ...])
Returns true
if the supplied multi values has exactly same content.
mv.equals(mv1, mv2)
Returns true
if the supplied multi value is not null/undefined and is empty.
mv.isEmpty(value)
Returns true
if the supplied multi value is not null/undefined and is not empty (has one or more elements).
mv.isNotEmpty(value)
Returns true
if the supplied multi value is null/undefined or is empty.
mv.isNullOrEmpty(value)
Returns true
if the supplied multi value is not null/undefined and is not empty (has one or more element).
mv.isNotNullOrEmpty(value)
Name | Type | Description |
---|
Name | Type | Description |
---|
Name | Type | Description |
---|
Name | Type | Description |
---|
Name | Type | Description |
---|
Name | Type | Description |
---|
Name | Type | Description |
---|
Name | Type | Description |
---|
Name | Type | Description |
---|
Name | Type | Description |
---|
ip
string
The IP-address in octets
subnet
string
The subnet in CIDR-notation
|
| The value to convert to multi value |
|
| The multi value whose length is to be calculated and returned. |
|
| The multi value whose content is to be asserted. |
|
| Value expected to be contained in value |
|
| Flag turning on string case insensitivity (default: |
|
| The multi value whose content is to be asserted. |
|
| One or more values expected to be contained in value |
|
| Flag turning on string case insensitivity (default: |
|
| The multi value whose content is to be asserted. |
|
| One or more values expected to be contained in value |
|
| Flag turning on string case insensitivity (default: |
|
| The multi value whose content is to be matched. |
|
| One or more regex to match against value. |
|
| The multi value whose content is to be matched. |
|
| One or more regex to match against value. |
|
| The multi value to assert |
|
| The multi value to assert |
|
| The multi value to assert |
|
| The multi value to assert |
Extension containing debug utilities
Describes a value, prints the result to stdout and returns the value.
Output will contain:
Type ('string'
, 'array'
, 'object'
, 'number'
, etc)
Value (concatenated to 32 chars)
Length (if applicable)
If value is an array (when type is 'object'
)
If value is JSON (when type is 'string'
)
JSON-type (when parsed)
JSON-length (when parsed)
dbg.describe(value[, label])
Name | Type | Description |
---|---|---|
value
any
The value to describe.