Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
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).
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).
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
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.
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}}
.
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:
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)
ip
string
The IP-address in octets
subnet
string
The subnet in CIDR-notation
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)
value
any
The value to convert to multi value
Returns the length of the supplied multi value.
mv.length(value)
value
any
The multi value whose length is to be calculated and returned.
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])
value
any
The multi value whose content is to be asserted.
expected
any
Value expected to be contained in value
ignoreCase
boolean
Flag turning on string case insensitivity (default: false
)
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])
value
any
The multi value whose content is to be asserted.
expected
any
One or more values expected to be contained in value
ignoreCase
boolean
Flag turning on string case insensitivity (default: false
)
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])
value
any
The multi value whose content is to be asserted.
expected
any
One or more values expected to be contained in value
ignoreCase
boolean
Flag turning on string case insensitivity (default: false
)
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, ...])
value
any
The multi value whose content is to be matched.
expected
any
One or more regex to match against value.
Returns true
if the supplied multi values has exactly same content.
mv.equals(mv1, mv2)
mv1
any
The multi value whose content is to be matched.
mv2
any
One or more regex to match against value.
Returns true
if the supplied multi value is not null/undefined and is empty.
mv.isEmpty(value)
value
any
The multi value to assert
Returns true
if the supplied multi value is not null/undefined and is not empty (has one or more elements).
mv.isNotEmpty(value)
value
any
The multi value to assert
Returns true
if the supplied multi value is null/undefined or is empty.
mv.isNullOrEmpty(value)
value
any
The multi value to assert
Returns true
if the supplied multi value is not null/undefined and is not empty (has one or more element).
mv.isNotNullOrEmpty(value)
value
any
The multi value to assert
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.
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)
value
string
The string whose length is calculated and returned. If empty, 0
is returned. If null, undefined or not a string, -1
is returned.
Returns true
if the supplied value is a string, otherwise false
.
str.isString(value)
value
string
The value to check
Returns true
if the supplied value is null
/undefined
or an empty string (""
).
str.isNullOrEmpty(value)
value
string
The value to check
Returns true
if the supplied value is a string and is not null
/undefined
or empty (""
).
str.isNotNullOrEmpty(value)
value
string
The value to check
Returns true
if the supplied values are strings with identical content, possible with different case.
str.isEqual(s1, s2[, ignoreCase])
s1
string
The first string to compare for equality
s2
string
The second string to compare for equality
ignoreCase
boolean
Flag turning on case-insensitive compare (default: false
)
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)
s1
string
The first string to compare for equality
s2
string
The second string to compare for equality
Returns true
if the supplied value match any of the supplied regular expressions (regex).
str.matchAny(value, regex[,regex, ...])
value
string
The value to match
regex
string | regex
One or more regular expressions used for matching.
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']
)
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.
For more information about JavaScript, see:
Extensions are libraries containing useful functions when working with predicates. For more information, see:
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])
value
any
The value to describe.