diff --git a/Dockerfile b/Dockerfile index e1f49fe..d7a8414 100644 --- a/Dockerfile +++ b/Dockerfile @@ -98,7 +98,7 @@ RUN pip install -r /tmp/requirements.txt # Install Node.js and set up symlinks RUN set -eux; \ - NODE_VERSION="v22.10.0" \ + NODE_VERSION="v22.19.0" \ ARCH= && dpkgArch="$(dpkg --print-architecture)"; \ case "${dpkgArch##*-}" in \ amd64) ARCH='x64';; \ diff --git a/python-sync-actions/src/component.py b/python-sync-actions/src/component.py index 0e57206..e1b92c3 100644 --- a/python-sync-actions/src/component.py +++ b/python-sync-actions/src/component.py @@ -217,6 +217,12 @@ def _build_url(self, base_url: str, endpoints: list[dict], selected_job: str) -> endpoint = ep.get("endpoint", "").lstrip("/") placeholders = ep.get("placeholders", {}) params = ep.get("params", {}) + user_params = self._configuration.user_parameters if self._configuration else {} + params = self._conf_helpers.fill_in_user_parameters( + params, + user_params, + evaluate_conf_objects_functions=True + ) try: formatted_path = endpoint.format(**placeholders) @@ -238,7 +244,7 @@ def _get_values_to_hide(self) -> list[str]: Get values to hide Args: """ - user_params = self._configuration.user_parameters + user_params = self._configuration.user_parameters if self._configuration else {} secrets = [value for key, value in user_params.items() if key.startswith("#") or key.startswith("__")] # get secrets from the auth method diff --git a/python-sync-actions/src/configuration.py b/python-sync-actions/src/configuration.py index b366a8a..1a63685 100644 --- a/python-sync-actions/src/configuration.py +++ b/python-sync-actions/src/configuration.py @@ -336,7 +336,12 @@ def build_api_request(configuration: dict) -> List[Tuple[ApiRequest, RequestCont method = endpoint_config.get("method", "GET") - request_content = build_request_content(method, endpoint_config.get("params", {})) + # evaluate functions inside the params + user_parameters = configuration.get("parameters", {}).get("config", {}) + params = endpoint_config.get("params", {}) + params = ConfigHelpers().fill_in_user_parameters(params, user_parameters, evaluate_conf_objects_functions=True) + request_content = build_request_content(method, params) + # use real method if method.upper() == "FORM": method = "POST" diff --git a/python-sync-actions/tests/calls/010-default-header/config.json b/python-sync-actions/tests/calls/010-default-header/config.json index 9b5af2e..b0354b1 100644 --- a/python-sync-actions/tests/calls/010-default-header/config.json +++ b/python-sync-actions/tests/calls/010-default-header/config.json @@ -31,7 +31,13 @@ "http": { "headers": { "Authorization": { - "attr": "#BEARER_TOKEN" + "function": "concat", + "args": [ + "Bearer ", + { + "attr": "#BEARER_TOKEN" + } + ] } } } diff --git a/python-sync-actions/tests/calls/011-params-func-eval/config.json b/python-sync-actions/tests/calls/011-params-func-eval/config.json new file mode 100644 index 0000000..abe17f3 --- /dev/null +++ b/python-sync-actions/tests/calls/011-params-func-eval/config.json @@ -0,0 +1,61 @@ +{ + "storage": {}, + "parameters": { + "__SELECTED_JOB": "0", + "config": { + "jobs": [ + { + "endpoint": "011-params-func-eval/orders", + "dataType": "orders", + "method": "POST", + "params": { + "greeting": { + "value": + { + "hi": { + "function": "concat", + "args": [ + "hello", + "-world" + ] + } + } + + } + } + } + ], + "debug": false, + "outputBucket": "in.c-", + "incrementalOutput": false, + "#BEARER_TOKEN": "token" + }, + "api": { + "baseUrl": "http://mock-server:80/", + "http": { + "headers": { + "Authorization": { + "attr": "#BEARER_TOKEN" + } + } + } + }, + "http": { + "maxRetries": 10, + "codes": [ + 500, + 502, + 503, + 504, + 408, + 420, + 429 + ] + } + }, + "action": "test_request", + "image_parameters": { + }, + "authorization": { + } +} diff --git a/python-sync-actions/tests/calls/011-params-func-eval/orders.request b/python-sync-actions/tests/calls/011-params-func-eval/orders.request new file mode 100644 index 0000000..e259a10 --- /dev/null +++ b/python-sync-actions/tests/calls/011-params-func-eval/orders.request @@ -0,0 +1,3 @@ +POST /011-params-func-eval/orders + +{"greeting": {"value": {"hi": "hello-world"}}} \ No newline at end of file diff --git a/python-sync-actions/tests/calls/011-params-func-eval/orders.requestHeaders b/python-sync-actions/tests/calls/011-params-func-eval/orders.requestHeaders new file mode 100644 index 0000000..68862da --- /dev/null +++ b/python-sync-actions/tests/calls/011-params-func-eval/orders.requestHeaders @@ -0,0 +1,4 @@ +accept: */* +authorization: token +content-length: 46 +content-type: application/json diff --git a/python-sync-actions/tests/calls/011-params-func-eval/orders.response b/python-sync-actions/tests/calls/011-params-func-eval/orders.response new file mode 100644 index 0000000..71d78ff --- /dev/null +++ b/python-sync-actions/tests/calls/011-params-func-eval/orders.response @@ -0,0 +1,82 @@ +{ + "nested": { + "orders": [ + { + "id": 1, + "customer": "John Doe", + "address": "123 Main St", + "items": [ + { + "id": 1, + "name": "Widget", + "price": 9.99, + "quantity": 2 + }, + { + "id": 2, + "name": "Thing", + "price": 5.99, + "quantity": 5 + } + ] + }, + { + "id": 2, + "customer": "Jan Novak", + "address": "123 Main St", + "items": [ + { + "id": 1, + "name": "Widget", + "price": 9.99, + "quantity": 2 + }, + { + "id": 2, + "name": "Thing", + "price": 5.99, + "quantity": 5 + } + ] + }, + { + "id": 3, + "customer": "Jana Novakova", + "address": "123 Main St", + "items": [ + { + "id": 1, + "name": "Widget", + "price": 9.99, + "quantity": 2 + }, + { + "id": 2, + "name": "Thing", + "price": 5.99, + "quantity": 5 + } + ] + }, + { + "id": 4, + "customer": "Bob Smith", + "address": "123 Main St", + "items": [ + { + "id": 1, + "name": "Widget", + "price": 9.99, + "quantity": 2 + }, + { + "id": 2, + "name": "Thing", + "price": 5.99, + "quantity": 5 + } + ] + } + ] + } +} \ No newline at end of file