You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2020/08/25 08:03:14 UTC

[camel] 01/02: CAMEL-15455: EndpointDSL with toD should not encoding endpoint parameters as they should be parsable with simple language, which needs to resolve first, before uri is encoded by ToD.

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

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

commit 598c109c5ea4b3bd959ea7de20468e6d4753d0a7
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Mon Aug 24 18:48:25 2020 +0200

    CAMEL-15455: EndpointDSL with toD should not encoding endpoint parameters as they should be parsable with simple language, which needs to resolve first, before uri is encoded by ToD.
---
 .../builder/endpoint/AbstractEndpointBuilder.java  | 13 ++++--
 .../builder/endpoint/SedaSimpleExpressionTest.java | 54 ++++++++++++++++++++++
 .../java/org/apache/camel/util/URISupport.java     | 42 +++++++++++++----
 3 files changed, 95 insertions(+), 14 deletions(-)

diff --git a/core/camel-endpointdsl/src/main/java/org/apache/camel/builder/endpoint/AbstractEndpointBuilder.java b/core/camel-endpointdsl/src/main/java/org/apache/camel/builder/endpoint/AbstractEndpointBuilder.java
index 90ffc0f..a23ade9 100644
--- a/core/camel-endpointdsl/src/main/java/org/apache/camel/builder/endpoint/AbstractEndpointBuilder.java
+++ b/core/camel-endpointdsl/src/main/java/org/apache/camel/builder/endpoint/AbstractEndpointBuilder.java
@@ -53,7 +53,7 @@ public class AbstractEndpointBuilder {
 
         Map<String, Object> remaining = new LinkedHashMap<>();
         // we should not bind complex objects to registry as we create the endpoint via the properties as-is
-        NormalizedEndpointUri uri = computeUri(remaining, context, false);
+        NormalizedEndpointUri uri = computeUri(remaining, context, false, true);
         ExtendedCamelContext ecc = (ExtendedCamelContext) context;
         Endpoint endpoint = ecc.getEndpoint(uri, properties);
         if (endpoint == null) {
@@ -70,10 +70,10 @@ public class AbstractEndpointBuilder {
     }
 
     public String getUri() {
-        return computeUri(new LinkedHashMap<>(), null, false).getUri();
+        return computeUri(new LinkedHashMap<>(), null, false, true).getUri();
     }
 
-    protected NormalizedUri computeUri(Map<String, Object> remaining, CamelContext camelContext, boolean bindToRegistry) {
+    protected NormalizedUri computeUri(Map<String, Object> remaining, CamelContext camelContext, boolean bindToRegistry, boolean encode) {
         NormalizedUri answer;
 
         // sort parameters so it can be regarded as normalized
@@ -99,7 +99,8 @@ public class AbstractEndpointBuilder {
             answer = new NormalizedUri(targetScheme + "://" + targetPath);
         } else {
             try {
-                String query = URISupport.createQueryString(params);
+                // build query string from parameters
+                String query = URISupport.createQueryString(params, encode);
                 answer = new NormalizedUri(targetScheme + "://" + targetPath + "?" + query);
             } catch (URISyntaxException e) {
                 throw RuntimeCamelException.wrapRuntimeCamelException(e);
@@ -158,7 +159,9 @@ public class AbstractEndpointBuilder {
 
     public Expression expr(CamelContext camelContext) {
         // need to bind complex properties so we can return an uri that includes these parameters too
-        NormalizedEndpointUri uri = computeUri(new LinkedHashMap<>(), camelContext, true);
+        // do not encode computed uri as we want to preserve simple expressions, as this is used
+        // by ToDynamic which builds the uri string un-encoded for simple language parser to be able to parse
+        NormalizedEndpointUri uri = computeUri(new LinkedHashMap<>(), camelContext, true, false);
         return SimpleBuilder.simple(uri.getUri());
     }
 
diff --git a/core/camel-endpointdsl/src/test/java/org/apache/camel/builder/endpoint/SedaSimpleExpressionTest.java b/core/camel-endpointdsl/src/test/java/org/apache/camel/builder/endpoint/SedaSimpleExpressionTest.java
new file mode 100644
index 0000000..08fedb6
--- /dev/null
+++ b/core/camel-endpointdsl/src/test/java/org/apache/camel/builder/endpoint/SedaSimpleExpressionTest.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.builder.endpoint;
+
+import org.apache.camel.EndpointInject;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.test.junit5.CamelTestSupport;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertSame;
+
+public class SedaSimpleExpressionTest extends CamelTestSupport {
+
+    @EndpointInject(value = "mock:result")
+    private MockEndpoint result;
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new EndpointRouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                from(direct("start")).toD(seda("foo").size("${header.mySize}"));
+
+                from(seda("foo").size(5)).to(mock("result"));
+            }
+        };
+    }
+
+    @Test
+    public void test() throws Exception {
+        MockEndpoint resultEndpoint = getMockEndpoint("mock:result");
+        resultEndpoint.expectedMessageCount(1);
+
+        template.sendBodyAndHeader("direct:start", "Hello World", "mySize", 5);
+
+        assertMockEndpointsSatisfied();
+        assertSame(result, resultEndpoint);
+    }
+}
diff --git a/core/camel-util/src/main/java/org/apache/camel/util/URISupport.java b/core/camel-util/src/main/java/org/apache/camel/util/URISupport.java
index e2a9ca0..55e2f7e 100644
--- a/core/camel-util/src/main/java/org/apache/camel/util/URISupport.java
+++ b/core/camel-util/src/main/java/org/apache/camel/util/URISupport.java
@@ -404,10 +404,25 @@ public final class URISupport {
      */
     @SuppressWarnings("unchecked")
     public static String createQueryString(Map<String, Object> options) throws URISyntaxException {
-        return createQueryString(options.keySet(), options);
+        return createQueryString(options.keySet(), options, true);
     }
 
-    public static String createQueryString(Collection<String> sortedKeys, Map<String, Object> options) throws URISyntaxException {
+    /**
+     * Assembles a query from the given map.
+     *
+     * @param  options            the map with the options (eg key/value pairs)
+     * @param  encode             whether to URL encode the query string
+     * @return                    a query string with <tt>key1=value&key2=value2&...</tt>, or an empty string if there
+     *                            is no options.
+     * @throws URISyntaxException is thrown if uri has invalid syntax.
+     */
+    @SuppressWarnings("unchecked")
+    public static String createQueryString(Map<String, Object> options, boolean encode) throws URISyntaxException {
+        return createQueryString(options.keySet(), options, encode);
+    }
+
+    public static String createQueryString(Collection<String> sortedKeys, Map<String, Object> options, boolean encode)
+            throws URISyntaxException {
         try {
             if (options.size() > 0) {
                 StringBuilder rc = new StringBuilder();
@@ -428,7 +443,7 @@ public final class URISupport {
                         List<String> list = (List<String>)value;
                         for (Iterator<String> it = list.iterator(); it.hasNext();) {
                             String s = it.next();
-                            appendQueryStringParameter(key, s, rc);
+                            appendQueryStringParameter(key, s, rc, encode);
                             // append & separator if there is more in the list
                             // to append
                             if (it.hasNext()) {
@@ -438,7 +453,7 @@ public final class URISupport {
                     } else {
                         // use the value as a String
                         String s = value != null ? value.toString() : null;
-                        appendQueryStringParameter(key, s, rc);
+                        appendQueryStringParameter(key, s, rc, encode);
                     }
                 }
                 return rc.toString();
@@ -452,8 +467,13 @@ public final class URISupport {
         }
     }
 
-    private static void appendQueryStringParameter(String key, String value, StringBuilder rc) throws UnsupportedEncodingException {
-        rc.append(URLEncoder.encode(key, CHARSET));
+    private static void appendQueryStringParameter(String key, String value, StringBuilder rc, boolean encode)
+            throws UnsupportedEncodingException {
+        if (encode) {
+            rc.append(URLEncoder.encode(key, CHARSET));
+        } else {
+            rc.append(key);
+        }
         if (value == null) {
             return;
         }
@@ -466,7 +486,11 @@ public final class URISupport {
             String s = StringHelper.replaceAll(value, "%", "%25");
             rc.append(s);
         } else {
-            rc.append(URLEncoder.encode(value, CHARSET));
+            if (encode) {
+                rc.append(URLEncoder.encode(value, CHARSET));
+            } else {
+                rc.append(value);
+            }
         }
     }
 
@@ -600,7 +624,7 @@ public final class URISupport {
                 keys.sort(null);
 
                 // build uri object with sorted parameters
-                query = URISupport.createQueryString(keys, parameters);
+                query = URISupport.createQueryString(keys, parameters, true);
                 return buildUri(scheme, path, query);
             }
         }
@@ -647,7 +671,7 @@ public final class URISupport {
                     List<String> keys = new ArrayList<>(parameters.keySet());
                     keys.sort(null);
                     // rebuild query with sorted parameters
-                    query = URISupport.createQueryString(keys, parameters);
+                    query = URISupport.createQueryString(keys, parameters, true);
                 }
 
                 return buildUri(scheme, path, query);