Repository: camel Updated Branches: refs/heads/master 41277fbdd -> a3de7e193
CAMEL-9105: Camel DefaultHttpBinding should convert response Date headers to HTTP-friendly format. Thanks to Sergey Beryozkin for the patch. Project: http://git-wip-us.apache.org/repos/asf/camel/repo Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/a3de7e19 Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/a3de7e19 Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/a3de7e19 Branch: refs/heads/master Commit: a3de7e1931ef5ee22094e192174f55c50896adf5 Parents: 41277fb Author: Claus Ibsen <[email protected]> Authored: Mon Sep 7 14:18:44 2015 +0200 Committer: Claus Ibsen <[email protected]> Committed: Mon Sep 7 14:18:44 2015 +0200 ---------------------------------------------------------------------- .../camel/http/common/DefaultHttpBinding.java | 60 +++++++++++++++++- .../http/common/DefaultHttpBindingTest.java | 66 ++++++++++++++++++++ .../src/test/resources/log4j.properties | 36 +++++++++++ 3 files changed, 160 insertions(+), 2 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/camel/blob/a3de7e19/components/camel-http-common/src/main/java/org/apache/camel/http/common/DefaultHttpBinding.java ---------------------------------------------------------------------- diff --git a/components/camel-http-common/src/main/java/org/apache/camel/http/common/DefaultHttpBinding.java b/components/camel-http-common/src/main/java/org/apache/camel/http/common/DefaultHttpBinding.java index dcb3f20..aa6c1e7 100644 --- a/components/camel-http-common/src/main/java/org/apache/camel/http/common/DefaultHttpBinding.java +++ b/components/camel-http-common/src/main/java/org/apache/camel/http/common/DefaultHttpBinding.java @@ -24,9 +24,13 @@ import java.io.OutputStream; import java.io.PrintWriter; import java.io.Serializable; import java.net.URLDecoder; +import java.text.SimpleDateFormat; +import java.util.Date; import java.util.Enumeration; import java.util.Iterator; +import java.util.Locale; import java.util.Map; +import java.util.TimeZone; import javax.activation.DataHandler; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletRequest; @@ -54,7 +58,19 @@ import org.slf4j.LoggerFactory; */ public class DefaultHttpBinding implements HttpBinding { + /** + * Whether Date/Locale should be converted to String types (enabled by default) + */ + public static final String DATE_LOCALE_CONVERSION = "CamelHttpBindingDateLocaleConversion"; + + /** + * The data format used for storing java.util.Date instances as a String value. + */ + public static final String DATE_FORMAT = "EEE, dd MMM yyyy HH:mm:ss zzz"; + private static final Logger LOG = LoggerFactory.getLogger(DefaultHttpBinding.class); + private static final TimeZone TIME_ZONE_GMT = TimeZone.getTimeZone("GMT"); + private boolean useReaderForPayload; private boolean eagerCheckContentAvailable; private boolean transferException; @@ -282,7 +298,7 @@ public class DefaultHttpBinding implements HttpBinding { // use an iterator as there can be multiple values. (must not use a delimiter) final Iterator<?> it = ObjectHelper.createIterator(value, null); while (it.hasNext()) { - String headerValue = exchange.getContext().getTypeConverter().convertTo(String.class, it.next()); + String headerValue = convertHeaderValueToString(exchange, it.next()); if (headerValue != null && headerFilterStrategy != null && !headerFilterStrategy.applyFilterToCamelHeaders(key, headerValue, exchange)) { response.addHeader(key, headerValue); @@ -300,10 +316,28 @@ public class DefaultHttpBinding implements HttpBinding { } } + protected String convertHeaderValueToString(Exchange exchange, Object headerValue) { + if ((headerValue instanceof Date || headerValue instanceof Locale) + && convertDateAndLocaleLocally(exchange)) { + if (headerValue instanceof Date) { + return toHttpDate((Date)headerValue); + } else { + return toHttpLanguage((Locale)headerValue); + } + } else { + return exchange.getContext().getTypeConverter().convertTo(String.class, headerValue); + } + } + + protected boolean convertDateAndLocaleLocally(Exchange exchange) { + // This check is done only if a given header value is Date or Locale + return exchange.getProperty(DATE_LOCALE_CONVERSION, Boolean.TRUE, Boolean.class); + } + protected boolean isText(String contentType) { if (contentType != null) { String temp = contentType.toLowerCase(); - if (temp.indexOf("text") >= 0 || temp.indexOf("html") >= 0) { + if (temp.contains("text") || temp.contains("html")) { return true; } } @@ -491,4 +525,26 @@ public class DefaultHttpBinding implements HttpBinding { this.headerFilterStrategy = headerFilterStrategy; } + protected static SimpleDateFormat getHttpDateFormat() { + SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT, Locale.US); + dateFormat.setTimeZone(TIME_ZONE_GMT); + return dateFormat; + } + + protected static String toHttpDate(Date date) { + SimpleDateFormat format = getHttpDateFormat(); + return format.format(date); + } + + protected static String toHttpLanguage(Locale locale) { + StringBuilder sb = new StringBuilder(); + sb.append(locale.getLanguage()); + if (locale.getCountry() != null) { + // Locale.toString() will use a "_" separator instead, + // while '-' is expected in headers such as Content-Language, etc: + // http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.10 + sb.append('-').append(locale.getCountry()); + } + return sb.toString(); + } } http://git-wip-us.apache.org/repos/asf/camel/blob/a3de7e19/components/camel-http-common/src/test/java/org/apache/camel/http/common/DefaultHttpBindingTest.java ---------------------------------------------------------------------- diff --git a/components/camel-http-common/src/test/java/org/apache/camel/http/common/DefaultHttpBindingTest.java b/components/camel-http-common/src/test/java/org/apache/camel/http/common/DefaultHttpBindingTest.java new file mode 100644 index 0000000..dbeb01f --- /dev/null +++ b/components/camel-http-common/src/test/java/org/apache/camel/http/common/DefaultHttpBindingTest.java @@ -0,0 +1,66 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.http.common; + +import java.util.Date; +import java.util.Locale; + +import org.apache.camel.Exchange; +import org.apache.camel.test.junit4.CamelTestSupport; +import org.junit.Test; + +public class DefaultHttpBindingTest extends CamelTestSupport { + + @Test + public void testConvertDate() throws Exception { + DefaultHttpBinding binding = new DefaultHttpBinding(); + Date date = new Date(); + Exchange exchange = super.createExchangeWithBody(null); + + String value = binding.convertHeaderValueToString(exchange, date); + assertNotEquals(value, date.toString()); + assertEquals(value, DefaultHttpBinding.getHttpDateFormat().format(date)); + } + @Test + public void testConvertDateTypeConverter() throws Exception { + DefaultHttpBinding binding = new DefaultHttpBinding(); + Date date = new Date(); + Exchange exchange = super.createExchangeWithBody(null); + exchange.setProperty(DefaultHttpBinding.DATE_LOCALE_CONVERSION, false); + String value = binding.convertHeaderValueToString(exchange, date); + assertEquals(value, date.toString()); + } + @Test + public void testConvertLocale() throws Exception { + DefaultHttpBinding binding = new DefaultHttpBinding(); + Locale l = Locale.SIMPLIFIED_CHINESE; + Exchange exchange = super.createExchangeWithBody(null); + + String value = binding.convertHeaderValueToString(exchange, l); + assertNotEquals(value, l.toString()); + assertEquals("zh-CN", value); + } + @Test + public void testConvertLocaleTypeConverter() throws Exception { + DefaultHttpBinding binding = new DefaultHttpBinding(); + Locale l = Locale.SIMPLIFIED_CHINESE; + Exchange exchange = super.createExchangeWithBody(null); + exchange.setProperty(DefaultHttpBinding.DATE_LOCALE_CONVERSION, false); + String value = binding.convertHeaderValueToString(exchange, l); + assertEquals(value, l.toString()); + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/a3de7e19/components/camel-http-common/src/test/resources/log4j.properties ---------------------------------------------------------------------- diff --git a/components/camel-http-common/src/test/resources/log4j.properties b/components/camel-http-common/src/test/resources/log4j.properties new file mode 100644 index 0000000..24f96f5 --- /dev/null +++ b/components/camel-http-common/src/test/resources/log4j.properties @@ -0,0 +1,36 @@ +## ------------------------------------------------------------------------ +## Licensed to the Apache Software Foundation (ASF) under one or more +## contributor license agreements. See the NOTICE file distributed with +## this work for additional information regarding copyright ownership. +## The ASF licenses this file to You under the Apache License, Version 2.0 +## (the "License"); you may not use this file except in compliance with +## the License. You may obtain a copy of the License at +## +## http://www.apache.org/licenses/LICENSE-2.0 +## +## Unless required by applicable law or agreed to in writing, software +## distributed under the License is distributed on an "AS IS" BASIS, +## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +## See the License for the specific language governing permissions and +## limitations under the License. +## ------------------------------------------------------------------------ + +# +# The logging properties used for testing +# +log4j.rootLogger=INFO, file + +# uncomment the following to enable camel debugging +#log4j.logger.org.apache.camel=DEBUG + +# CONSOLE appender not used by default +log4j.appender.out=org.apache.log4j.ConsoleAppender +log4j.appender.out.layout=org.apache.log4j.PatternLayout +#log4j.appender.out.layout.ConversionPattern=[%30.30t] %-30.30c{1} %-5p %m%n +log4j.appender.out.layout.ConversionPattern=%d [%-50.50t] %-5p %-30.30c{1} - %m%n + +# File appender +log4j.appender.file=org.apache.log4j.FileAppender +log4j.appender.file.layout=org.apache.log4j.PatternLayout +log4j.appender.file.layout.ConversionPattern=%d [%-15.15t] %-5p %-30.30c{1} - %m%n +log4j.appender.file.file=target/camel-http-common-test.log
