diff --git a/spring-integration-http/src/main/java/org/springframework/integration/http/config/HttpOutboundChannelAdapterParser.java b/spring-integration-http/src/main/java/org/springframework/integration/http/config/HttpOutboundChannelAdapterParser.java
index df81521391..d1a6c0ee44 100644
--- a/spring-integration-http/src/main/java/org/springframework/integration/http/config/HttpOutboundChannelAdapterParser.java
+++ b/spring-integration-http/src/main/java/org/springframework/integration/http/config/HttpOutboundChannelAdapterParser.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2012 the original author or authors.
+ * Copyright 2002-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -32,6 +32,7 @@ import org.springframework.util.StringUtils;
* @author Mark Fisher
* @author Oleg Zhurakousky
* @author Gary Russell
+ * @author Artem Bilan
* @since 2.0
*/
public class HttpOutboundChannelAdapterParser extends AbstractOutboundChannelAdapterParser {
@@ -42,6 +43,8 @@ public class HttpOutboundChannelAdapterParser extends AbstractOutboundChannelAda
builder.addPropertyValue("expectReply", false);
HttpAdapterParsingUtils.configureUrlConstructorArg(element, parserContext, builder);
+ IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "encode-uri");
+
HttpAdapterParsingUtils.setHttpMethodOrExpression(element, parserContext, builder);
String restTemplate = element.getAttribute("rest-template");
diff --git a/spring-integration-http/src/main/java/org/springframework/integration/http/config/HttpOutboundGatewayParser.java b/spring-integration-http/src/main/java/org/springframework/integration/http/config/HttpOutboundGatewayParser.java
index 0d13e685ec..df2ed76567 100644
--- a/spring-integration-http/src/main/java/org/springframework/integration/http/config/HttpOutboundGatewayParser.java
+++ b/spring-integration-http/src/main/java/org/springframework/integration/http/config/HttpOutboundGatewayParser.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2012 the original author or authors.
+ * Copyright 2002-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -31,6 +31,7 @@ import org.springframework.util.StringUtils;
* @author Mark Fisher
* @author Oleg Zhurakousky
* @author Gary Russell
+ * @author Artem Bilan
*/
public class HttpOutboundGatewayParser extends AbstractConsumerEndpointParser {
@@ -45,6 +46,8 @@ public class HttpOutboundGatewayParser extends AbstractConsumerEndpointParser {
HttpAdapterParsingUtils.configureUrlConstructorArg(element, parserContext, builder);
+ IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "encode-uri");
+
HttpAdapterParsingUtils.setHttpMethodOrExpression(element, parserContext, builder);
String restTemplate = element.getAttribute("rest-template");
diff --git a/spring-integration-http/src/main/java/org/springframework/integration/http/outbound/HttpRequestExecutingMessageHandler.java b/spring-integration-http/src/main/java/org/springframework/integration/http/outbound/HttpRequestExecutingMessageHandler.java
index d76929d3e6..db2f808ac1 100755
--- a/spring-integration-http/src/main/java/org/springframework/integration/http/outbound/HttpRequestExecutingMessageHandler.java
+++ b/spring-integration-http/src/main/java/org/springframework/integration/http/outbound/HttpRequestExecutingMessageHandler.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2012 the original author or authors.
+ * Copyright 2002-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -62,6 +62,8 @@ import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;
import org.springframework.web.client.ResponseErrorHandler;
import org.springframework.web.client.RestTemplate;
+import org.springframework.web.util.UriComponents;
+import org.springframework.web.util.UriComponentsBuilder;
/**
* A {@link MessageHandler} implementation that executes HTTP requests by delegating
@@ -90,6 +92,8 @@ public class HttpRequestExecutingMessageHandler extends AbstractReplyProducingMe
private final Expression uriExpression;
+ private volatile boolean encodeUri = true;
+
private volatile Expression httpMethodExpression = new LiteralExpression(HttpMethod.POST.name());
private volatile boolean expectReply = true;
@@ -157,6 +161,16 @@ public class HttpRequestExecutingMessageHandler extends AbstractReplyProducingMe
this.evaluationContext = sec;
}
+ /**
+ * Specify whether the real URI should be encoded after uriVariables
+ * expanding and before send request via {@link RestTemplate}. The default value is true.
+ *
+ * @see UriComponentsBuilder
+ */
+ public void setEncodeUri(boolean encodeUri) {
+ this.encodeUri = encodeUri;
+ }
+
/**
* Specify the SpEL {@link Expression} to determine {@link HttpMethod} dynamically
*
@@ -348,7 +362,9 @@ public class HttpRequestExecutingMessageHandler extends AbstractReplyProducingMe
Class> expectedResponseType = this.determineExpectedResponseType(requestMessage);
HttpEntity> httpRequest = this.generateHttpRequest(requestMessage, httpMethod);
- ResponseEntity> httpResponse = this.restTemplate.exchange(uri, httpMethod, httpRequest, expectedResponseType, uriVariables);
+ UriComponents uriComponents = UriComponentsBuilder.fromUriString(uri).buildAndExpand(uriVariables);
+ URI realUri = this.encodeUri ? uriComponents.toUri() : new URI(uriComponents.toUriString());
+ ResponseEntity> httpResponse = this.restTemplate.exchange(realUri, httpMethod, httpRequest, expectedResponseType);
if (this.expectReply) {
HttpHeaders httpHeaders = httpResponse.getHeaders();
Map headers = this.headerMapper.toHeaders(httpHeaders);
diff --git a/spring-integration-http/src/main/resources/org/springframework/integration/http/config/spring-integration-http-3.0.xsd b/spring-integration-http/src/main/resources/org/springframework/integration/http/config/spring-integration-http-3.0.xsd
index b6bddc7ff9..6f2203a573 100644
--- a/spring-integration-http/src/main/resources/org/springframework/integration/http/config/spring-integration-http-3.0.xsd
+++ b/spring-integration-http/src/main/resources/org/springframework/integration/http/config/spring-integration-http-3.0.xsd
@@ -390,6 +390,15 @@ The String "HTTP_REQUEST_HEADERS" will match against any of the standard HTTP Re
]]>
+
+
+
+ When set to "false", the real URI won't be encoded before the request is sent. This may be useful
+ in some scenarios as it allows user control over the encoding, if needed,
+ for example by using the "url-expression". Default is "true".
+
+
+
@@ -560,6 +569,15 @@ The String "HTTP_REQUEST_HEADERS" will match against any of the standard HTTP Re
]]>
+
+
+
+ When set to "false", the real URI won't be encoded before the request is sent. This may be useful
+ in some scenarios as it allows user control over the encoding, if needed,
+ for example by using the "url-expression". Default is "true".
+
+
+
diff --git a/spring-integration-http/src/test/java/org/springframework/integration/http/outbound/HttpOutboundWithinChainTests-context.xml b/spring-integration-http/src/test/java/org/springframework/integration/http/outbound/HttpOutboundWithinChainTests-context.xml
index d77d40fdc2..a4ca379b94 100644
--- a/spring-integration-http/src/test/java/org/springframework/integration/http/outbound/HttpOutboundWithinChainTests-context.xml
+++ b/spring-integration-http/src/test/java/org/springframework/integration/http/outbound/HttpOutboundWithinChainTests-context.xml
@@ -9,15 +9,22 @@
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
-
+
-
+
+
+
+
+
-
+ encode-uri="false"
+ expected-response-type="java.lang.String">
+
+
diff --git a/spring-integration-http/src/test/java/org/springframework/integration/http/outbound/HttpRequestExecutingMessageHandlerTests.java b/spring-integration-http/src/test/java/org/springframework/integration/http/outbound/HttpRequestExecutingMessageHandlerTests.java
index c30a6bc0b5..145978948e 100644
--- a/spring-integration-http/src/test/java/org/springframework/integration/http/outbound/HttpRequestExecutingMessageHandlerTests.java
+++ b/spring-integration-http/src/test/java/org/springframework/integration/http/outbound/HttpRequestExecutingMessageHandlerTests.java
@@ -29,6 +29,7 @@ import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.Serializable;
import java.net.URI;
+import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap;
@@ -42,6 +43,7 @@ import javax.xml.transform.Source;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.junit.Test;
+import org.mockito.Mockito;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.beans.DirectFieldAccessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
@@ -673,23 +675,28 @@ public class HttpRequestExecutingMessageHandlerTests {
}
@Test //INT-2275
- public void testOutboundChannelAdapterWithinChain() {
+ public void testOutboundChannelAdapterWithinChain() throws URISyntaxException {
ApplicationContext ctx = new ClassPathXmlApplicationContext("HttpOutboundWithinChainTests-context.xml", this.getClass());
MessageChannel channel = ctx.getBean("httpOutboundChannelAdapterWithinChain", MessageChannel.class);
+ RestTemplate restTemplate = ctx.getBean("restTemplate", RestTemplate.class);
channel.send(MessageBuilder.withPayload("test").build());
-// It's just enough if it was sent successfully from chain without any failures
+ Mockito.verify(restTemplate).exchange(Mockito.eq(new URI("http://localhost/test1/%2f")), Mockito.eq(HttpMethod.POST),
+ Mockito.any(HttpEntity.class), Mockito.eq((Class>) null));
}
@Test //INT-1029
- public void testHttpOutboundGatewayWithinChain() throws IOException {
+ public void testHttpOutboundGatewayWithinChain() throws IOException, URISyntaxException {
ApplicationContext ctx = new ClassPathXmlApplicationContext("HttpOutboundWithinChainTests-context.xml", this.getClass());
MessageChannel channel = ctx.getBean("httpOutboundGatewayWithinChain", MessageChannel.class);
+ RestTemplate restTemplate = ctx.getBean("restTemplate", RestTemplate.class);
channel.send(MessageBuilder.withPayload("test").build());
PollableChannel output = ctx.getBean("replyChannel", PollableChannel.class);
Message> receive = output.receive();
assertEquals(HttpStatus.OK, ((ResponseEntity>)receive.getPayload()).getStatusCode());
-
+ Mockito.verify(restTemplate)
+ .exchange(Mockito.eq(new URI("http://localhost:51235/%2f/testApps?param=http%20Outbound%20Gateway%20Within%20Chain")),
+ Mockito.eq(HttpMethod.POST), Mockito.any(HttpEntity.class), Mockito.eq(String.class));
}
@Test
@@ -698,7 +705,7 @@ public class HttpRequestExecutingMessageHandlerTests {
HttpRequestExecutingMessageHandler handler = new HttpRequestExecutingMessageHandler(
new SpelExpressionParser().parseExpression("headers['foo']"),
restTemplate);
- String theURL = "http://bar/baz";
+ String theURL = "http://bar/baz?foo#bar";
Message> message = MessageBuilder.withPayload("").setHeader("foo", theURL).build();
try {
handler.handleRequestMessage(message);
@@ -707,6 +714,21 @@ public class HttpRequestExecutingMessageHandlerTests {
assertEquals(theURL, restTemplate.actualUrl.get());
}
+ @Test
+ public void testInt2455UriNotEncoded() {
+ MockRestTemplate restTemplate = new MockRestTemplate();
+ HttpRequestExecutingMessageHandler handler = new HttpRequestExecutingMessageHandler(
+ new SpelExpressionParser().parseExpression("'http://my.RabbitMQ.com/api/' + payload"),
+ restTemplate);
+ handler.setEncodeUri(false);
+ Message> message = MessageBuilder.withPayload("queues/%2f/si.test.queue?foo#bar").build();
+ try {
+ handler.handleRequestMessage(message);
+ }
+ catch (Exception e) {}
+ assertEquals("http://my.RabbitMQ.com/api/queues/%2f/si.test.queue?foo#bar", restTemplate.actualUrl.get());
+ }
+
@Test
public void nonCompatibleConversionService() throws Exception {
HttpRequestExecutingMessageHandler handler =
@@ -857,9 +879,9 @@ public class HttpRequestExecutingMessageHandlerTests {
private final AtomicReference actualUrl = new AtomicReference();
@Override
- public ResponseEntity exchange(String url, HttpMethod method, HttpEntity> requestEntity,
- Class responseType, Map uriVariables) throws RestClientException {
- this.actualUrl.set(url);
+ public ResponseEntity exchange(URI uri, HttpMethod method, HttpEntity> requestEntity,
+ Class responseType) throws RestClientException {
+ this.actualUrl.set(uri.toString());
this.lastRequestEntity.set(requestEntity);
throw new RuntimeException("intentional");
}
@@ -869,8 +891,8 @@ public class HttpRequestExecutingMessageHandlerTests {
private static class MockRestTemplate2 extends RestTemplate {
@Override
- public ResponseEntity exchange(String url, HttpMethod method, HttpEntity> requestEntity,
- Class responseType, Map uriVariables) throws RestClientException {
+ public ResponseEntity exchange(URI uri, HttpMethod method, HttpEntity> requestEntity,
+ Class responseType) throws RestClientException {
return new ResponseEntity(HttpStatus.OK);
}
}
diff --git a/src/reference/docbook/http.xml b/src/reference/docbook/http.xml
index 76ac32de22..e1ebde4e95 100644
--- a/src/reference/docbook/http.xml
+++ b/src/reference/docbook/http.xml
@@ -376,7 +376,7 @@ In the case of the Outbound Gateway, the reply message produced by the gateway w
- Mapping URI variables
+ Mapping URI Variables
If your URL contains URI variables, you can map them using the
@@ -402,6 +402,24 @@ In the case of the Outbound Gateway, the reply message produced by the gateway w
method will be invoked on the payload object of the Message and the result
of that method will be used as the value for the URI variable named 'zipCode'.
+
+ Controlling URI Encoding
+
+
+ By default, the URL string is encoded (see
+ UriComponentsBuilder)
+ to the URI object before sending the request. In some scenarios with a non-standard URI (e.g. the RabbitMQ Rest API) it is
+ undesirable to perform the encoding. The <http:outbound-gateway/>
+ and <http:outbound-channel-adapter/> provide an encode-uri attribute.
+ To disable encoding the URL, this attribute should be set to false (by default it is true).
+ If you wish to partially encode some of the URL, this can be achieved using an expression within a
+ <uri-variable/>:
+
+
+
+]]>
diff --git a/src/reference/docbook/whats-new.xml b/src/reference/docbook/whats-new.xml
index cbef2d2e10..f1e9672cbe 100644
--- a/src/reference/docbook/whats-new.xml
+++ b/src/reference/docbook/whats-new.xml
@@ -136,5 +136,14 @@
see 'JSON Transformers' in .
+
+ HTTP Outbound Endpoint 'encode-uri' property
+
+ <http:outbound-gateway/> and <http:outbound-channel-adapter/> now
+ provide an encode-uri attribute to allow disabling the encoding of the URI object
+ before sending the request. For more information see .
+
+
+