From c97afe92fedf3c7b0900bb0da28c4bf26f3c754e Mon Sep 17 00:00:00 2001 From: Gary Russell Date: Mon, 18 Jan 2016 11:23:29 -0500 Subject: [PATCH] INT-3934: HTTP Requests Without Content-Type JIRA: https://jira.spring.io/browse/INT-3934 Coerce a missing Content-Type to `application/octet-stream`. --- .../HttpRequestHandlingEndpointSupport.java | 10 +++--- ...pRequestHandlingMessagingGatewayTests.java | 36 +++++++++---------- src/reference/asciidoc/http.adoc | 5 +++ src/reference/asciidoc/whats-new.adoc | 7 ++++ 4 files changed, 34 insertions(+), 24 deletions(-) diff --git a/spring-integration-http/src/main/java/org/springframework/integration/http/inbound/HttpRequestHandlingEndpointSupport.java b/spring-integration-http/src/main/java/org/springframework/integration/http/inbound/HttpRequestHandlingEndpointSupport.java index 3541d25f63..aba5025ff3 100644 --- a/spring-integration-http/src/main/java/org/springframework/integration/http/inbound/HttpRequestHandlingEndpointSupport.java +++ b/spring-integration-http/src/main/java/org/springframework/integration/http/inbound/HttpRequestHandlingEndpointSupport.java @@ -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; diff --git a/spring-integration-http/src/test/java/org/springframework/integration/http/inbound/HttpRequestHandlingMessagingGatewayTests.java b/spring-integration-http/src/test/java/org/springframework/integration/http/inbound/HttpRequestHandlingMessagingGatewayTests.java index 521cc58984..19e8a26451 100644 --- a/spring-integration-http/src/test/java/org/springframework/integration/http/inbound/HttpRequestHandlingMessagingGatewayTests.java +++ b/spring-integration-http/src/test/java/org/springframework/integration/http/inbound/HttpRequestHandlingMessagingGatewayTests.java @@ -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); diff --git a/src/reference/asciidoc/http.adoc b/src/reference/asciidoc/http.adoc index ad3299c5f7..24bde3b992 100644 --- a/src/reference/asciidoc/http.adoc +++ b/src/reference/asciidoc/http.adoc @@ -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. diff --git a/src/reference/asciidoc/whats-new.adoc b/src/reference/asciidoc/whats-new.adoc index 5fe0dbe8ca..092d00331f 100644 --- a/src/reference/asciidoc/whats-new.adoc +++ b/src/reference/asciidoc/whats-new.adoc @@ -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 <> and <> 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 <> for more information.