lib

package
v1.10.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 21, 2024 License: Apache-2.0 Imports: 41 Imported by: 3

Documentation

Overview

Package lib provides a set of extension libraries for the Common Expression Language intended to be used for message stream processing.

Index

Constants

View Source
const OptionalTypesVersion = 1

OptionalTypesVersion is the version of the optional types library used by mito.

Variables

This section is empty.

Functions

func CSVHeader

func CSVHeader(r io.Reader) ref.Val

CSVHeader provides a file transform that returns a <list<map<string,string>>> from an io.Reader holding text/csv data. It should be handed to the File or MIME lib with

File(map[string]interface{}{
	"text/csv; header=present": lib.CSVHeader,
})

or

MIME(map[string]interface{}{
	"text/csv; header=present": lib.CSVHeader,
})

It will then be able to be used in a file or mime call.

Example:

Given a file hello.csv:
   "first","second","third"
   1,2,3

file('hello.csv', 'text/csv; header=present')

will return:

[{"first": "1", "second": "2", "third": "3"}]

func CSVNoHeader

func CSVNoHeader(r io.Reader) ref.Val

CSVNoHeader provides a file transform that returns a <list<list<string>>> from an io.Reader holding text/csv data. It should be handed to the File or MIME lib with

File(map[string]interface{}{
	"text/csv; header=absent": lib.CSVNoHeader,
})

or

MIME(map[string]interface{}{
	"text/csv; header=absent": lib.CSVNoHeader,
})

It will then be able to be used in a file or mime call.

Example:

Given a file hello.csv:
   "first","second","third"
   1,2,3

file('hello.csv', 'text/csv; header=absent')

will return:

[["first", "second", "third"], ["1", "2", "3"]]

func Collections

func Collections() cel.EnvOption

Collections returns a cel.EnvOption to configure extended functions for handling collections.

As (Macro)

The as macro is syntactic sugar for [val].map(var, function)[0].

Examples:

{"a":1, "b":2}.as(v, v.a == 1)         // return true
{"a":1, "b":2}.as(v, v)                // return {"a":1, "b":2}
{"a":1, "b":2}.as(v, v.with({"c":3}))  // return {"a":1, "b":2, "c":3}
{"a":1, "b":2}.as(v, [v, v])           // return [{"a":1, "b":2}, {"a":1, "b":2}]

Collate

Returns a list of values obtained by traversing fields in the receiver with the path or paths given as the string parameter. When a list is traversed all children are include in the resulting list:

<list<dyn>>.collate(<string>) -> <list<dyn>>
<list<dyn>>.collate(<list<string>>) -> <list<dyn>>
<map<string,dyn>>.collate(<string>) -> <list<dyn>>
<map<string,dyn>>.collate(<list<string>>) -> <list<dyn>>

Examples:

Given v:
{
        "a": [
            {"b": 1},
            {"b": 2},
            {"b": 3}
        ],
        "b": [
            {"b": -1, "c": 10},
            {"b": -2, "c": 20},
            {"b": -3, "c": 30}
        ]
}

v.collate("a")             // return [{"b": 1}, {"b": 2}, {"b": 3}]
v.collate("a.b")           // return [1, 2, 3]
v.collate(["a.b", "b.b"])  // return [1, 2, 3, -1, -2, -3]
v.collate(["a", "b.b"])    // return [{"b": 1 }, {"b": 2 }, {"b": 3 }, -1, -2, -3 ]

If the the path to be dropped includes a dot, it can be escaped with a literal backslash. See drop below.

Drop

Returns the value of the receiver with the object at the given paths remove:

<list<dyn>>.drop(<string>) -> <list<dyn>>
<list<dyn>>.drop(<list<string>>) -> <list<dyn>>
<map<string,dyn>>.drop(<string>) -> <map<string,dyn>>
<map<string,dyn>>.drop(<list<string>>) -> <map<string,dyn>>

Examples:

Given v:
{
        "a": [
            {"b": 1},
            {"b": 2},
            {"b": 3}
        ],
        "b": [
            {"b": -1, "c": 10},
            {"b": -2, "c": 20},
            {"b": -3, "c": 30}
        ]
}

v.drop("a")             // return {"b": [{"b": -1, "c": 10}, {"b": -2, "c": 20}, {"b": -3, "c": 30}]}
v.drop("a.b")           // return {"a": [{}, {}, {}], "b": [{"b": -1, "c": 10}, {"b": -2, "c": 20}, {"b": -3, "c": 30}]}
v.drop(["a.b", "b.b"])  // return {"a": [{}, {}, {}], "b": [{"c": 10}, {"c": 20}, {"c": 30}]}
v.drop(["a", "b.b"])    // return {"b": [{"c": 10}, {"c": 20}, {"c": 30}]}

If the the path to be dropped includes a dot, it can be escaped with a literal backslash.

Examples:

Given v:
{
        "dotted.path": [
            {"b": -1, "c": 10},
            {"b": -2, "c": 20},
            {"b": -3, "c": 30}
        ]
}

v.drop("dotted\\.path.b")  // return {"dotted.path": [{"c": 10}, {"c": 20}, {"c": 30}]}

Drop Empty

Returns the value of the receiver with all empty lists and maps removed, recursively

