INT-3934: HTTP Requests Without Content-Type

JIRA: https://jira.spring.io/browse/INT-3934

Coerce a missing Content-Type to `application/octet-stream`.
This commit is contained in:
Gary Russell
2016-01-18 11:23:29 -05:00
parent 22eaa649ca
commit c97afe92fe
4 changed files with 34 additions and 24 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 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.
@@ -603,11 +603,10 @@ public abstract class HttpRequestHandlingEndpointSupport extends MessagingGatewa
}
/**
* Checks if the request has a readable body (not a GET, HEAD, or OPTIONS request) and a Content-Type header.
* Checks if the request has a readable body (not a GET, HEAD, or OPTIONS request).
*/
private boolean isReadable(ServletServerHttpRequest request) {
return !(CollectionUtils.containsInstance(nonReadableBodyHttpMethods, request.getMethod()))
&& request.getHeaders().getContentType() != null;
return !(CollectionUtils.containsInstance(nonReadableBodyHttpMethods, request.getMethod()));
}
/**
@@ -638,6 +637,9 @@ public abstract class HttpRequestHandlingEndpointSupport extends MessagingGatewa
@SuppressWarnings({"unchecked", "rawtypes"})
private Object extractRequestBody(ServletServerHttpRequest request) throws IOException {
MediaType contentType = request.getHeaders().getContentType();
if (contentType == null) {
contentType = MediaType.APPLICATION_OCTET_STREAM;
}
Class<?> expectedType = this.requestPayloadType;
if (expectedType == null) {
expectedType = ("text".equals(contentType.getType())) ? String.class : byte[].class;

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 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.
@@ -99,11 +99,7 @@ public class HttpRequestHandlingMessagingGatewayTests extends AbstractHttpInboun
gateway.afterPropertiesSet();
MockHttpServletRequest request = new MockHttpServletRequest();
request.setMethod("POST");
//request.setContentType("text/plain"); //Works in Spring 3.1.2.RELEASE but NOT in 3.0.7.RELEASE
//Instead do:
request.addHeader("Content-Type", "text/plain");
request.setContentType("text/plain");
request.setContent("hello".getBytes());
MockHttpServletResponse response = new MockHttpServletResponse();
gateway.handleRequest(request, response);
@@ -115,6 +111,15 @@ public class HttpRequestHandlingMessagingGatewayTests extends AbstractHttpInboun
@Test
public void stringExpectedWithReply() throws Exception {
stringExpectedWithReplyGuts(true);
}
@Test
public void stringExpectedWithReplyNoContentType() throws Exception {
stringExpectedWithReplyGuts(false);
}
private void stringExpectedWithReplyGuts(boolean contentType) throws Exception {
DirectChannel requestChannel = new DirectChannel();
requestChannel.subscribe(new AbstractReplyProducingMessageHandler() {
@Override
@@ -131,11 +136,9 @@ public class HttpRequestHandlingMessagingGatewayTests extends AbstractHttpInboun
MockHttpServletRequest request = new MockHttpServletRequest();
request.setMethod("POST");
request.addHeader("Accept", "x-application/octet-stream");
//request.setContentType("text/plain"); //Works in Spring 3.1.2.RELEASE but NOT in 3.0.7.RELEASE
//Instead do:
request.addHeader("Content-Type", "text/plain");
if (contentType) {
request.setContentType("text/plain");
}
request.setContent("hello".getBytes());
MockHttpServletResponse response = new MockHttpServletResponse();
gateway.handleRequest(request, response);
@@ -158,11 +161,7 @@ public class HttpRequestHandlingMessagingGatewayTests extends AbstractHttpInboun
gateway.afterPropertiesSet();
MockHttpServletRequest request = new MockHttpServletRequest();
request.setMethod("POST");
//request.setContentType("text/plain"); //Works in Spring 3.1.2.RELEASE but NOT in 3.0.7.RELEASE
//Instead do:
request.addHeader("Content-Type", "text/plain");
request.setContentType("text/plain");
request.setContent("hello".getBytes());
MockHttpServletResponse response = new MockHttpServletResponse();
gateway.handleRequest(request, response);
@@ -237,10 +236,7 @@ public class HttpRequestHandlingMessagingGatewayTests extends AbstractHttpInboun
MockHttpServletRequest request = new MockHttpServletRequest("POST", "/test");
//request.setContentType("application/x-java-serialized-object"); //Works in Spring 3.1.2.RELEASE but NOT in 3.0.7.RELEASE
//Instead do:
request.addHeader("Content-Type", "application/x-java-serialized-object");
request.setContentType("application/x-java-serialized-object");
TestBean testBean = new TestBean();
testBean.setName("T. Bean");
testBean.setAge(42);

View File

@@ -55,6 +55,11 @@ The default converters encapsulate simple strategies, which for example will cre
An additional flag (`mergeWithDefaultConverters`) can be set along with the list of custom `HttpMessageConverter` to add the default converters after the custom converters.
By default this flag is set to false, meaning that the custom converters replace the default list.
The message conversion process uses the (optional) `requestPayloadType` property and the incoming `Content-Type` header.
Starting with _version 4.3_, if a request has no content type header, `application/octet-stream` is assumed, as
recommended by `RFC 2616`.
Previously, the body of such messages was ignored.
Starting with _Spring Integration 2.0_, MultiPart File support is implemented.
If the request has been wrapped as a _MultipartHttpServletRequest_, when using the default converters, that request will be converted to a Message payload that is a MultiValueMap containing values that may be byte arrays, Strings, or instances of Spring's `MultipartFile` depending on the content type of the individual parts.

View File

@@ -85,3 +85,10 @@ pushing to the left end and reading from the right end.
It is now possible to configure the reading and writing direction using `rightPop` and `leftPush` options for the
`RedisQueueMessageDrivenEndpoint` and `RedisQueueOutboundChannelAdapter` respectively.
See <<redis-queue-inbound-channel-adapter>> and <<redis-queue-outbound-channel-adapter>> for more information.
==== HTTP Changes
Previously, with requests that had a body (such as `POST`) that had no `content-type` header, the body was ignored.
With this release, the content type of such requests is considered to be `application/octet-stream` as recommended
by RFC 2616.
See <<http-inbound>> for more information.