This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git


The following commit(s) were added to refs/heads/main by this push:
     new 352344c3b969 CAMEL-24112: camel-rest-openapi - Fix path parameters 
leaking into query string with multi-param operations
352344c3b969 is described below

commit 352344c3b969dd4398dd467b85d0b84964f8a0b7
Author: Claus Ibsen <[email protected]>
AuthorDate: Thu Jul 16 17:09:21 2026 +0200

    CAMEL-24112: camel-rest-openapi - Fix path parameters leaking into query 
string with multi-param operations
    
    Co-Authored-By: Claude Opus 4.6 <[email protected]>
    
    Signed-off-by: Claus Ibsen <[email protected]>
    Co-authored-by: Claude Opus 4.6 <[email protected]>
---
 .../rest/openapi/RestOpenApiEndpoint.java          | 13 ++---
 .../rest/openapi/RestOpenApiEndpointV3Test.java    | 64 ++++++++++++++++++++++
 2 files changed, 70 insertions(+), 7 deletions(-)

diff --git 
a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java
 
b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java
index 761ca925126c..9c856e06b48e 100644
--- 
a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java
+++ 
b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java
@@ -683,13 +683,12 @@ public final class RestOpenApiEndpoint extends 
DefaultEndpoint {
         if (this.parameters != null) {
             if (operation.getParameters() != null) {
                 for (Map.Entry<String, Object> entry : 
this.parameters.entrySet()) {
-                    for (Parameter param : operation.getParameters()) {
-                        // skip parameters that are part of the operation as 
path as otherwise
-                        // it will be duplicated as query parameter as well
-                        boolean clash = "path".equals(param.getIn()) && 
entry.getKey().equals(param.getName());
-                        if (!clash) {
-                            nestedParameters.put(entry.getKey(), 
entry.getValue());
-                        }
+                    // skip parameters that are part of the operation as path 
as otherwise
+                    // it will be duplicated as query parameter as well
+                    boolean clash = operation.getParameters().stream()
+                            .anyMatch(p -> "path".equals(p.getIn()) && 
entry.getKey().equals(p.getName()));
+                    if (!clash) {
+                        nestedParameters.put(entry.getKey(), entry.getValue());
                     }
                 }
             } else {
diff --git 
a/components/camel-rest-openapi/src/test/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpointV3Test.java
 
b/components/camel-rest-openapi/src/test/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpointV3Test.java
index 24ed458fb49f..f77769d89466 100644
--- 
a/components/camel-rest-openapi/src/test/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpointV3Test.java
+++ 
b/components/camel-rest-openapi/src/test/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpointV3Test.java
@@ -287,6 +287,70 @@ public class RestOpenApiEndpointV3Test {
                 entry("queryParameters", "q={q}&o={o?}"));
     }
 
+    @Test
+    public void shouldNotLeakPathParametersAsQueryParameters() {
+        final CamelContext camelContext = mock(CamelContext.class);
+
+        final RestOpenApiComponent component = new RestOpenApiComponent();
+        component.setCamelContext(camelContext);
+
+        // endpoint parameters include two path params and one extra param
+        Map<String, Object> params = new HashMap<>();
+        params.put("userId", "1");
+        params.put("orderId", "2");
+        params.put("format", "json");
+
+        final RestOpenApiEndpoint endpoint = new RestOpenApiEndpoint(
+                "uri", "remaining", component, params);
+        endpoint.setHost("http://petstore.openapi.io";);
+
+        final OpenAPI openapi = new OpenAPI();
+        final Operation operation = new Operation().operationId("getOrder");
+        operation.addParametersItem(new 
Parameter().name("userId").in("path").required(true));
+        operation.addParametersItem(new 
Parameter().name("orderId").in("path").required(true));
+
+        Map<String, Object> result = 
endpoint.determineEndpointParameters(openapi, operation);
+
+        @SuppressWarnings("unchecked")
+        Map<String, Object> nested = (Map<String, Object>) 
result.get("parameters");
+
+        // path params must not leak into nested parameters
+        assertThat(nested).doesNotContainKey("userId");
+        assertThat(nested).doesNotContainKey("orderId");
+        // non-path param must be preserved
+        assertThat(nested).containsEntry("format", "json");
+    }
+
+    @Test
+    public void shouldKeepEndpointParametersWhenNoPathParamClash() {
+        final CamelContext camelContext = mock(CamelContext.class);
+
+        final RestOpenApiComponent component = new RestOpenApiComponent();
+        component.setCamelContext(camelContext);
+
+        Map<String, Object> params = new HashMap<>();
+        params.put("verbose", "true");
+        params.put("timeout", "5000");
+
+        final RestOpenApiEndpoint endpoint = new RestOpenApiEndpoint(
+                "uri", "remaining", component, params);
+        endpoint.setHost("http://petstore.openapi.io";);
+
+        final OpenAPI openapi = new OpenAPI();
+        final Operation operation = new Operation().operationId("listUsers");
+        operation.addParametersItem(new Parameter().name("page").in("query"));
+        operation.addParametersItem(new Parameter().name("limit").in("query"));
+
+        Map<String, Object> result = 
endpoint.determineEndpointParameters(openapi, operation);
+
+        @SuppressWarnings("unchecked")
+        Map<String, Object> nested = (Map<String, Object>) 
result.get("parameters");
+
+        // no path params in the operation, so all endpoint params should be 
preserved
+        assertThat(nested).containsEntry("verbose", "true");
+        assertThat(nested).containsEntry("timeout", "5000");
+    }
+
     @Test
     public void shouldDetermineHostFromRestConfiguration() {
         assertThat(RestOpenApiEndpoint.hostFrom(null)).isNull();

Reply via email to