<list<dyn>>.drop_empty() -> <list<dyn>>
<map<string,dyn>>.drop_empty() -> <map<string,dyn>>

Examples:

Given v:
{
        "a": [
            {},
            {},
            {}
        ],
        "b": [
            {"b": -1, "c": 10},
            {"b": -2, "c": 20},
            {"b": -3, "c": 30}
        ]
}

v.drop_empty()  // return {"b":[{"b":-1, "c":10}, {"b":-2, "c":20}, {"b":-3, "c":30}]}

Flatten

Returns a list of non-list objects resulting from the depth-first traversal of a nested list:

<list<dyn>...>.flatten() -> <list<dyn>>

Examples:

[[1],[2,3],[[[4]],[5,6]]].flatten()                     // return [1, 2, 3, 4, 5, 6]
[[{"a":1,"b":[10, 11]}],[2,3],[[[4]],[5,6]]].flatten()  // return [{"a":1, "b":[10, 11]}, 2, 3, 4, 5, 6]

Max

Returns the maximum value of a list of comparable objects:

<list<dyn>>.max() -> <dyn>
max(<list<dyn>>) -> <dyn>

Examples:

[1,2,3,4,5,6,7].max()  // return 7
max([1,2,3,4,5,6,7])   // return 7

Min

Returns the minimum value of a list of comparable objects:

<list<dyn>>.min() -> <dyn>
min(<list<dyn>>) -> <dyn>

Examples:

[1,2,3,4,5,6,7].min()  // return 1
min([1,2,3,4,5,6,7])   // return 1

With

Returns the receiver's value with the value of the parameter updating or adding fields:

<map<K,V>>.with(<map<K,V>>) -> <map<K,V>>

Examples:

{"a":1, "b":2}.with({"a":10, "c":3})  // return {"a":10, "b":2, "c":3}

With Replace

Returns the receiver's value with the value of the parameter replacing existing fields:

<map<K,V>>.with(<map<K,V>>) -> <map<K,V>>

Examples:

{"a":1, "b":2}.with({"a":10, "c":3})  // return {"a":10, "b":2}

With Update

Returns the receiver's value with the value of the parameter updating the map without replacing any existing fields:

<map<K,V>>.with(<map<K,V>>) -> <map<K,V>>

Examples:

{"a":1, "b":2}.with({"a":10, "c":3})  // return {"a":1, "b":2, "c":3}

Zip

Returns a map keyed on elements of a list with values from another equally sized list:

zip(<list<K>>, <list<V>>) -> <map<K,V>>
<list<K>>.zip(<list<V>>) -> <map<K,V>>

Examples:

zip(["a", "b"], [1, 2])  // return {"a":1, "b":2}
["a", "b"].zip([1, 2])   // return {"a":1, "b":2}

Keys

Returns a list of keys from a map:

keys(<map<dyn,dyn>>) -> <list<dyn>>
<map<dyn,dyn>>.keys() -> <list<dyn>>

Examples:

keys({"a":1, "b":2})   // return ["a", "b"]
{1:"a", 2:"b"}.keys()   // return [1, 2]

Values

Returns a list of values from a map:

values(<map<dyn,dyn>>) -> <list<dyn>>
<map<dyn,dyn>>.values() -> <list<dyn>>

Examples:

values({"a":1, "b":2})   // return [1, 2]
{1:"a", 2:"b"}.values()   // return ["a", "b"]

func Crypto

func Crypto() cel.EnvOption

Crypto returns a cel.EnvOption to configure extended functions for cryptographic hash functions and encoding.

Base64

Returns a string of the base64 encoding of a string or bytes:

base64(<bytes>) -> <string>
base64(<string>) -> <string>
<bytes>.base64() -> <string>
<string>.base64() -> <string>

Examples:

"hello world".base64()  // return "aGVsbG8gd29ybGQ="

Base64 Decode

Returns a bytes from the base64 encoding in a string:

base64_decode(<string>) -> <bytes>
<string>.base64_decode() -> <bytes>

Examples:

"aGVsbG8gd29ybGQ=".base64_decode()  // return b"hello world"

Base64 Raw

Returns a string of the raw unpadded base64 encoding of a string or bytes:

base64_raw(<bytes>) -> <string>
base64_raw(<string>) -> <string>
<bytes>.base64_raw() -> <string>
<string>.base64_raw() -> <string>

Examples:

"hello world".base64_raw()  // return "aGVsbG8gd29ybGQ"

Base64 Raw Decode

Returns a bytes from the raw base64 encoding in a string:

base64_raw_decode(<string>) -> <bytes>
<string>.base64_raw_decode() -> <bytes>

Examples:

"aGVsbG8gd29ybGQ".base64_raw_decode()  // return b"hello world"

Hex

Returns a string of the hexadecimal representation of a string or bytes:

hex(<bytes>) -> <string>
hex(<string>) -> <string>
<bytes>.hex() -> <string>
<string>.hex() -> <string>

Examples:

"hello world".hex()  // return "68656c6c6f20776f726c64"

MD5

Returns a bytes of the md5 hash of a string or bytes:

md5(<bytes>) -> <bytes>
md5(<string>) -> <bytes>
<bytes>.md5() -> <bytes>
<string>.md5() -> <bytes>

Examples:

