Merge pull request #569 from ghillert/INT-2680
* INT-2680: INT-2680 - Duplicate Content-Type header For reference please see: https://jira.springsource.org/browse/INT-2680
This commit is contained in:
12
build.gradle
12
build.gradle
@@ -47,7 +47,9 @@ subprojects { subproject ->
|
||||
mockitoVersion = '1.9.0'
|
||||
|
||||
// When changing Spring Versions - don't forget to update bundlor ranges
|
||||
springVersion = project.hasProperty('springVersion') ? getProperty('springVersion') : '3.1.2.RELEASE'
|
||||
springVersionDefault = '3.1.2.RELEASE'
|
||||
springVersion = project.hasProperty('springVersion') ? getProperty('springVersion') : springVersionDefault
|
||||
|
||||
springAmqpVersion = '1.1.1.RELEASE'
|
||||
springDataMongoVersion = '1.1.0.M1'
|
||||
springDataRedisVersion = '1.0.1.RELEASE'
|
||||
@@ -356,7 +358,13 @@ project('spring-integration-http') {
|
||||
dependencies {
|
||||
compile project(":spring-integration-core")
|
||||
compile "org.springframework:spring-webmvc:$springVersion"
|
||||
compile("javax.servlet:javax.servlet-api:3.0.1", provided)
|
||||
|
||||
if (springVersionDefault.equalsIgnoreCase(springVersion)) {
|
||||
compile("javax.servlet:javax.servlet-api:3.0.1", provided)
|
||||
} else {
|
||||
compile("javax.servlet:servlet-api:2.5", provided)
|
||||
}
|
||||
|
||||
compile("commons-httpclient:commons-httpclient:3.1") { dep ->
|
||||
optional dep
|
||||
exclude group: 'junit', module: 'junit'
|
||||
|
||||
@@ -27,6 +27,7 @@ import org.springframework.context.MessageSource;
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.expression.common.LiteralExpression;
|
||||
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||
import org.springframework.http.server.ServletServerHttpResponse;
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
@@ -140,7 +141,9 @@ public class HttpRequestHandlingController extends HttpRequestHandlingEndpointSu
|
||||
try {
|
||||
Message<?> replyMessage = super.doHandleRequest(servletRequest, servletResponse);
|
||||
if (replyMessage != null) {
|
||||
Object reply = setupResponseAndConvertReply(servletResponse, replyMessage);
|
||||
ServletServerHttpResponse response = new ServletServerHttpResponse(servletResponse);
|
||||
Object reply = setupResponseAndConvertReply(response, replyMessage);
|
||||
response.close();
|
||||
modelAndView.addObject(this.replyKey, reply);
|
||||
}
|
||||
if (this.viewExpression != null) {
|
||||
|
||||
@@ -432,25 +432,38 @@ public abstract class HttpRequestHandlingEndpointSupport extends MessagingGatewa
|
||||
|
||||
/**
|
||||
* Converts the reply message to the appropriate HTTP reply object and
|
||||
* sets up the servlet response.
|
||||
* @param servletResponse The servlet response.
|
||||
* sets up the {@link ServletServerHttpResponse}.
|
||||
*
|
||||
* @param response The ServletServerHttpResponse.
|
||||
* @param replyMessage The reply message.
|
||||
* @return The message payload (if {@link #extractReplyPayload}) otherwise the
|
||||
* message.
|
||||
*/
|
||||
protected final Object setupResponseAndConvertReply(HttpServletResponse servletResponse, Message<?> replyMessage) {
|
||||
ServletServerHttpResponse response = new ServletServerHttpResponse(servletResponse);
|
||||
protected final Object setupResponseAndConvertReply(ServletServerHttpResponse response, Message<?> replyMessage) {
|
||||
|
||||
this.headerMapper.fromHeaders(replyMessage.getHeaders(), response.getHeaders());
|
||||
HttpStatus httpStatus = this.resolveHttpStatusFromHeaders(((Message<?>) replyMessage).getHeaders());
|
||||
if (httpStatus != null) {
|
||||
response.setStatusCode(httpStatus);
|
||||
}
|
||||
response.close();
|
||||
|
||||
Object reply = replyMessage;
|
||||
if (this.extractReplyPayload) {
|
||||
reply = replyMessage.getPayload();
|
||||
}
|
||||
return reply;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated As of release 2.2, please use {@link #setupResponseAndConvertReply(ServletServerHttpResponse, Message)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
protected final Object setupResponseAndConvertReply(HttpServletResponse servletResponse, Message<?> replyMessage) {
|
||||
ServletServerHttpResponse response = new ServletServerHttpResponse(servletResponse);
|
||||
Object reply = setupResponseAndConvertReply(response, replyMessage);
|
||||
response.close();
|
||||
return reply;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -93,18 +93,21 @@ public class HttpRequestHandlingMessagingGateway extends HttpRequestHandlingEndp
|
||||
throws ServletException, IOException {
|
||||
Object responseContent = null;
|
||||
Message<?> responseMessage;
|
||||
|
||||
final ServletServerHttpRequest request = new ServletServerHttpRequest(servletRequest);
|
||||
final ServletServerHttpResponse response = new ServletServerHttpResponse(servletResponse);
|
||||
|
||||
try {
|
||||
responseMessage = super.doHandleRequest(servletRequest, servletResponse);
|
||||
if (responseMessage != null) {
|
||||
responseContent = setupResponseAndConvertReply(servletResponse, responseMessage);
|
||||
responseContent = setupResponseAndConvertReply(response, responseMessage);
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
responseContent = handleExceptionInternal(e);
|
||||
}
|
||||
if (responseContent != null) {
|
||||
ServletServerHttpRequest request = new ServletServerHttpRequest(servletRequest);
|
||||
ServletServerHttpResponse response = new ServletServerHttpResponse(servletResponse);
|
||||
|
||||
if (responseContent instanceof HttpStatus) {
|
||||
response.setStatusCode((HttpStatus) responseContent);
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import static org.junit.Assert.assertNotNull;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
@@ -30,6 +31,7 @@ import org.springframework.http.HttpInputMessage;
|
||||
import org.springframework.http.HttpOutputMessage;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.converter.AbstractHttpMessageConverter;
|
||||
import org.springframework.http.converter.ByteArrayHttpMessageConverter;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
import org.springframework.http.converter.HttpMessageNotReadableException;
|
||||
import org.springframework.http.converter.HttpMessageNotWritableException;
|
||||
@@ -37,6 +39,7 @@ import org.springframework.integration.Message;
|
||||
import org.springframework.integration.channel.DirectChannel;
|
||||
import org.springframework.integration.channel.QueueChannel;
|
||||
import org.springframework.integration.handler.AbstractReplyProducingMessageHandler;
|
||||
import org.springframework.integration.support.MessageBuilder;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
@@ -218,6 +221,68 @@ public class HttpRequestHandlingMessagingGatewayTests {
|
||||
assertEquals(84, result.age);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void INT2680DuplicateContentTypeHeader() throws Exception {
|
||||
|
||||
final DirectChannel requestChannel = new DirectChannel();
|
||||
requestChannel.subscribe(new AbstractReplyProducingMessageHandler() {
|
||||
@Override
|
||||
protected Object handleRequestMessage(Message<?> requestMessage) {
|
||||
return MessageBuilder.withPayload("Cartman".getBytes())
|
||||
.setHeader("Content-type", "text/plain")
|
||||
.build();
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
final List<MediaType> supportedMediaTypes = new ArrayList<MediaType>();
|
||||
supportedMediaTypes.add(MediaType.TEXT_HTML);
|
||||
|
||||
final ByteArrayHttpMessageConverter messageConverter = new ByteArrayHttpMessageConverter();
|
||||
messageConverter.setSupportedMediaTypes(supportedMediaTypes);
|
||||
|
||||
final List<HttpMessageConverter<?>> messageConverters = new ArrayList<HttpMessageConverter<?>>();
|
||||
messageConverters.add(messageConverter);
|
||||
|
||||
final HttpRequestHandlingMessagingGateway gateway = new HttpRequestHandlingMessagingGateway(true);
|
||||
gateway.setMessageConverters(messageConverters);
|
||||
gateway.setRequestChannel(requestChannel);
|
||||
|
||||
final MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setMethod("GET");
|
||||
request.addHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
|
||||
|
||||
final ContentTypeCheckingMockHttpServletResponse response = new ContentTypeCheckingMockHttpServletResponse();
|
||||
gateway.handleRequest(request, response);
|
||||
|
||||
assertEquals("Cartman", response.getContentAsString());
|
||||
|
||||
/* Before fixing INT2680, 2 content type headers were being written. */
|
||||
final List<String> contentTypes = response.getContentTypeList();
|
||||
|
||||
assertEquals("Exptecting only 1 content type being set.", Integer.valueOf(1), Integer.valueOf(contentTypes.size()));
|
||||
assertEquals("text/plain", contentTypes.get(0));
|
||||
}
|
||||
|
||||
private class ContentTypeCheckingMockHttpServletResponse extends MockHttpServletResponse {
|
||||
|
||||
private List<String> contentTypeList = new ArrayList<String>();
|
||||
|
||||
@Override
|
||||
public void addHeader(String name, String value) {
|
||||
|
||||
if ("Content-Type".equalsIgnoreCase(name)) {
|
||||
this.contentTypeList.add(value);
|
||||
}
|
||||
|
||||
super.addHeader(name, value);
|
||||
}
|
||||
|
||||
public List<String> getContentTypeList() {
|
||||
return contentTypeList;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class TestHttpMessageConverter extends AbstractHttpMessageConverter<Exception> {
|
||||
|
||||
|
||||
Reference in New Issue
Block a user