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

commit 6831f37c94e4906873a4836e8c1c2e34383951be
Author: Claus Ibsen <claus.ib...@gmail.com>
AuthorDate: Fri Dec 10 07:59:11 2021 +0100

    CAMEL-17295: rest-dsl - Fix parse uri template for query parameters.
---
 .../servlet/rest/RestServletQueryParamTest.java    |  20 ++-
 ...Test.java => RestServletQueryParamUriTest.java} |  28 ++--
 .../apache/camel/model/rest/RestDefinition.java    | 145 +++++++++++++--------
 3 files changed, 123 insertions(+), 70 deletions(-)

diff --git 
a/components/camel-servlet/src/test/java/org/apache/camel/component/servlet/rest/RestServletQueryParamTest.java
 
b/components/camel-servlet/src/test/java/org/apache/camel/component/servlet/rest/RestServletQueryParamTest.java
index 68f7d29..4b49f8d 100644
--- 
a/components/camel-servlet/src/test/java/org/apache/camel/component/servlet/rest/RestServletQueryParamTest.java
+++ 
b/components/camel-servlet/src/test/java/org/apache/camel/component/servlet/rest/RestServletQueryParamTest.java
@@ -31,7 +31,7 @@ public class RestServletQueryParamTest extends 
ServletCamelRouterTestSupport {
     private ServletRestHttpBinding restHttpBinding = new 
ServletRestHttpBinding();
 
     @Test
-    public void testServletProducerGet() throws Exception {
+    public void testQueryTrue() throws Exception {
         WebRequest req = new GetMethodWebRequest(contextUrl + 
"/services/users/");
         req.setParameter("auth", "secret");
         WebResponse response = query(req, false);
@@ -41,25 +41,35 @@ public class RestServletQueryParamTest extends 
ServletCamelRouterTestSupport {
         assertEquals("secret;Donald Duck", response.getText());
     }
 
+    @Test
+    public void testQueryFalse() throws Exception {
+        WebRequest req = new GetMethodWebRequest(contextUrl + 
"/services/users/");
+        WebResponse response = query(req, false);
+
+        assertEquals(400, response.getResponseCode());
+    }
+
     @Override
     protected RouteBuilder createRouteBuilder() throws Exception {
         return new RouteBuilder() {
             @Override
             public void configure() throws Exception {
                 // configure to use servlet on localhost
-                
restConfiguration().component("servlet").host("localhost").endpointProperty("httpBinding",
 "#myBinding");
+                
restConfiguration().component("servlet").host("localhost").endpointProperty("httpBinding",
 "#myBinding")
+                        .clientRequestValidation(true);
 
                 // use the rest DSL to define the rest services
                 rest()
-                    .get("/users/?auth={myToken}")
+                    .get("/users/")
                         .param()
                             .name("auth")
                             .type(RestParamType.query)
+                            .required(true)
                         .endParam()
                     .route().to("mock:input").process(exchange -> {
                         String auth = exchange.getIn().getHeader("auth", 
String.class);
-                        exchange.getMessage().setBody(auth + ";Donald Duck");
-                    });
+                            exchange.getMessage().setBody(auth + ";Donald 
Duck");
+                        });
             }
         };
     }
diff --git 
a/components/camel-servlet/src/test/java/org/apache/camel/component/servlet/rest/RestServletQueryParamTest.java
 
b/components/camel-servlet/src/test/java/org/apache/camel/component/servlet/rest/RestServletQueryParamUriTest.java
similarity index 73%
copy from 
components/camel-servlet/src/test/java/org/apache/camel/component/servlet/rest/RestServletQueryParamTest.java
copy to 
components/camel-servlet/src/test/java/org/apache/camel/component/servlet/rest/RestServletQueryParamUriTest.java
index 68f7d29..4ed1b34 100644
--- 
a/components/camel-servlet/src/test/java/org/apache/camel/component/servlet/rest/RestServletQueryParamTest.java
+++ 
b/components/camel-servlet/src/test/java/org/apache/camel/component/servlet/rest/RestServletQueryParamUriTest.java
@@ -20,18 +20,17 @@ import org.apache.camel.BindToRegistry;
 import org.apache.camel.builder.RouteBuilder;
 import org.apache.camel.component.servlet.ServletCamelRouterTestSupport;
 import org.apache.camel.component.servlet.ServletRestHttpBinding;
-import org.apache.camel.model.rest.RestParamType;
 import org.junit.jupiter.api.Test;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
 
-public class RestServletQueryParamTest extends ServletCamelRouterTestSupport {
+public class RestServletQueryParamUriTest extends 
ServletCamelRouterTestSupport {
 
     @BindToRegistry("myBinding")
     private ServletRestHttpBinding restHttpBinding = new 
ServletRestHttpBinding();
 
     @Test
-    public void testServletProducerGet() throws Exception {
+    public void testQueryTrue() throws Exception {
         WebRequest req = new GetMethodWebRequest(contextUrl + 
"/services/users/");
         req.setParameter("auth", "secret");
         WebResponse response = query(req, false);
@@ -41,25 +40,32 @@ public class RestServletQueryParamTest extends 
ServletCamelRouterTestSupport {
         assertEquals("secret;Donald Duck", response.getText());
     }
 
+    @Test
+    public void testQueryFalse() throws Exception {
+        WebRequest req = new GetMethodWebRequest(contextUrl + 
"/services/users/");
+        WebResponse response = query(req, false);
+
+        // we do not know if the query was required, so we cannot validate this
+        assertEquals(200, response.getResponseCode());
+        assertEquals("null;Donald Duck", response.getText());
+    }
+
     @Override
     protected RouteBuilder createRouteBuilder() throws Exception {
         return new RouteBuilder() {
             @Override
             public void configure() throws Exception {
                 // configure to use servlet on localhost
-                
restConfiguration().component("servlet").host("localhost").endpointProperty("httpBinding",
 "#myBinding");
+                
restConfiguration().component("servlet").host("localhost").endpointProperty("httpBinding",
 "#myBinding")
+                        .clientRequestValidation(true);
 
                 // use the rest DSL to define the rest services
                 rest()
-                    .get("/users/?auth={myToken}")
-                        .param()
-                            .name("auth")
-                            .type(RestParamType.query)
-                        .endParam()
+                    .get("/users/?auth={myAuth}")
                     .route().to("mock:input").process(exchange -> {
                         String auth = exchange.getIn().getHeader("auth", 
String.class);
-                        exchange.getMessage().setBody(auth + ";Donald Duck");
-                    });
+                            exchange.getMessage().setBody(auth + ";Donald 
Duck");
+                        });
             }
         };
     }
diff --git 
a/core/camel-core-model/src/main/java/org/apache/camel/model/rest/RestDefinition.java
 
b/core/camel-core-model/src/main/java/org/apache/camel/model/rest/RestDefinition.java
index e56a633..df627cd 100644
--- 
a/core/camel-core-model/src/main/java/org/apache/camel/model/rest/RestDefinition.java
+++ 
b/core/camel-core-model/src/main/java/org/apache/camel/model/rest/RestDefinition.java
@@ -16,7 +16,6 @@
  */
 package org.apache.camel.model.rest;
 
-import java.net.URISyntaxException;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -792,13 +791,11 @@ public class RestDefinition extends 
OptionalIdentifiedDefinition<RestDefinition>
         }
 
         if (!options.isEmpty()) {
-            String query;
             try {
-                query = URISupport.createQueryString(options);
-            } catch (URISyntaxException e) {
+                from = URISupport.appendParametersToURI(from, options);
+            } catch (Exception e) {
                 throw RuntimeCamelException.wrapRuntimeCamelException(e);
             }
-            from = from + "?" + query;
         }
 
         // we use the same uri as the producer (so we have a little route for
@@ -885,9 +882,6 @@ public class RestDefinition extends 
OptionalIdentifiedDefinition<RestDefinition>
 
             route.setRestBindingDefinition(binding);
 
-            // create the from endpoint uri which is using the rest component
-            String from = buildFromUri(verb);
-
             // append options
             Map<String, Object> options = new HashMap<>();
             // verb takes precedence over configuration on rest
@@ -934,16 +928,6 @@ public class RestDefinition extends 
OptionalIdentifiedDefinition<RestDefinition>
                 options.put("description", description);
             }
 
-            if (!options.isEmpty()) {
-                String query;
-                try {
-                    query = URISupport.createQueryString(options);
-                } catch (URISyntaxException e) {
-                    throw RuntimeCamelException.wrapRuntimeCamelException(e);
-                }
-                from = from + "?" + query;
-            }
-
             String path = getPath();
             String s1 = FileUtil.stripTrailingSeparator(path);
             String s2 = FileUtil.stripLeadingSeparator(verb.getUri());
@@ -957,42 +941,17 @@ public class RestDefinition extends 
OptionalIdentifiedDefinition<RestDefinition>
             }
 
             // each {} is a parameter (url templating)
-            if (allPath != null) {
-                String[] arr = allPath.split("\\/");
-                for (String a : arr) {
-                    // need to resolve property placeholders first
-                    try {
-                        a = camelContext.resolvePropertyPlaceholders(a);
-                    } catch (Exception e) {
-                        throw 
RuntimeCamelException.wrapRuntimeCamelException(e);
-                    }
-
-                    Matcher m = Pattern.compile("\\{(.*?)\\}").matcher(a);
-                    while (m.find()) {
-                        String key = m.group(1);
-                        //  merge if exists
-                        boolean found = false;
-                        for (RestOperationParamDefinition param : 
verb.getParams()) {
-                            // name is mandatory
-                            String name = param.getName();
-                            StringHelper.notEmpty(name, "parameter name");
-                            // need to resolve property placeholders first
-                            try {
-                                name = 
camelContext.resolvePropertyPlaceholders(name);
-                            } catch (Exception e) {
-                                throw 
RuntimeCamelException.wrapRuntimeCamelException(e);
-                            }
-                            if (name.equalsIgnoreCase(key)) {
-                                param.type(RestParamType.path);
-                                found = true;
-                                break;
-                            }
-                        }
-                        if (!found) {
-                            
param(verb).name(key).type(RestParamType.path).endParam();
-                        }
-                    }
-                }
+            Set<String> toRemove = null;
+            if (allPath != null && allPath.contains("?")) {
+                // special when having query parameters
+                String path1 = StringHelper.before(allPath, "?");
+                uriTemplating(camelContext, verb, path1, false);
+                String path2 = StringHelper.after(allPath, "?");
+                // there may be some query parameters that are templates which 
we then must remove
+                toRemove = uriTemplating(camelContext, verb, path2, true);
+            } else {
+                // no query parameters
+                uriTemplating(camelContext, verb, allPath, false);
             }
 
             if (verb.getType() != null) {
@@ -1010,6 +969,36 @@ public class RestDefinition extends 
OptionalIdentifiedDefinition<RestDefinition>
                 }
             }
 
+            // create the from endpoint uri which is using the rest component
+            String from = buildFromUri(verb);
+
+            // rebuild uri without these query parameters
+            if (toRemove != null && !toRemove.isEmpty()) {
+                try {
+                    Map<String, Object> query = 
URISupport.parseQuery(URISupport.extractQuery(from));
+                    // remove if the value matches, eg: auth={myAuth}
+                    toRemove.forEach(v -> {
+                        query.values().removeIf(qv -> qv.toString().equals(v));
+                    });
+                    from = URISupport.stripQuery(from);
+                    if (!query.isEmpty()) {
+                        String q = URISupport.createQueryString(query);
+                        from = URISupport.stripQuery(from) + "?" + q;
+                    }
+                } catch (Exception e) {
+                    throw RuntimeCamelException.wrapRuntimeCamelException(e);
+                }
+            }
+
+            // append additional options
+            if (!options.isEmpty()) {
+                try {
+                    from = URISupport.appendParametersToURI(from, options);
+                } catch (Exception e) {
+                    throw RuntimeCamelException.wrapRuntimeCamelException(e);
+                }
+            }
+
             // the route should be from this rest endpoint
             route.fromRest(from);
             route.setRestDefinition(this);
@@ -1017,6 +1006,54 @@ public class RestDefinition extends 
OptionalIdentifiedDefinition<RestDefinition>
         }
     }
 