"hello world".md5()       // return "XrY7u+Ae7tCTyyK7j1rNww=="
"hello world".md5().hex() // return "5eb63bbbe01eeed093cb22bb8f5acdc3"

SHA-1

Returns a bytes of the sha-1 hash of a string or bytes:

sha1(<bytes>) -> <bytes>
sha1(<string>) -> <bytes>
<bytes>.sha1() -> <bytes>
<string>.sha1() -> <bytes>

Examples:

"hello world".sha1()       // return "Kq5sNclPz7QV2+lfQIuc6R7oRu0="
"hello world".sha1().hex() // return "2aae6c35c94fcfb415dbe95f408b9ce91ee846ed"

SHA-256

Returns a bytes of the sha-256 cryptographic hash of a string or bytes:

sha256(<bytes>) -> <bytes>
sha256(<string>) -> <bytes>
<bytes>.sha256() -> <bytes>
<string>.sha256() -> <bytes>

Examples:

"hello world".sha1()        // return "uU0nuZNNPgilLlLX2n2r+sSE7+N6U4DukIj3rOLvzek="
"hello world".sha1().hex()  // return "b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9"

HMAC

Returns a bytes of the HMAC keyed MAC of a string or bytes using either the sha-1 or sha-256 hash function depending on the the second parameter:

hmac(<bytes>, <string>, <bytes>) -> <bytes>
hmac(<string>, <string>, <bytes>) -> <bytes>
<bytes>.hmac(<string>, <bytes>) -> <bytes>
<string>.hmac(<string>, <bytes>) -> <bytes>

Examples:

"hello world".hmac("sha256", b"key")        // return "C6BvH5pjAEYeQ0VFNdw8QiPkex01cHPXU26ukOwJW+E="
"hello world".hmac("sha256", b"key").hex()  // return "0ba06f1f9a6300461e43454535dc3c4223e47b1d357073d7536eae90ec095be1"

UUID

Returns a string of a random (Version 4) UUID based on the the Go crypto/rand source:

uuid() -> <string>

Examples:

uuid()  // return "582fc58b-f983-4c35-abb1-65c507c1dc0c"

func Debug added in v1.6.0

func Debug(handler func(tag string, value any)) cel.EnvOption

Debug returns a cel.EnvOption to configure extended functions for allowing intermediate values to be logged without disrupting program flow.

The debug function will pass errors through without halting the program's execution. If the value cannot be serialised, an error will be passed to the handler.

Debug

The second parameter is returned unaltered and the value is logged to the lib's logger:

debug(<string>, <dyn>) -> <dyn>

Examples:

debug("tag", expr) // return expr even if it is an error and logs with "tag".

func DraftRateLimit

func DraftRateLimit(h http.Header, window time.Duration) map[string]interface{}

DraftRateLimit implements the draft rate limit policy translation. It should be handed to the Limit lib with

Limit(map[string]lib.LimitPolicy{
	"draft": lib.DraftRateLimit,
})

It will then be able to be used in a limit call where the duration is the default quota window.

Example:

rate_limit(h, 'draft', duration('60s'))

might return something like:

{
    "burst": 1,
    "headers": "Rate-Limit-Limit=\"5000\" Rate-Limit-Remaining=\"100\" Rate-Limit-Reset=\"Sat, 16 Apr 2022 07:48:40 GMT\"",
    "next": 83.33333333333333,
    "rate": 0.16689431007474315,
    "reset": "2022-04-16T07:48:40Z"
}

or

{
    "burst": 1000,
    "headers": "Rate-Limit-Limit=\"12, 12;window=1; burst=1000;policy=\\\"leaky bucket\\\"\" Rate-Limit-Remaining=\"100\" Rate-Limit-Reset=\"Sat, 16 Apr 2022 07:48:40 GMT\"",
    "next": 12,
    "rate": 100,
    "reset": "2022-04-16T07:48:40Z"
}

See https://datatracker.ietf.org/doc/html/draft-polli-ratelimit-headers-00

func File

func File(mimetypes map[string]interface{}) cel.EnvOption

File returns a cel.EnvOption to configure extended functions for reading files. It takes a mapping of mimetypes to transforms to allow reading specific mime type. The values in the map must be one of: func([]byte), func(io.Reader) io.Reader, func(io.Reader) (io.Reader, error) or func(io.Reader) ref.Val. If the transform is func([]byte) it is expected to mutate the bytes in place.

Dir

dir returns either a directory for the provided path:

dir(<string>) -> <list<map<string,dyn>>>

Examples:

dir('subdir')

will return something like:

[
    {
        "is_dir": true,
        "mod_time": "2022-04-05T20:53:11.923840504+09:30",
        "name": "subsubdir",
        "size": 4096
    },
    {
        "is_dir": false,
        "mod_time": "2022-04-05T20:53:11.923840504+09:30",
        "name": "a.txt",
        "size": 13
    },
    {
        "is_dir": false,
        "mod_time": "2022-04-05T20:53:11.923840504+09:30",
        "name": "b.txt",
        "size": 11
    }
]

File

file returns either a <bytes> or a <dyn> depending on whether it is called with one parameter or two:

file(<string>) -> <bytes>
file(<string>, <string>) -> <dyn>

The first parameter is a file path and the second is a look-up into the transforms map provided by to the File cel.EnvOption.

Examples:

