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 a97c88dccbd CAMEL-22136: camel-rest - Allow to use variables in {xxx}
placeholder syntax for the producer
a97c88dccbd is described below
commit a97c88dccbd53cb9d9e4b88eabff04b568a2b5ce
Author: Claus Ibsen <[email protected]>
AuthorDate: Wed Jun 4 12:33:42 2025 +0200
CAMEL-22136: camel-rest - Allow to use variables in {xxx} placeholder
syntax for the producer
---
.../rest/producer/HttpRestProducerGetTest.java | 8 ++-
.../camel-rest/src/main/docs/rest-component.adoc | 9 +++-
.../apache/camel/component/rest/RestProducer.java | 57 ++++++++++++----------
3 files changed, 46 insertions(+), 28 deletions(-)
diff --git
a/components/camel-jetty/src/test/java/org/apache/camel/component/jetty/rest/producer/HttpRestProducerGetTest.java
b/components/camel-jetty/src/test/java/org/apache/camel/component/jetty/rest/producer/HttpRestProducerGetTest.java
index 3802aecf98b..210b2bce2da 100644
---
a/components/camel-jetty/src/test/java/org/apache/camel/component/jetty/rest/producer/HttpRestProducerGetTest.java
+++
b/components/camel-jetty/src/test/java/org/apache/camel/component/jetty/rest/producer/HttpRestProducerGetTest.java
@@ -27,11 +27,17 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
public class HttpRestProducerGetTest extends BaseJettyTest {
@Test
- public void testHttpProducerGet() {
+ public void testHttpProducerGetWithHeader() {
String out = fluentTemplate.withHeader("id",
"123").to("direct:start").request(String.class);
assertEquals("123;Donald Duck", out);
}
+ @Test
+ public void testHttpProducerGetWithVariable() {
+ String out = fluentTemplate.withVariable("id",
"456").to("direct:start").request(String.class);
+ assertEquals("456;Donald Duck", out);
+ }
+
@Override
protected RouteBuilder createRouteBuilder() {
return new RouteBuilder() {
diff --git a/components/camel-rest/src/main/docs/rest-component.adoc
b/components/camel-rest/src/main/docs/rest-component.adoc
index 29be9d030a4..053860fe189 100644
--- a/components/camel-rest/src/main/docs/rest-component.adoc
+++ b/components/camel-rest/src/main/docs/rest-component.adoc
@@ -119,7 +119,7 @@ from("direct:start")
.to("rest:get:hello/{me}");
----
-And then the dynamic value `\{me}` is mapped to a Camel message with the same
name.
+And then the dynamic value `\{me}` is mapped to a header or variable with the
same name.
So to call this REST service, you can send an empty message body and a header
as shown:
[source,java]
@@ -127,6 +127,13 @@ So to call this REST service, you can send an empty
message body and a header as
template.sendBodyAndHeader("direct:start", null, "me", "Donald Duck");
----
+Instead of a header you can also use exchange variable such as:
+
+[source,java]
+----
+String response = template.withVariable("me", "Donald
Duck").to("direct:start").request(String.class);
+----
+
The Rest producer needs to know the hostname and port of the REST service,
which you can configure
using the host option as shown:
diff --git
a/components/camel-rest/src/main/java/org/apache/camel/component/rest/RestProducer.java
b/components/camel-rest/src/main/java/org/apache/camel/component/rest/RestProducer.java
index fbd78cdfb93..c588433ca5f 100644
---
a/components/camel-rest/src/main/java/org/apache/camel/component/rest/RestProducer.java
+++
b/components/camel-rest/src/main/java/org/apache/camel/component/rest/RestProducer.java
@@ -16,9 +16,9 @@
*/
package org.apache.camel.component.rest;
-import java.io.UnsupportedEncodingException;
import java.net.URISyntaxException;
import java.net.URLDecoder;
+import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Locale;
@@ -30,7 +30,6 @@ import org.apache.camel.AsyncProcessor;
import org.apache.camel.CamelContext;
import org.apache.camel.Endpoint;
import org.apache.camel.Exchange;
-import org.apache.camel.Message;
import org.apache.camel.Producer;
import org.apache.camel.spi.DataFormat;
import org.apache.camel.spi.PropertyConfigurer;
@@ -146,7 +145,6 @@ public class RestProducer extends DefaultAsyncProducer {
String resolvedUriTemplate
= getEndpoint().getUriTemplate() != null ?
getEndpoint().getUriTemplate() : getEndpoint().getPath();
- Message inMessage = exchange.getIn();
if (prepareUriTemplate) {
if (resolvedUriTemplate.contains("{")) {
// resolve template and replace {key} with the values form the
exchange
@@ -154,7 +152,7 @@ public class RestProducer extends DefaultAsyncProducer {
String[] arr = resolvedUriTemplate.split("\\/");
StringJoiner uriTemplateBuilder = new StringJoiner("/");
for (String a : arr) {
- String resolvedUriParam = resolveHeaderPlaceholders(a,
inMessage);
+ String resolvedUriParam = resolvePlaceholders(a, exchange);
// Backward compatibility: if one of the path params is
fully resolved,
// then it is assumed that whole uri is resolved.
@@ -172,11 +170,11 @@ public class RestProducer extends DefaultAsyncProducer {
}
// resolve uri parameters
- String query =
createQueryParameters(getEndpoint().getQueryParameters(), inMessage);
+ String query =
createQueryParameters(getEndpoint().getQueryParameters(), exchange);
if (query != null) {
// the query parameters for the rest call to be used
- inMessage.setHeader(RestConstants.REST_HTTP_QUERY, query);
+ exchange.getMessage().setHeader(RestConstants.REST_HTTP_QUERY,
query);
}
if (hasPath) {
@@ -193,14 +191,14 @@ public class RestProducer extends DefaultAsyncProducer {
overrideUri += "/" + resolvedUriTemplate;
}
// the http uri for the rest call to be used
- inMessage.setHeader(RestConstants.REST_HTTP_URI, overrideUri);
+ exchange.getMessage().setHeader(RestConstants.REST_HTTP_URI,
overrideUri);
// when chaining RestConsumer with RestProducer, the
// HTTP_PATH header will be present, we remove it here
// as the REST_HTTP_URI contains the full URI for the
// request and every other HTTP producer will concatenate
// REST_HTTP_URI with HTTP_PATH resulting in incorrect URIs
- inMessage.removeHeader(Exchange.HTTP_PATH);
+ exchange.getMessage().removeHeader(Exchange.HTTP_PATH);
}
// method
@@ -208,28 +206,28 @@ public class RestProducer extends DefaultAsyncProducer {
if (method != null) {
// the method should be in upper case
String upper = method.toUpperCase(Locale.US);
- inMessage.setHeader(RestConstants.HTTP_METHOD, upper);
+ exchange.getMessage().setHeader(RestConstants.HTTP_METHOD, upper);
}
final String produces = getEndpoint().getProduces();
- if (isEmpty(inMessage.getHeader(RestConstants.CONTENT_TYPE)) &&
isNotEmpty(produces)) {
- inMessage.setHeader(RestConstants.CONTENT_TYPE, produces);
+ if
(isEmpty(exchange.getMessage().getHeader(RestConstants.CONTENT_TYPE)) &&
isNotEmpty(produces)) {
+ exchange.getMessage().setHeader(RestConstants.CONTENT_TYPE,
produces);
}
final String consumes = getEndpoint().getConsumes();
- if (isEmpty(inMessage.getHeader(RestConstants.ACCEPT)) &&
isNotEmpty(consumes)) {
- inMessage.setHeader(RestConstants.ACCEPT, consumes);
+ if (isEmpty(exchange.getMessage().getHeader(RestConstants.ACCEPT)) &&
isNotEmpty(consumes)) {
+ exchange.getMessage().setHeader(RestConstants.ACCEPT, consumes);
}
}
/**
- * Replaces placeholders "{}" with message header values.
+ * Replaces placeholders "{}" with message header or exchange variable
values.
*
- * @param str string with placeholders
- * @param msg message with headers
- * @return filled string
+ * @param str string with placeholders
+ * @param exchange the exchange
+ * @return filled string
*/
- private String resolveHeaderPlaceholders(String str, Message msg) {
+ private String resolvePlaceholders(String str, Exchange exchange) {
int startIndex = -1;
String res = str;
while ((startIndex = res.indexOf('{', startIndex + 1)) >= 0) {
@@ -238,12 +236,15 @@ public class RestProducer extends DefaultAsyncProducer {
continue;
}
String key = res.substring(startIndex + 1, endIndex);
- String headerValue = msg.getHeader(key, String.class);
- if (headerValue != null) {
- res = res.substring(0, startIndex) + headerValue +
res.substring(endIndex + 1);
+ // try header first and then fallback to variable
+ String value = exchange.getMessage().getHeader(key, String.class);
+ if (value == null) {
+ value = exchange.getVariable(key, String.class);
+ }
+ if (value != null) {
+ res = res.substring(0, startIndex) + value +
res.substring(endIndex + 1);
}
}
-
return res;
}
@@ -399,8 +400,8 @@ public class RestProducer extends DefaultAsyncProducer {
|| key.startsWith("xml.out.");
}
- static String createQueryParameters(String query, Message inMessage)
- throws URISyntaxException, UnsupportedEncodingException {
+ static String createQueryParameters(String query, Exchange exchange)
+ throws URISyntaxException {
if (query != null) {
final Map<String, Object> givenParams =
URISupport.parseQuery(query);
final Map<String, Object> params = new
LinkedHashMap<>(givenParams.size());
@@ -409,7 +410,7 @@ public class RestProducer extends DefaultAsyncProducer {
if (v != null) {
String a = v.toString();
// decode the key as { may be decoded to %NN
- a = URLDecoder.decode(a, "UTF-8");
+ a = URLDecoder.decode(a, StandardCharsets.UTF_8);
if (a.startsWith("{") && a.endsWith("}")) {
String key = a.substring(1, a.length() - 1);
boolean optional = false;
@@ -417,7 +418,11 @@ public class RestProducer extends DefaultAsyncProducer {
key = key.substring(0, key.length() - 1);
optional = true;
}
- Object value = inMessage.getHeader(key);
+ // try header first and fallback to variable
+ Object value = exchange.getMessage().getHeader(key);
+ if (value == null) {
+ value = exchange.getVariable(key);
+ }
if (value != null) {
params.put(entry.getKey(), value);
} else if (!optional) {