+    private Set<String> uriTemplating(
+            CamelContext camelContext, VerbDefinition verb,
+            String path, boolean query) {
+
+        if (path == null) {
+            return null;
+        }
+
+        Set<String> params = new HashSet<>();
+        String[] arr = path.split("\\/");
+        for (String a : arr) {
+            // need to resolve property placeholders first
+            try {
+                a = camelContext.resolvePropertyPlaceholders(a);
+            } catch (Exception e) {
+                throw RuntimeCamelException.wrapRuntimeCamelException(e);
+            }
+
+            Matcher m = Pattern.compile("\\{(.*?)\\}").matcher(a);
+            while (m.find()) {
+                String key = m.group(1);
+                params.add("{" + key + "}");
+                //  merge if exists
+                boolean found = false;
+                for (RestOperationParamDefinition param : verb.getParams()) {
+                    // name is mandatory
+                    String name = param.getName();
+                    StringHelper.notEmpty(name, "parameter name");
+                    // need to resolve property placeholders first
+                    try {
+                        name = camelContext.resolvePropertyPlaceholders(name);
+                    } catch (Exception e) {
+                        throw 
RuntimeCamelException.wrapRuntimeCamelException(e);
+                    }
+                    if (name.equalsIgnoreCase(key)) {
+                        param.type(query ? RestParamType.query : 
RestParamType.path);
+                        found = true;
+                        break;
+                    }
+                }
+                if (!found) {
+                    param(verb).name(key).type(query ? RestParamType.query : 
RestParamType.path).endParam();
+                }
+            }
+        }
+        return params;
+    }
+
     private String buildUri(VerbDefinition verb) {
         if (path != null && verb.getUri() != null) {
             return path + ":" + verb.getUri();

Reply via email to