Given a file hello.txt:
   world!

And the following transforms map (rot13 is a transforming reader):

   map[string]interface{}{
       "text/rot13": func(r io.Reader) io.Reader { return rot13{r} },
       "text/upper": func(p []byte) {
           for i, b := range p {
               if 'a' <= b && b <= 'z' {
                   p[i] &^= 'a' - 'A'
               }
           }
       },
   }

string(file('hello.txt'))                 // return "world!\n"
string(file('hello.txt', 'text/rot13'))   // return "jbeyq!\n"
string(file('hello.txt', 'text/upper'))   // return "WORLD!\n"

func Globals

func Globals(vars map[string]interface{}) cel.EnvOption

Globals returns a cel.EnvOption to configure global variables for the environment. Each variable will be visible as the key in the vars map. Not all Go variable types are acceptable to the CEL environment, but Globals will make a best-effort to map types to their CEL equivalents. This typing is only done for the values in the map and does not apply recursively if those values are nested.

func HTTP

func HTTP(client *http.Client, limit *rate.Limiter, auth *BasicAuth) cel.EnvOption

HTTP returns a cel.EnvOption to configure extended functions for HTTP requests. Requests and responses are returned as maps corresponding to the Go http.Request and http.Response structs. The client and limit parameters will be used for the requests and API rate limiting. If client is nil the http.DefaultClient will be used and if limit is nil an non-limiting rate.Limiter will be used. If auth is not nil, the Authorization header is populated for Basic Authentication in requests constructed for direct HEAD, GET and POST method calls. Explicitly constructed requests used in do_request are not affected by auth. In cases where Basic Authentication is needed for these constructed requests, the basic_authentication method can be used to add the necessary header.

HEAD

head performs a HEAD method request and returns the result:

head(<string>) -> <map<string,dyn>>

Example:

head('http://www.example.com/')  // returns {"Body": "", "Close": false,

GET

get performs a GET method request and returns the result:

get(<string>) -> <map<string,dyn>>

Example:

get('http://www.example.com/')  // returns {"Body": "PCFkb2N0e...

GET Request

get_request returns a GET method request:

get_request(<string>) -> <map<string,dyn>>

Example:

get_request('http://www.example.com/')

will return:

{
    "Close": false,
    "ContentLength": 0,
    "Header": {},
    "Host": "www.example.com",
    "Method": "GET",
    "Proto": "HTTP/1.1",
    "ProtoMajor": 1,
    "ProtoMinor": 1,
    "URL": "http://www.example.com/"
}

POST

post performs a POST method request and returns the result:

post(<string>, <string>, <bytes>) -> <map<string,dyn>>
post(<string>, <string>, <string>) -> <map<string,dyn>>

Example:

post("http://www.example.com/", "text/plain", "test")  // returns {"Body": "PCFkb2N0e...

POST Request

post_request returns a POST method request:

post_request(<string>, <string>, <bytes>) -> <map<string,dyn>>
post_request(<string>, <string>, <string>) -> <map<string,dyn>>

Example:

post_request("http://www.example.com/", "text/plain", "test")

will return:

{
    "Body": "test",
    "Close": false,
    "ContentLength": 4,
    "Header": {
        "Content-Type": [
            "text/plain"
        ]
    },
    "Host": "www.example.com",
    "Method": "POST",
    "Proto": "HTTP/1.1",
    "ProtoMajor": 1,
    "ProtoMinor": 1,
    "URL": "http://www.example.com/"
}

Request

request returns a user-defined method request:

request(<string>, <string>) -> <map<string,dyn>>
request(<string>, <string>, <bytes>) -> <map<string,dyn>>
request(<string>, <string>, <string>) -> <map<string,dyn>>

Example:

request("GET", "http://www.example.com/").with({"Header":{
    "Authorization": ["Basic "+string(base64("username:password"))],
}})

will return:

{
    "Close": false,
    "ContentLength": 0,
    "Header": {
        "Authorization": [
            "Basic dXNlcm5hbWU6cGFzc3dvcmQ="
        ]
    },
    "Host": "www.example.com",
    "Method": "GET",
    "Proto": "HTTP/1.1",
    "ProtoMajor": 1,
    "ProtoMinor": 1,
    "URL": "http://www.example.com/"
}

Basic Authentication

basic_authentication adds a Basic Authentication Authorization header to a request, returning the modified request.

<map<string,dyn>>.basic_authentication(<string>, <string>) -> <map<string,dyn>>

Example:

request("GET", "http://www.example.com/").basic_authentication("username", "password")

will return:

{
    "Close": false,
    "ContentLength": 0,
    "Header": {
        "Authorization": [
            "Basic dXNlcm5hbWU6cGFzc3dvcmQ="
        ]
    },
    "Host": "www.example.com",
    "Method": "GET",
    "Proto": "HTTP/1.1",
    "ProtoMajor": 1,
    "ProtoMinor": 1,
    "URL": "http://www.example.com/"
}

Do Request

do_request executes an HTTP request:

<map<string,dyn>>.do_request() -> <map<string,dyn>>

Example:

get_request("http://www.example.com/").do_request()  // returns {"Body": "PCFkb2N0e...

Parse URL

parse_url returns a map holding the details of the parsed URL corresponding to the Go url.URL struct:

