diff --git a/impl/core/src/main/java/io/serverlessworkflow/impl/WorkflowUtils.java b/impl/core/src/main/java/io/serverlessworkflow/impl/WorkflowUtils.java index c250f7ee..bedae900 100644 --- a/impl/core/src/main/java/io/serverlessworkflow/impl/WorkflowUtils.java +++ b/impl/core/src/main/java/io/serverlessworkflow/impl/WorkflowUtils.java @@ -223,11 +223,10 @@ public static final String checkSecret( } public static URI concatURI(URI base, String pathToAppend) { - if (!isValid(pathToAppend)) { - return base; - } + return !isValid(pathToAppend) ? base : concatURI(base, URI.create(pathToAppend)); + } - final URI child = URI.create(pathToAppend); + public static URI concatURI(URI base, URI child) { if (child.isAbsolute()) { return child; } @@ -242,21 +241,21 @@ public static URI concatURI(URI base, String pathToAppend) { String relPath = child.getPath(); if (relPath == null) { relPath = ""; + } else { + while (relPath.startsWith("/")) { + relPath = relPath.substring(1); + } } - while (relPath.startsWith("/")) { - relPath = relPath.substring(1); - } - - String finalPath = basePath + relPath; - - String query = child.getQuery(); - String fragment = child.getFragment(); - try { - return new URI(base.getScheme(), base.getAuthority(), finalPath, query, fragment); + return new URI( + base.getScheme(), + base.getAuthority(), + basePath + relPath, + child.getQuery(), + child.getFragment()); } catch (URISyntaxException e) { throw new IllegalArgumentException( - "Failed to build combined URI from base=" + base + " and path=" + pathToAppend, e); + "Failed to build combined URI from base=" + base + " and child=" + child, e); } } diff --git a/impl/http/src/main/java/io/serverlessworkflow/impl/executors/http/HttpExecutor.java b/impl/http/src/main/java/io/serverlessworkflow/impl/executors/http/HttpExecutor.java index 41eb0264..1ec92c4d 100644 --- a/impl/http/src/main/java/io/serverlessworkflow/impl/executors/http/HttpExecutor.java +++ b/impl/http/src/main/java/io/serverlessworkflow/impl/executors/http/HttpExecutor.java @@ -257,7 +257,6 @@ private static WorkflowValueResolver getTargetSupplier( return (w, t, n) -> HttpClientResolver.client(w, t) .target( - WorkflowUtils.concatURI( - uriSupplier.apply(w, t, n), pathSupplier.apply(w, t, n).toString())); + WorkflowUtils.concatURI(uriSupplier.apply(w, t, n), pathSupplier.apply(w, t, n))); } } diff --git a/impl/openapi/src/main/java/io/serverlessworkflow/impl/executors/openapi/OpenAPIExecutor.java b/impl/openapi/src/main/java/io/serverlessworkflow/impl/executors/openapi/OpenAPIExecutor.java index 86e7f89b..7b2a7d11 100644 --- a/impl/openapi/src/main/java/io/serverlessworkflow/impl/executors/openapi/OpenAPIExecutor.java +++ b/impl/openapi/src/main/java/io/serverlessworkflow/impl/executors/openapi/OpenAPIExecutor.java @@ -32,8 +32,10 @@ import io.swagger.v3.oas.models.parameters.Parameter; import java.util.Collection; import java.util.HashMap; +import java.util.HashSet; import java.util.Iterator; import java.util.Map; +import java.util.Set; import java.util.concurrent.CompletableFuture; public class OpenAPIExecutor implements CallableTask { @@ -105,24 +107,31 @@ private void fillHttpBuilder(WorkflowApplication application, OperationDefinitio Map headersMap = new HashMap<>(); Map queryMap = new HashMap<>(); Map pathParameters = new HashMap<>(); + Set missingParams = new HashSet<>(); Map bodyParameters = new HashMap<>(parameters); for (Parameter parameter : operation.getParameters()) { switch (parameter.getIn()) { case "header": - param(parameter.getName(), bodyParameters, headersMap); + param(parameter, bodyParameters, headersMap, missingParams); break; case "path": - param(parameter.getName(), bodyParameters, pathParameters); + param(parameter, bodyParameters, pathParameters, missingParams); break; case "query": - param(parameter.getName(), bodyParameters, queryMap); + param(parameter, bodyParameters, queryMap, missingParams); break; } } - validateRequiredParameters(operation, headersMap, queryMap, pathParameters); - + if (!missingParams.isEmpty()) { + throw new IllegalArgumentException( + "Missing required OpenAPI parameters for operation '" + + (operation.getOperation().getOperationId() != null + ? operation.getOperation().getOperationId() + : "" + "': ") + + missingParams); + } builder .withMethod(operation.getMethod()) .withPath(new OperationPathResolver(operation.getPath(), application, pathParameters)) @@ -131,71 +140,22 @@ private void fillHttpBuilder(WorkflowApplication application, OperationDefinitio .withHeaders(headersMap); } - private void param(String name, Map origMap, Map collectorMap) { - Object value = origMap.remove(name); - if (value != null) { - collectorMap.put(name, value); - } - } - - private void validateRequiredParameters( - OperationDefinition operation, - Map headersMap, - Map queryMap, - Map pathParameters) { - - StringBuilder missing = new StringBuilder(); - - for (Parameter parameter : operation.getParameters()) { - if (!Boolean.TRUE.equals(parameter.getRequired())) { - continue; - } - - String in = parameter.getIn(); - String name = parameter.getName(); - - Map targetMap = - switch (in) { - case "header" -> headersMap; - case "path" -> pathParameters; - case "query" -> queryMap; - default -> null; - }; - - if (targetMap == null) { - // We don't currently handle other "in" locations here (e.g., cookie). - // Treat as "not validated" instead of failing. - continue; - } - - boolean present = targetMap.containsKey(name); - - if (!present) { - // Try to satisfy the requirement using the OpenAPI default, if any - Schema schema = parameter.getSchema(); - Object defaultValue = schema != null ? schema.getDefault() : null; - - if (defaultValue != null) { - targetMap.put(name, defaultValue); - present = true; - } + private void param( + Parameter parameter, + Map origMap, + Map collectorMap, + Set missingParams) { + String name = parameter.getName(); + if (origMap.containsKey(name)) { + collectorMap.put(parameter.getName(), origMap.remove(name)); + } else if (parameter.getRequired()) { + Schema schema = parameter.getSchema(); + Object defaultValue = schema != null ? schema.getDefault() : null; + if (defaultValue != null) { + collectorMap.put(name, defaultValue); + } else { + missingParams.add(name); } - - if (!present) { - if (!missing.isEmpty()) { - missing.append(", "); - } - missing.append(in).append(" parameter '").append(name).append("'"); - } - } - - if (!missing.isEmpty()) { - String operationId = - operation.getOperation().getOperationId() != null - ? operation.getOperation().getOperationId() - : ""; - throw new IllegalArgumentException( - "Missing required OpenAPI parameters for operation '" + operationId + "': " + missing); } } }