From d76af8c2aa54061c77ccc450dec86c5355612218 Mon Sep 17 00:00:00 2001 From: Artem Bilan Date: Wed, 1 Nov 2017 12:44:47 -0400 Subject: [PATCH] Fix HTTP module for proper RFC date formats * Copy data format algorithm from the Spring Web `HttpHeaders` into the `DefaultHttpHeaderMapper` * Fix `HttpProxyScenarioTests` for proper zoned date formatting --- .../http/support/DefaultHttpHeaderMapper.java | 20 ++++++++++++------- .../http/HttpProxyScenarioTests.java | 20 +++++++++++-------- 2 files changed, 25 insertions(+), 15 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 afd0c16658..d7a0f4b009 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 @@ -257,11 +257,14 @@ public class DefaultHttpHeaderMapper implements HeaderMapper, BeanF public static final String HTTP_RESPONSE_HEADER_NAME_PATTERN = "HTTP_RESPONSE_HEADERS"; + // Copy of 'org.springframework.http.HttpHeaders#GMT' + private static final ZoneId GMT = ZoneId.of("GMT"); + // Copy of 'org.springframework.http.HttpHeaders#DATE_FORMATS' protected static final DateTimeFormatter[] DATE_FORMATS = new DateTimeFormatter[] { - DateTimeFormatter.ofPattern("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US).withZone(ZoneId.of("GMT")), - DateTimeFormatter.ofPattern("EEE, dd-MMM-yy HH:mm:ss zzz", Locale.US).withZone(ZoneId.of("GMT")), - DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss yyyy", Locale.US).withZone(ZoneId.of("GMT")) + DateTimeFormatter.RFC_1123_DATE_TIME, + DateTimeFormatter.ofPattern("EEEE, dd-MMM-yy HH:mm:ss zz", Locale.US), + DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss yyyy", Locale.US).withZone(GMT) }; static { @@ -1069,22 +1072,25 @@ public class DefaultHttpHeaderMapper implements HeaderMapper, BeanF // Utility methods protected long getFirstDate(String headerValue, String headerName) { - for (DateTimeFormatter dateFormat : DATE_FORMATS) { + for (DateTimeFormatter dateFormatter : DATE_FORMATS) { try { - return dateFormat.parse(headerValue, ZonedDateTime::from) + return ZonedDateTime.parse(headerValue, dateFormatter) .toInstant() .toEpochMilli(); } - catch (DateTimeParseException e) { + catch (DateTimeParseException ex) { // ignore } } + throw new IllegalArgumentException("Cannot parse date value '" + headerValue + "' for '" + headerName + "' header"); } protected String formatDate(long date) { - return DATE_FORMATS[0].format(Instant.ofEpochMilli(date)); + Instant instant = Instant.ofEpochMilli(date); + ZonedDateTime zonedDateTime = ZonedDateTime.ofInstant(instant, GMT); + return DATE_FORMATS[0].format(zonedDateTime); } /** diff --git a/spring-integration-http/src/test/java/org/springframework/integration/http/HttpProxyScenarioTests.java b/spring-integration-http/src/test/java/org/springframework/integration/http/HttpProxyScenarioTests.java index 8d6afa320f..03a7a3e3ac 100644 --- a/spring-integration-http/src/test/java/org/springframework/integration/http/HttpProxyScenarioTests.java +++ b/spring-integration-http/src/test/java/org/springframework/integration/http/HttpProxyScenarioTests.java @@ -23,11 +23,11 @@ import static org.junit.Assert.assertThat; import static org.mockito.ArgumentMatchers.isNull; import java.net.URI; -import java.text.DateFormat; -import java.text.SimpleDateFormat; +import java.time.Instant; +import java.time.ZoneId; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; import java.util.Calendar; -import java.util.Locale; -import java.util.TimeZone; import org.junit.Test; import org.junit.runner.RunWith; @@ -89,18 +89,22 @@ public class HttpProxyScenarioTests { @Test public void testHttpProxyScenario() throws Exception { - DateFormat dateFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US); - dateFormat.setTimeZone(TimeZone.getTimeZone("GMT")); + DateTimeFormatter dateTimeFormatter = DateTimeFormatter.RFC_1123_DATE_TIME; + ZoneId GMT = ZoneId.of("GMT"); Calendar c = Calendar.getInstance(); c.set(Calendar.MILLISECOND, 0); final long ifModifiedSince = c.getTimeInMillis(); - String ifModifiedSinceValue = dateFormat.format(ifModifiedSince); + Instant instant = Instant.ofEpochMilli(ifModifiedSince); + ZonedDateTime zonedDateTime = ZonedDateTime.ofInstant(instant, GMT); + String ifModifiedSinceValue = dateTimeFormatter.format(zonedDateTime); c.add(Calendar.DATE, -1); long ifUnmodifiedSince = c.getTimeInMillis(); - final String ifUnmodifiedSinceValue = dateFormat.format(ifUnmodifiedSince); + instant = Instant.ofEpochMilli(ifUnmodifiedSince); + zonedDateTime = ZonedDateTime.ofInstant(instant, GMT); + final String ifUnmodifiedSinceValue = dateTimeFormatter.format(zonedDateTime); MockHttpServletRequest request = new MockHttpServletRequest("GET", "/test"); request.setQueryString("foo=bar&FOO=BAR");