<string>.parse_url() -> <map<string,dyn>>

Example:

"https://pkg.go.dev/net/url#URL".parse_url()

will return:

{
    "ForceQuery": false,
    "Fragment": "URL",
    "Host": "pkg.go.dev",
    "Opaque": "",
    "Path": "/net/url",
    "RawFragment": "",
    "RawPath": "",
    "RawQuery": "",
    "Scheme": "https",
    "User": null
}

Format URL

format_url returns string corresponding to the URL map that is the receiver:

<map<string,dyn>>.format_url() -> <string>

Example:

"https://pkg.go.dev/net/url#URL".parse_url().with_replace({"Host": "godoc.org"}).format_url()

will return:

"https://godoc.org/net/url#URL"

Parse Query

parse_query returns a map holding the details of the parsed query corresponding to the Go url.Values map:

<string>.parse_query() -> <map<string,<list<string>>>

Example:

"page=1&line=25".parse_url()

will return:

{
    "line": ["25"],
    "page": ["1"]
}

Format Query

format_query returns string corresponding to the query map that is the receiver:

<map<string,<list<string>>>.format_query() -> <string>

Example:

"page=1&line=25".parse_query().with_replace({"page":[string(2)]}).format_query()

will return:

line=25&page=2"

func HTTPWithContext

func HTTPWithContext(ctx context.Context, client *http.Client, limit *rate.Limiter, auth *BasicAuth) cel.EnvOption

HTTPWithContext returns a cel.EnvOption to configure extended functions for HTTP requests that include a context.Context in network requests.

func JSON

func JSON(adapter ref.TypeAdapter) cel.EnvOption

JSON returns a cel.EnvOption to configure extended functions for JSON coding and decoding. The parameter specifies the CEL type adapter to use. A nil adapter is valid an will give an option using the default type adapter, types.DefaultTypeAdapter.

Encode JSON

encode_json returns a string of the JSON encoding of the receiver or parameter:

encode_json(<dyn>) -> <string>
<dyn>.encode_json() -> <string>

Examples:

{"a":1, "b":[1, 2, 3]}.encode_json()  // return "{\"a\":1,\"b\":[1,2,3]}"
encode_json({"a":1, "b":[1, 2, 3]})   // return "{\"a\":1,\"b\":[1,2,3]}"

Decode JSON

decode_json returns the object described by the JSON encoding of the receiver or parameter:

<bytes>.decode_json() -> <dyn>
<string>.decode_json() -> <dyn>
decode_json(<bytes>) -> <dyn>
decode_json(<string>) -> <dyn>

Examples:

"{\"a\":1,\"b\":[1,2,3]}".decode_json()   // return {"a":1, "b":[1, 2, 3]}
b"{\"a\":1,\"b\":[1,2,3]}".decode_json()  // return {"a":1, "b":[1, 2, 3]}

Decode JSON Stream

decode_json_stream returns a list of objects described by the JSON stream of the receiver or parameter:

<bytes>.decode_json_stream() -> <list<dyn>>
<string>.decode_json_stream() -> <list<dyn>>
decode_json_stream(<bytes>) -> <list<dyn>>
decode_json_stream(<string>) -> <list<dyn>>

Examples:

'{"a":1}{"b":2}'.decode_json_stream()   // return [{"a":1}, {"b":2}]
b'{"a":1}{"b":2}'.decode_json_stream()  // return [{"a":1}, {"b":2}]

func Limit

func Limit(policy map[string]LimitPolicy) cel.EnvOption

Limit returns a cel.EnvOption to configure extended functions for interpreting request rate limit policies.

It takes a mapping of policy names to policy interpreters to allow implementing specific rate limit policies. The map returned by the policy functions should have "rate" and "next" fields with type rate.Limit or string with the value "inf", a "burst" field with type int and a "reset" field with type time.Time in the UTC location. The semantics of "rate" and "burst" are described in the documentation for the golang.org/x/time/rate package.

The map may have other fields that can be logged. If a field named "error" exists it should be a string with an error message indicating the result can not be used.

Rate Limit

rate_limit returns <map<string,dyn>> interpreted through the registered rate limit policy or with a generalised policy constructor:

rate_limit(<map<string,dyn>>, <string>, <duration>) -> <map<string,dyn>>
rate_limit(<map<string,dyn>>, <string>, <bool>, <bool>, <duration>, <int>) -> <map<string,dyn>>

In the first form the string is the policy name and the duration is the default quota window to use in the absence of window information from headers.

In the second form the parameters are the header, the prefix for the rate limit header keys, whether the keys are canonically formatted MIME header keys, whether the reset header is a delta as opposed to a timestamp, the duration of the quota window, and the burst rate. rate_limit in the second form will never set a burst rate to zero.

In all cases if any of the three rate limit headers is missing the rate_limit call returns a map with only the headers written. This should be considered an error condition.

Examples:

rate_limit(h, 'okta', duration('1m'))
rate_limit(h, 'draft', duration('1m'))

// Similar semantics to the okta policy.
rate_limit(h, 'X-Rate-Limit', true, false, duration('1s'), 1)

// Similar semantics to the draft policy in the simplest case.
rate_limit(h, 'Rate-Limit', true, true, duration('1s'), 1)

// Non-canonical keys.
rate_limit(h, 'X-RateLimit', false, false, duration('1s'), 1)

