From 53d80b5694816c66abb45a51aee46ee9ac638786 Mon Sep 17 00:00:00 2001 From: Artem Bilan Date: Mon, 10 Oct 2016 12:17:01 -0400 Subject: [PATCH] INT-3903: user prefix as "" for HTTP headers JIRA: https://jira.spring.io/browse/INT-3903 According to RFC-6648, the "X-" prefix has been deprecated and now any use-specific headers can be mapped without any prefix * Fix `DefaultHttpHeaderMapper` for the `""` as a `userDefinedHeaderPrefix` by default Document `X-` changes --- .../http/support/DefaultHttpHeaderMapper.java | 5 +-- .../config/HttpInboundGatewayParserTests.java | 4 ++- ...tpHeaderMapperFromMessageInboundTests.java | 35 ++++++++++--------- ...pHeaderMapperFromMessageOutboundTests.java | 25 ++++++------- src/reference/asciidoc/http.adoc | 7 +++- src/reference/asciidoc/whats-new.adoc | 5 +++ 6 files changed, 48 insertions(+), 33 deletions(-) diff --git a/spring-integration-http/src/main/java/org/springframework/integration/http/support/DefaultHttpHeaderMapper.java b/spring-integration-http/src/main/java/org/springframework/integration/http/support/DefaultHttpHeaderMapper.java index 7f1a69531f..cab0411ecb 100644 --- a/spring-integration-http/src/main/java/org/springframework/integration/http/support/DefaultHttpHeaderMapper.java +++ b/spring-integration-http/src/main/java/org/springframework/integration/http/support/DefaultHttpHeaderMapper.java @@ -291,7 +291,7 @@ public class DefaultHttpHeaderMapper implements HeaderMapper, BeanF private volatile String[] excludedInboundStandardResponseHeaderNames = new String[0]; - private volatile String userDefinedHeaderPrefix = "X-"; + private volatile String userDefinedHeaderPrefix = ""; private volatile boolean isDefaultOutboundMapper; @@ -384,7 +384,8 @@ public class DefaultHttpHeaderMapper implements HeaderMapper, BeanF } /** - * Sets the prefix to use with user-defined (non-standard) headers. Default is 'X-'. + * Sets the prefix to use with user-defined (non-standard) headers. Default is an + * empty string. * @param userDefinedHeaderPrefix The user defined header prefix. */ public void setUserDefinedHeaderPrefix(String userDefinedHeaderPrefix) { diff --git a/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpInboundGatewayParserTests.java b/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpInboundGatewayParserTests.java index 6c366e0995..b09341823a 100644 --- a/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpInboundGatewayParserTests.java +++ b/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpInboundGatewayParserTests.java @@ -202,7 +202,7 @@ public class HttpInboundGatewayParserTests { headers = new HttpHeaders(); headerMapper.fromHeaders(mh, headers); assertTrue(headers.size() == 1); - List abc = headers.get("X-abc"); + List abc = headers.get("abc"); assertEquals("abc", abc.get(0)); } @@ -211,6 +211,8 @@ public class HttpInboundGatewayParserTests { DefaultHttpHeaderMapper headerMapper = (DefaultHttpHeaderMapper) TestUtils.getPropertyValue(withMappedHeadersAndConverter, "headerMapper"); + headerMapper.setUserDefinedHeaderPrefix("X-"); + HttpHeaders headers = new HttpHeaders(); headers.set("foo", "foo"); headers.set("bar", "bar"); diff --git a/spring-integration-http/src/test/java/org/springframework/integration/http/support/DefaultHttpHeaderMapperFromMessageInboundTests.java b/spring-integration-http/src/test/java/org/springframework/integration/http/support/DefaultHttpHeaderMapperFromMessageInboundTests.java index 9f099a4132..8629f619bf 100644 --- a/spring-integration-http/src/test/java/org/springframework/integration/http/support/DefaultHttpHeaderMapperFromMessageInboundTests.java +++ b/spring-integration-http/src/test/java/org/springframework/integration/http/support/DefaultHttpHeaderMapperFromMessageInboundTests.java @@ -331,10 +331,10 @@ public class DefaultHttpHeaderMapperFromMessageInboundTests { HttpHeaders headers = new HttpHeaders(); mapper.fromHeaders(new MessageHeaders(messageHeaders), headers); assertEquals(2, headers.size()); - assertEquals(1, headers.get("X-foo").size()); - assertEquals("abc", headers.getFirst("X-foo")); - assertEquals(1, headers.get("X-bar").size()); - assertEquals("123", headers.getFirst("X-bar")); + assertEquals(1, headers.get("foo").size()); + assertEquals("abc", headers.getFirst("foo")); + assertEquals(1, headers.get("bar").size()); + assertEquals("123", headers.getFirst("bar")); } @Test @@ -356,18 +356,19 @@ public class DefaultHttpHeaderMapperFromMessageInboundTests { assertNull(headers.get("z1")); assertNull(headers.get("abc")); assertNull(headers.get("def")); - assertEquals(1, headers.get("X-x1").size()); - assertEquals("x1-value", headers.getFirst("X-x1")); - assertEquals(1, headers.get("X-1z").size()); - assertEquals("1z-value", headers.getFirst("X-1z")); - assertEquals(1, headers.get("X-abcdef").size()); - assertEquals("abcdef-value", headers.getFirst("X-abcdef")); + assertEquals(1, headers.get("x1").size()); + assertEquals("x1-value", headers.getFirst("x1")); + assertEquals(1, headers.get("1z").size()); + assertEquals("1z-value", headers.getFirst("1z")); + assertEquals(1, headers.get("abcdef").size()); + assertEquals("abcdef-value", headers.getFirst("abcdef")); } @Test public void validateCustomHeaderNamePatternsAndStandardResponseHeadersMappedToHttpHeaders() throws Exception { DefaultHttpHeaderMapper mapper = new DefaultHttpHeaderMapper(); mapper.setOutboundHeaderNames(new String[] { "foo*", "HTTP_RESPONSE_HEADERS" }); + mapper.setUserDefinedHeaderPrefix("X-"); Map messageHeaders = new HashMap(); messageHeaders.put("foobar", "abc"); messageHeaders.put("Accept", "text/html"); @@ -518,9 +519,9 @@ public class DefaultHttpHeaderMapperFromMessageInboundTests { messageHeaders.put("customHeaderB", new TestClass()); mapper.fromHeaders(new MessageHeaders(messageHeaders), headers); - assertNotNull(headers.get("X-customHeaderA")); - assertEquals("123", headers.get("X-customHeaderA").get(0)); - assertNull(headers.get("X-customHeaderB")); + assertNotNull(headers.get("customHeaderA")); + assertEquals("123", headers.get("customHeaderA").get(0)); + assertNull(headers.get("customHeaderB")); } @Test @@ -540,10 +541,10 @@ public class DefaultHttpHeaderMapperFromMessageInboundTests { messageHeaders.put("customHeaderB", new TestClass()); mapper.fromHeaders(new MessageHeaders(messageHeaders), headers); - assertNotNull(headers.get("X-customHeaderA")); - assertEquals("123", headers.get("X-customHeaderA").get(0)); - assertNotNull(headers.get("X-customHeaderB")); - assertEquals("TestClass.class", headers.get("X-customHeaderB").get(0)); + assertNotNull(headers.get("customHeaderA")); + assertEquals("123", headers.get("customHeaderA").get(0)); + assertNotNull(headers.get("customHeaderB")); + assertEquals("TestClass.class", headers.get("customHeaderB").get(0)); } @Test diff --git a/spring-integration-http/src/test/java/org/springframework/integration/http/support/DefaultHttpHeaderMapperFromMessageOutboundTests.java b/spring-integration-http/src/test/java/org/springframework/integration/http/support/DefaultHttpHeaderMapperFromMessageOutboundTests.java index 54c6fc6c16..58ce6bb5db 100644 --- a/spring-integration-http/src/test/java/org/springframework/integration/http/support/DefaultHttpHeaderMapperFromMessageOutboundTests.java +++ b/spring-integration-http/src/test/java/org/springframework/integration/http/support/DefaultHttpHeaderMapperFromMessageOutboundTests.java @@ -571,10 +571,10 @@ public class DefaultHttpHeaderMapperFromMessageOutboundTests { messageHeaders.put("foo", "foo"); HttpHeaders headers = new HttpHeaders(); mapper.fromHeaders(new MessageHeaders(messageHeaders), headers); - assertNull(headers.get("foo")); - assertNotNull(headers.get("X-foo")); - assertTrue(headers.get("X-foo").size() == 1); - assertEquals("foo", headers.get("X-foo").get(0)); + assertNull(headers.get("X-foo")); + assertNotNull(headers.get("foo")); + assertTrue(headers.get("foo").size() == 1); + assertEquals("foo", headers.get("foo").get(0)); } @Test @@ -596,12 +596,12 @@ public class DefaultHttpHeaderMapperFromMessageOutboundTests { assertNull(headers.get("z1")); assertNull(headers.get("abc")); assertNull(headers.get("def")); - assertEquals(1, headers.get("X-x1").size()); - assertEquals("x1-value", headers.getFirst("X-x1")); - assertEquals(1, headers.get("X-1z").size()); - assertEquals("1z-value", headers.getFirst("X-1z")); - assertEquals(1, headers.get("X-abcdef").size()); - assertEquals("abcdef-value", headers.getFirst("X-abcdef")); + assertEquals(1, headers.get("x1").size()); + assertEquals("x1-value", headers.getFirst("x1")); + assertEquals(1, headers.get("1z").size()); + assertEquals("1z-value", headers.getFirst("1z")); + assertEquals(1, headers.get("abcdef").size()); + assertEquals("abcdef-value", headers.getFirst("abcdef")); } @Test @@ -615,8 +615,8 @@ public class DefaultHttpHeaderMapperFromMessageOutboundTests { HttpHeaders headers = new HttpHeaders(); mapper.fromHeaders(new MessageHeaders(messageHeaders), headers); assertEquals(3, headers.size()); - assertEquals(1, headers.get("X-foobar").size()); - assertEquals("abc", headers.getFirst("X-foobar")); + assertEquals(1, headers.get("foobar").size()); + assertEquals("abc", headers.getFirst("foobar")); assertEquals("text/html", headers.getContentType().toString()); assertEquals(1, headers.getAccept().size()); assertEquals(MediaType.TEXT_XML, headers.getAccept().get(0)); @@ -663,6 +663,7 @@ public class DefaultHttpHeaderMapperFromMessageOutboundTests { public void validateCustomHeaderCaseInsensitivity() throws ParseException { DefaultHttpHeaderMapper mapper = new DefaultHttpHeaderMapper(); mapper.setOutboundHeaderNames(new String[] {"*", "HTTP_REQUEST_HEADERS"}); + mapper.setUserDefinedHeaderPrefix("X-"); Map messageHeaders = new HashMap(); messageHeaders.put("foobar", "abc"); messageHeaders.put("X-bar", "xbar"); diff --git a/src/reference/asciidoc/http.adoc b/src/reference/asciidoc/http.adoc index 39a230954a..5ea2a94eee 100644 --- a/src/reference/asciidoc/http.adoc +++ b/src/reference/asciidoc/http.adoc @@ -515,7 +515,7 @@ The configuration looks very similar to the gateway: [NOTE] ===== To specify the URL; you can use either the 'url' attribute or the 'url-expression' attribute. -The 'url' is a simple string (with placedholders for URI variables, as described below); the 'url-expression' is a SpEL expression, with the Message as the root object, enabling dynamic urls. +The 'url' is a simple string (with placeholders for URI variables, as described below); the 'url-expression' is a SpEL expression, with the Message as the root object, enabling dynamic urls. The url resulting from the expression evaluation can still have placeholders for URI variables. In previous releases, some users used the place holders to replace the entire URL with a URI variable. @@ -774,6 +774,11 @@ The adapters and gateways will use the `DefaultHttpHeaderMapper` which now provi If further customization is required you can also configure a `DefaultHttpHeaderMapper` independently and inject it into the adapter via the `header-mapper` attribute. +Before _version 5.0_, the `DefaultHttpHeaderMapper` the default prefix for user-defined, non-standard HTTP headers was `X-`. +In `_version 5.0_` this has been changed to an empty string. +According to https://tools.ietf.org/html/rfc6648[RFC-6648], the use of such prefixes is now discouraged. +This option can still be customized by setting the `DefaultHttpHeaderMapper.setUserDefinedHeaderPrefix()` property. + [source,xml] ---- > for more information. The AMQP outbound endpoints now support setting a delay expression for when using the RabbitMQ Delayed Message Exchange plugin. See <> for more information. + +==== HTTP Changes + +The `DefaultHttpHeaderMapper.userDefinedHeaderPrefix` property is now an empty string by default instead of `X-`. +See <> for more information.