Skip to content

Commit

Permalink
More hcl functions (#455)
Browse files Browse the repository at this point in the history
* added to_number() function

* added contains() function

* added length() function

* added join() function

* added keys() function

* added set_intersection() function

* go fmt

* added lookup() function

* added tests for some error cases

* documentation for new HCL functions

* changelog entry for new HCL functions

* corrected lookup function documentation
  • Loading branch information
johakoch authored Mar 21, 2022
1 parent b613096 commit 45ee7e8
Show file tree
Hide file tree
Showing 5 changed files with 385 additions and 14 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ Unreleased changes are available as `avenga/couper:edge` container.
* `beta_scope_map` attribute for the [JWT Block](./docs/REFERENCE.md#jwt-block) ([#434](https://github.com/avenga/couper/pull/434))
* `saml` [error type](./docs/ERRORS.md#error-types) ([#424](https://github.com/avenga/couper/pull/424))
* `allowed_methods` attribute for the [API](./docs/REFERENCE.md#api-block) or [Endpoint Block](./docs/REFERENCE.md#endpoint-block) ([#444](https://github.com/avenga/couper/pull/444))
* new HCL functions: `contains()`, `join()`, `keys()`, `length()`, `lookup()`, `set_intersection()`, `to_number()` ([#455](https://github.com/avenga/couper/pull/455))

* **Changed**
* Automatically add the `private` directive to the response `Cache-Control` HTTP header field value for all resources protected by [JWT](./docs/REFERENCE.md#jwt-block) ([#418](https://github.com/avenga/couper/pull/418))
Expand Down
7 changes: 7 additions & 0 deletions docs/REFERENCE.md
Original file line number Diff line number Diff line change
Expand Up @@ -712,18 +712,25 @@ To access the HTTP status code of the `default` response use `backend_responses.
| :----------------------------- | :-------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------- | :--------------------------------------------------- |
| `base64_decode` | string | Decodes Base64 data, as specified in RFC 4648. | `encoded` (string) | `base64_decode("Zm9v")` |
| `base64_encode` | string | Encodes Base64 data, as specified in RFC 4648. | `decoded` (string) | `base64_encode("foo")` |
| `contains` | bool | Determines whether a given list contains a given single value as one of its elements. | `list` (tuple or list), `value` (various) | `contains([1,2,3], 2)` |
| `default` | string | Returns the first of the given arguments that is not null or an empty string. If no argument matches, the last argument is returned. | `arg...` (various) | `default(request.cookies.foo, "bar")` |
| `join` | string | Concatenates together the string elements of one or more lists with a given separator. | `sep` (string), `lists...` (tuples or lists) | `join("-", [0,1,2,3])` |
| `json_decode` | various | Parses the given JSON string and, if it is valid, returns the value it represents. | `encoded` (string) | `json_decode("{\"foo\": 1}")` |
| `json_encode` | string | Returns a JSON serialization of the given value. | `val` (various) | `json_encode(request.context.myJWT)` |
| `jwt_sign` | string | jwt_sign creates and signs a JSON Web Token (JWT) from information from a referenced [JWT Signing Profile Block](#jwt-signing-profile-block) (or [JWT Block](#jwt-block) with `signing_ttl`) and additional claims provided as a function parameter. | `label` (string), `claims` (object) | `jwt_sign("myJWT")` |
| `keys` | list | Takes a map and returns a sorted list of the map keys. | `inputMap` (object or map) | `keys(request.headers)` |
| `length` | integer | Returns the number of elements in the given collection. | `collection` (tuple, list or map; **no object**) | `length([0,1,2,3])` |
| `lookup` | various | Performs a dynamic lookup into a map. The default (third argument) is returned if the key (second argument) is not found in the inputMap (first argument). | `inputMap` (object or map), `key` (string), `default` (various) | `lookup({a = 1}, "b", "def")` |
| `merge` | object or tuple | Deep-merges two or more of either objects or tuples. `null` arguments are ignored. A `null` attribute value in an object removes the previous attribute value. An attribute value with a different type than the current value is set as the new value. `merge()` with no parameters returns `null`. | `arg...` (object or tuple) | `merge(request.headers, { x-additional = "myval" })` |
| `oauth2_authorization_url` | string | Creates an OAuth2 authorization URL from a referenced [OAuth2 AC Block](#oauth2-ac-block-beta) or [OIDC Block](#oidc-block). | `label` (string) | `oauth2_authorization_url("myOAuth2")` |
| `oauth2_verifier` | string | Creates a cryptographically random key as specified in RFC 7636, applicable for all verifier methods; e.g. to be set as a cookie and read into `verifier_value`. Multiple calls of this function in the same client request context return the same value. | | `oauth2_verifier()` |
| `relative_url` | string | Returns a relative URL by retaining `path`, `query` and `fragment` components. The input URL `s` must begin with `/<path>`, `//<authority>`, `http://` or `https://`, otherwise an error is thrown. | s (string) | `relative_url("https://httpbin.org/anything?query#fragment") // returns "/anything?query#fragment"` |
| `saml_sso_url` | string | Creates a SAML SingleSignOn URL (including the `SAMLRequest` parameter) from a referenced [SAML Block](#saml-block). | `label` (string) | `saml_sso_url("mySAML")` |
| `set_intersection` | list or tuple | Returns a new set containing the elements that exist in all of the given sets. | `sets...` (tuple or list) | `set_intersection(["A", "B", "C"], ["B", D"])` |
| `split` | tuple | Divides a given string by a given separator, returning a list of strings containing the characters between the separator sequences. | `sep` (string), `str` (string) | `split(" ", "foo bar qux")` |
| `substr` | string | Extracts a sequence of characters from another string and creates a new string. The "`offset`" index may be negative, in which case it is relative to the end of the given string. The "`length`" may be `-1`, in which case the remainder of the string after the given offset will be returned. | `str` (string), `offset` (integer), `length` (integer) | `substr("abcdef", 3, -1)` |
| `to_lower` | string | Converts a given string to lowercase. | `s` (string) | `to_lower(request.cookies.name)` |
| `to_number` | number | Converts its argument to a number value. Only numbers, `null`, and strings containing decimal representations of numbers can be converted to number. All other values will produce an error. | `num` (string or number) | `to_number("1,23")`, `to_number(env.PI)` |
| `to_upper` | string | Converts a given string to uppercase. | `s` (string) | `to_upper("CamelCase")` |
| `unixtime` | integer | Retrieves the current UNIX timestamp in seconds. | | `unixtime()` |
| `url_encode` | string | URL-encodes a given string according to RFC 3986. | `s` (string) | `url_encode("abc%&,123")` |
Expand Down
35 changes: 21 additions & 14 deletions eval/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -555,20 +555,27 @@ func newCtyCouperVariablesMap() cty.Value {
// Functions
func newFunctionsMap() map[string]function.Function {
return map[string]function.Function{
"base64_decode": lib.Base64DecodeFunc,
"base64_encode": lib.Base64EncodeFunc,
"coalesce": lib.DefaultFunc,
"default": lib.DefaultFunc,
"json_decode": stdlib.JSONDecodeFunc,
"json_encode": stdlib.JSONEncodeFunc,
"merge": lib.MergeFunc,
"relative_url": lib.RelativeUrlFunc,
"split": stdlib.SplitFunc,
"substr": stdlib.SubstrFunc,
"to_lower": stdlib.LowerFunc,
"to_upper": stdlib.UpperFunc,
"unixtime": lib.UnixtimeFunc,
"url_encode": lib.UrlEncodeFunc,
"base64_decode": lib.Base64DecodeFunc,
"base64_encode": lib.Base64EncodeFunc,
"coalesce": lib.DefaultFunc,
"contains": stdlib.ContainsFunc,
"default": lib.DefaultFunc,
"join": stdlib.JoinFunc,
"json_decode": stdlib.JSONDecodeFunc,
"json_encode": stdlib.JSONEncodeFunc,
"keys": stdlib.KeysFunc,
"length": stdlib.LengthFunc,
"lookup": stdlib.LookupFunc,
"merge": lib.MergeFunc,
"relative_url": lib.RelativeUrlFunc,
"set_intersection": stdlib.SetIntersectionFunc,
"split": stdlib.SplitFunc,
"substr": stdlib.SubstrFunc,
"to_lower": stdlib.LowerFunc,
"to_number": stdlib.MakeToFunc(cty.Number),
"to_upper": stdlib.UpperFunc,
"unixtime": lib.UnixtimeFunc,
"url_encode": lib.UrlEncodeFunc,
}
}

Expand Down
Loading

0 comments on commit 45ee7e8

Please sign in to comment.