func MIME

func MIME(mimetypes map[string]interface{}) cel.EnvOption

MIME returns a cel.EnvOption to configure extended functions for reading files. It takes a mapping of mimetypes to transforms to allow interpreting specific mime type. The values in the map must be one of: func([]byte), func(io.Reader) io.Reader, func(io.Reader) (io.Reader, error) or func(io.Reader) ref.Val. If the transform is func([]byte) it is expected to mutate the bytes in place.

MIME

mime returns <dyn> interpreted through the registered MIME type:

<bytes>.mime(<string>) -> <dyn>

Examples:

string(b"hello world!".mime("text/rot13"))  // return "uryyb jbeyq!"
string(b"hello world!".mime("text/upper"))  // return "HELLO WORLD!"
string(b"\x1f\x8b\b\x00\x00\x00\x00\x00\x00\xff\xcaH\xcd\xc9\xc9W(\xcf/\xcaIQ\x04\x04\x00\x00\xff\xffm´\x03\f\x00\x00\x00"
    .mime("application/gzip"))  // return "hello world!"

See also File and NDJSON.

func NDJSON

func NDJSON(r io.Reader) ref.Val

NDJSON provides a file transform that returns a <list<dyn>> from an io.Reader holding ND-JSON data. It should be handed to the File or MIME lib with

File(map[string]interface{}{
	"application/x-ndjson": lib.NDJSON,
})

or

MIME(map[string]interface{}{
	"application/x-ndjson": lib.NDJSON,
})

It will then be able to be used in a file or mime call.

Example:

Given a file hello.ndjson:
   {"message":"hello"}
   {"message":"world"}

file('hello.ndjson', 'application/x-ndjson')

will return:

[
    {
        "message": "hello"
    },
    {
        "message": "world"
    }
]

Messages in the ND-JSON stream that are invalid will be added to the list as CEL errors and will need to be processed using the try function.

Example:

Given a file hello.ndjson:
   {"message":"hello"}
   {"message":"oops"
   {"message":"world"}

file('hello.ndjson', 'application/x-ndjson').map(e, try(e, "error.message"))

will return:

[
    {
        "message": "hello"
    },
    {
        "error.message": "unexpected end of JSON input: {\"message\":\"oops\""
    },
    {
        "message": "world"
    }
]

func OktaRateLimit

func OktaRateLimit(h http.Header, window time.Duration) map[string]interface{}

OktaRateLimit implements the Okta rate limit policy translation. It should be handed to the Limit lib with

Limit(map[string]lib.LimitPolicy{
	"okta": lib.OktaRateLimit,
})

It will then be able to be used in a limit call with the window duration given by the Okta documentation.

Example:

rate_limit(h, 'okta', duration('1m'))

might return:

{
    "burst": 1,
    "headers": "X-Rate-Limit-Limit=\"600\" X-Rate-Limit-Remaining=\"598\" X-Rate-Limit-Reset=\"1650094960\"",
    "next": 10,
    "rate": 0.9975873271836141,
    "reset": "2022-04-16T07:48:40Z"
},

See https://developer.okta.com/docs/reference/rl-best-practices/

func Regexp

func Regexp(patterns map[string]*regexp.Regexp) cel.EnvOption

Regexp returns a cel.EnvOption to configure extended functions for using regular expressions on strings and bytes. It takes a mapping of names to Go regular expressions. The names are used to specify the pattern in the CEL regexp call.

Each function corresponds to methods on regexp.Regexp in the Go standard library.

For the examples below assume an input patterns map:

map[string]*regexp.Regexp{
    "foo":     regexp.MustCompile("foo(.)"),
    "foo_rep": regexp.MustCompile("(f)oo([ld])"),
}

RE Match

Returns whether the named pattern matches the receiver:

<bytes>.re_match(<string>) -> <bool>
<string>.re_match(<string>) -> <bool>

Examples:

'food'.re_match('foo')    // return true
b'food'.re_match(b'foo')  // return true

RE Find

Returns a string or bytes of the named pattern's match:

<bytes>.re_find(<string>) -> <bytes>
<string>.re_find(<string>) -> <string>

Examples:

'food'.re_find('foo')    // return "food"
b'food'.re_find(b'foo')  // return "Zm9vZA=="

RE Find All

Returns a list of strings or bytes of all the named pattern's matches:

<bytes>.re_find_all(<string>) -> <list<bytes>>
<string>.re_find_all(<string>) -> <list<string>>

Examples:

'food fool'.re_find_all('foo')  // return ["food", "fool"]
b'food fool'.re_find_all(b'foo')  // return ["Zm9vZA==", "Zm9vZA=="]

RE Find Submatch

Returns a list of strings or bytes of the named pattern's submatches:

<bytes>.re_find_submatch(<string>) -> <list<bytes>>
<string>.re_find_submatch(<string>) -> <list<string>>

Examples:

'food fool'.re_find_submatch('foo')   // return ["food", "d"]
b'food fool'.re_find_submatch('foo')  // return ["Zm9vZA==", "ZA=="]

RE Find All Submatch

Returns a list of lists of strings or bytes of all the named pattern's submatches:

<bytes>.re_find_all_submatch(<string>) -> <list<list<bytes>>>
<string>.re_find_all_submatch(<string>) -> <list<list<string>>>

Examples:

'food fool'.re_find_all_submatch('foo')  // return [["food", "d"], ["fool", "l"]]

RE Replace All

Returns a strings or bytes applying a replacement to all matches of the named pattern:

<bytes>.re_replace_all(<string>, <bytes>) -> <bytes>
<string>.re_replace_all(<string>, <string>) -> <string>

Examples:

'food fool'.re_replace_all('foo_rep', '${1}u${2}')    // return "fud ful"
b'food fool'.re_replace_all('foo_rep', b'${1}u${2}')  // return "ZnVkIGZ1bA=="

func Send

func Send(ch map[string]chan interface{}) cel.EnvOption

Send returns a cel.EnvOption to configure extended functions for sending values on a Go channel during expression evaluation. The channel should be received from by a goroutine running in the host program. Send to calls will allow error values to be passed as arguments in the <dyn> position.

Send ref.Val To

Sends a value as a ref.Val to the named channel and returns the value:

<dyn>.send_to(<string>) -> <dyn>
send_to(<dyn>, <string>) -> <dyn>

Send To

Sends a value to the named channel and returns the value:

<dyn>.send_to(<string>) -> <dyn>
send_to(<dyn>, <string>) -> <dyn>

Close

Closes the named channel and returns true. It will cause an error if the same name is closed more than once in an expression. The dyn received is ignored.

<dyn>.close(<string>) -> <bool>

func Strings

func Strings() cel.EnvOption

Strings returns a cel.EnvOption to configure extended functions for handling strings.

All functions provided by Strings are methods on the string type or list<string> type with the exception of to_valid_utf8 and valid_utf8 which are methods on the bytes type.

Relevant documentation for the methods can obtained from the Go standard library. In all cases the first parameter in the Go function corresponds to the CEL method receiver.

String Methods

  • compare: strings.Compare(a, b string) int
  • contains_substr: strings.Contains(s, substr string) bool
  • contained_any: strings.ContainsAny(s, chars string) bool
  • count: strings.Count(s, substr string) int
  • equal_fold: strings.EqualFold(s, t string) bool
  • fields: strings.Fields(s string) []string
  • has_prefix: strings.HasPrefix(s, prefix string) bool
  • has_suffix: strings.HasSuffix(s, suffix string) bool
  • index: strings.Index(s, substr string) int
  • index_any: strings.IndexAny(s, chars string) int
  • last_index: strings.LastIndex(s, substr string) int
  • last_index_any: strings.LastIndexAny(s, chars string) int
  • repeat: strings.Repeat(s string, count int) string
  • replace: strings.Replace(s, old, new string, n int) string
  • replace_all: strings.ReplaceAll(s, old, new string) string
  • split: strings.Split(s, sep string) []string
  • split_after: strings.SplitAfter(s, sep string) []string
  • split_after_n: strings.SplitAfterN(s, sep string, n int) []string
  • split_n: strings.SplitN(s, sep string, n int) []string
  • to_lower: strings.ToLower(s string) string
  • to_title: strings.ToTitle(s string) string
  • to_upper: strings.ToUpper(s string) string
  • trim: strings.Trim(s, cutset string) string
  • trim_left: strings.TrimLeft(s, cutset string) string
  • trim_prefix: strings.TrimPrefix(s, prefix string) string
  • trim_right: strings.TrimRight(s, cutset string) string
  • trim_space: strings.TrimSpace(s string) string
  • trim_suffix: strings.TrimSuffix(s, suffix string) string

In addition to the strings package functions, a sub-string method is provided that allows string slicing at unicode code point boundaries. It differs from Go's string slicing operator which may slice within a code point resulting in invalid UTF-8. The substring method will always return a valid UTF-8 string, or an error if the indexes are out of bounds or invalid.

  • substring: s[start:end]

String List Methods

  • join: strings.Join(elems []string, sep string) string

Bytes Methods

The to_valid_utf8 method is equivalent to strings.ToValidUTF8 with the receiver first converted to a Go string. This special case is required as CEL does not permit invalid UTF-8 string conversions.

  • to_valid_utf8: strings.ToValidUTF8(s, replacement string) string
  • valid_utf8: utf8.Valid(s []byte) bool

func Time

func Time() cel.EnvOption

Time returns a cel.EnvOption to configure extended functions for handling timestamps.

Now (function)

Returns a timestamp for when the call was made:

now() -> <timestamp>

Examples:

now()  // return "2022-03-30T11:17:57.078390759Z"

Now (Global Variable)

Returns a timestamp for when the expression evaluation started:

now -> <timestamp>

Examples:

now  // return "2022-03-30T11:17:57.078389559Z"

Format

Returns a string representation of the timestamp formatted according to the provided layout:

<timestamp>.format(<string>) -> <string>

Examples:

now().format(time_layout.Kitchen)  // return "11:17AM"

Parse Time

Returns a timestamp from a string based on a time layout or list of possible layouts. If a list of formats is provided, the first successful layout is used:

<string>.parse_time(<string>) -> <timestamp>
<string>.parse_time(<list<string>>) -> <timestamp>

Examples:

"11:17AM".parse_time(time_layout.Kitchen)                       // return <timestamp>
"11:17AM".parse_time([time_layout.RFC3339,time_layout.Kitchen]) // return <timestamp>
"11:17AM".parse_time(time_layout.RFC3339)                       // return error

Global Variables

A collection of global variable are provided to give access to the start time of the evaluation and to the time formatting layouts provided by the Go standard library time package.

"now": <timestamp of evaluation start>,
"time_layout": {
    "Layout":      time.Layout,
    "ANSIC":       time.ANSIC,
    "UnixDate":    time.UnixDate,
    "RubyDate":    time.RubyDate,
    "RFC822":      time.RFC822,
    "RFC822Z":     time.RFC822Z,
    "RFC850":      time.RFC850,
    "RFC1123":     time.RFC1123,
    "RFC1123Z":    time.RFC1123Z,
    "RFC3339":     time.RFC3339,
    "RFC3339Nano": time.RFC3339Nano,
    "Kitchen":     time.Kitchen,
    "Stamp":       time.Stamp,
    "StampMilli":  time.StampMilli,
    "StampMicro":  time.StampMicro,
    "StampNano":   time.StampNano,
    "HTTP":        http.TimeFormat
}

func Try

func Try() cel.EnvOption

Try returns a cel.EnvOption to configure extended functions for allowing errors to be weakened to strings or objects.

Try

try returns either passes a value through unaltered if it is valid and not an error, or it returns a string or object describing the error:

try(<error>) -> <map<string,string>>
try(<dyn>) -> <dyn>
try(<error>, <string>) -> <map<string,string>>
try(<dyn>, <string>) -> <dyn>

Examples:

try(0/1)            // return 0
try(0/0)            // return "division by zero"
try(0/0, "error")   // return {"error": "division by zero"}

Is Error

is_error returns a bool indicating whether the argument is an error:

is_error(<dyn>) -> <bool>

Examples:

is_error(0/1)            // return false
is_error(0/0)            // return true

func XML

func XML(adapter ref.TypeAdapter, xsd map[string]string) (cel.EnvOption, error)

XML returns a cel.EnvOption to configure extended functions for XML decoding. The parameter specifies the CEL type adapter to use and a map of names to XSD document descriptions. A nil adapter is valid and will give an option using the default type adapter, types.DefaultTypeAdapter. A nil XSD mapping is valid and will give an option that performs best effort decoding leaving all values as strings and elevating elements to lists when more than one item is found for the path.

Decode XML

decode_xml returns the object described by the XML encoding of the receiver or parameter, using an optional named XSD:

<bytes>.decode_xml() -> <dyn>
<string>.decode_xml() -> <dyn>
decode_xml(<bytes>) -> <dyn>
decode_xml(<string>) -> <dyn>
<bytes>.decode_xml(<string>) -> <dyn>
<string>.decode_xml(<string>) -> <dyn>
decode_xml(<bytes>, <string>) -> <dyn>
decode_xml(<string>, <string>) -> <dyn>

Examples:

"<?xml vers... ...>".decode_xml()   // return { ... }
b"<?xml vers... ...>".decode_xml()   // return { ... }
"<?xml vers... ...>".decode_xml("xsd")   // return { ... }
b"<?xml vers... ...>".decode_xml("xsd")   // return { ... }

func Zip

func Zip(r io.Reader) ref.Val

Zip provides a file transform that returns a <map<dyn>> from an io.Reader holding a zip archive data. It should be handed to the File or MIME lib with

File(map[string]interface{}{
	"application/zip": lib.Zip,
})

or

MIME(map[string]interface{}{
	"application/zip": lib.Zip,
})

It will then be able to be used in a file or mime call.

The returned map reflects the structure of the Go zip.Reader struct.

Example:

file('hello.zip', 'application/zip')

might return:

{
    "Comment": "hello zip file"
    "File": [
        {
            "CRC32": 0,
            "Comment": "",
            "Data": "",
            "Extra": "VVQFAAMCCFhidXgLAAEE6AMAAAToAwAA",
            "IsDir": true,
            "Modified": "2022-04-14T21:09:46+09:30",
            "Name": "subdir/",
            "NonUTF8": false,
            "Size": 0
        },
        {
            "CRC32": 30912436,
            "Comment": "",
            "Data": "aGVsbG8gd29ybGQhCg==",
            "Extra": "VVQFAAP0B1hidXgLAAEE6AMAAAToAwAA",
            "IsDir": false,
            "Modified": "2022-04-14T21:09:32+09:30",
            "Name": "subdir/a.txt",
            "NonUTF8": false,
            "Size": 13
        }
    ]
}

Note that the entire contents of the zip file is expanded into memory.

Types

type BasicAuth

type BasicAuth struct {
	Username, Password string
}

BasicAuth is used to populate the Authorization header to use HTTP Basic Authentication with the provided username and password for direct HTTP method calls.

type DecoratedError added in v1.8.0

type DecoratedError struct {
	AST *cel.Ast
	Err error
}

DecoratedError implements error source location rendering.

func (DecoratedError) Error added in v1.8.0

func (e DecoratedError) Error() string

type LimitPolicy

type LimitPolicy func(header http.Header, window time.Duration) map[string]interface{}

Directories

Path Synopsis
Package xml provides an XSD-based dynamically typed xml decoder.
Package xml provides an XSD-based dynamically typed xml decoder.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL