From dc0a934c998cc329bda3a4a76bc3290e3518546f Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Sun, 5 Nov 2017 16:12:21 +0100 Subject: [PATCH] MockHttpServletResponse.getDateHeader returns -1 for non-existent header Includes consistent getDateHeader results in both MockHttpServletResponse variants (spring-test and spring-web) Issue: SPR-16160 (cherry picked from commit 80a0cf7) --- .../mock/web/MockHttpServletResponse.java | 35 +++-- .../web/MockHttpServletResponseTests.java | 8 +- .../web/test/MockHttpServletResponse.java | 2 +- .../ServletWebRequestHttpMethodsTests.java | 127 ++++++++---------- 4 files changed, 85 insertions(+), 87 deletions(-) diff --git a/spring-test/src/main/java/org/springframework/mock/web/MockHttpServletResponse.java b/spring-test/src/main/java/org/springframework/mock/web/MockHttpServletResponse.java index 1d5b838dfe..9983ff797b 100644 --- a/spring-test/src/main/java/org/springframework/mock/web/MockHttpServletResponse.java +++ b/spring-test/src/main/java/org/springframework/mock/web/MockHttpServletResponse.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * Copyright 2002-2017 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. @@ -23,6 +23,7 @@ import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.io.UnsupportedEncodingException; import java.io.Writer; +import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; @@ -493,27 +494,33 @@ public class MockHttpServletResponse implements HttpServletResponse { setHeaderValue(name, formatDate(value)); } - public long getDateHeader(String name) { - SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT, Locale.US); - dateFormat.setTimeZone(GMT); - try { - return dateFormat.parse(getHeader(name)).getTime(); - } - catch (ParseException ex) { - throw new IllegalArgumentException( - "Value for header '" + name + "' is not a valid Date: " + getHeader(name)); - } - } - @Override public void addDateHeader(String name, long value) { addHeaderValue(name, formatDate(value)); } + public long getDateHeader(String name) { + String headerValue = getHeader(name); + if (headerValue == null) { + return -1; + } + try { + return newDateFormat().parse(getHeader(name)).getTime(); + } + catch (ParseException ex) { + throw new IllegalArgumentException( + "Value for header '" + name + "' is not a valid Date: " + headerValue); + } + } + private String formatDate(long date) { + return newDateFormat().format(new Date(date)); + } + + private DateFormat newDateFormat() { SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT, Locale.US); dateFormat.setTimeZone(GMT); - return dateFormat.format(new Date(date)); + return dateFormat; } @Override diff --git a/spring-test/src/test/java/org/springframework/mock/web/MockHttpServletResponseTests.java b/spring-test/src/test/java/org/springframework/mock/web/MockHttpServletResponseTests.java index 96b55e8111..a14c5f5894 100644 --- a/spring-test/src/test/java/org/springframework/mock/web/MockHttpServletResponseTests.java +++ b/spring-test/src/test/java/org/springframework/mock/web/MockHttpServletResponseTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * Copyright 2002-2017 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. @@ -273,6 +273,12 @@ public class MockHttpServletResponseTests { response.getDateHeader("Last-Modified"); } + @Test // SPR-16160 + public void getNonExistentDateHeader() { + assertNull(response.getHeader("Last-Modified")); + assertEquals(-1, response.getDateHeader("Last-Modified")); + } + @Test // SPR-10414 public void modifyStatusAfterSendError() throws IOException { response.sendError(HttpServletResponse.SC_NOT_FOUND); diff --git a/spring-web/src/test/java/org/springframework/mock/web/test/MockHttpServletResponse.java b/spring-web/src/test/java/org/springframework/mock/web/test/MockHttpServletResponse.java index c0986b2955..8447e6c28f 100644 --- a/spring-web/src/test/java/org/springframework/mock/web/test/MockHttpServletResponse.java +++ b/spring-web/src/test/java/org/springframework/mock/web/test/MockHttpServletResponse.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * Copyright 2002-2017 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. diff --git a/spring-web/src/test/java/org/springframework/web/context/request/ServletWebRequestHttpMethodsTests.java b/spring-web/src/test/java/org/springframework/web/context/request/ServletWebRequestHttpMethodsTests.java index 0b9dee0c22..a791f308ee 100644 --- a/spring-web/src/test/java/org/springframework/web/context/request/ServletWebRequestHttpMethodsTests.java +++ b/spring-web/src/test/java/org/springframework/web/context/request/ServletWebRequestHttpMethodsTests.java @@ -16,6 +16,7 @@ package org.springframework.web.context.request; +import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Arrays; import java.util.Date; @@ -35,7 +36,8 @@ import org.springframework.mock.web.test.MockHttpServletResponse; import static org.junit.Assert.*; /** - * Parameterized tests for ServletWebRequest + * Parameterized tests for {@link ServletWebRequest}. + * * @author Juergen Hoeller * @author Brian Clozel * @author Markus Malkusch @@ -61,8 +63,7 @@ public class ServletWebRequestHttpMethodsTests { @Parameters(name = "{0}") static public Iterable safeMethods() { return Arrays.asList(new Object[][] { - {"GET"}, - {"HEAD"} + {"GET"}, {"HEAD"} }); } @@ -100,11 +101,11 @@ public class ServletWebRequestHttpMethodsTests { @Test // SPR-14559 public void checkNotModifiedInvalidIfNoneMatchHeader() { - String eTag = "\"etagvalue\""; + String etag = "\"etagvalue\""; servletRequest.addHeader("If-None-Match", "missingquotes"); - assertFalse(request.checkNotModified(eTag)); + assertFalse(request.checkNotModified(etag)); assertEquals(200, servletResponse.getStatus()); - assertEquals(eTag, servletResponse.getHeader("ETag")); + assertEquals(etag, servletResponse.getHeader("ETag")); } @Test @@ -120,12 +121,11 @@ public class ServletWebRequestHttpMethodsTests { } @Test - public void checkNotModifiedTimestamp() throws Exception { + public void checkNotModifiedTimestamp() { long epochTime = currentDate.getTime(); servletRequest.addHeader("If-Modified-Since", epochTime); assertTrue(request.checkNotModified(epochTime)); - assertEquals(304, servletResponse.getStatus()); assertEquals(dateFormat.format(epochTime), servletResponse.getHeader("Last-Modified")); } @@ -136,119 +136,109 @@ public class ServletWebRequestHttpMethodsTests { servletRequest.addHeader("If-Modified-Since", oneMinuteAgo); assertFalse(request.checkNotModified(currentDate.getTime())); - assertEquals(200, servletResponse.getStatus()); assertEquals(dateFormat.format(currentDate.getTime()), servletResponse.getHeader("Last-Modified")); } @Test public void checkNotModifiedETag() { - String eTag = "\"Foo\""; - servletRequest.addHeader("If-None-Match", eTag); - - assertTrue(request.checkNotModified(eTag)); + String etag = "\"Foo\""; + servletRequest.addHeader("If-None-Match", etag); + assertTrue(request.checkNotModified(etag)); assertEquals(304, servletResponse.getStatus()); - assertEquals(eTag, servletResponse.getHeader("ETag")); + assertEquals(etag, servletResponse.getHeader("ETag")); } @Test public void checkNotModifiedETagWithSeparatorChars() { - String eTag = "\"Foo, Bar\""; - servletRequest.addHeader("If-None-Match", eTag); - - assertTrue(request.checkNotModified(eTag)); + String etag = "\"Foo, Bar\""; + servletRequest.addHeader("If-None-Match", etag); + assertTrue(request.checkNotModified(etag)); assertEquals(304, servletResponse.getStatus()); - assertEquals(eTag, servletResponse.getHeader("ETag")); + assertEquals(etag, servletResponse.getHeader("ETag")); } @Test public void checkModifiedETag() { String currentETag = "\"Foo\""; - String oldEtag = "Bar"; - servletRequest.addHeader("If-None-Match", oldEtag); + String oldETag = "Bar"; + servletRequest.addHeader("If-None-Match", oldETag); assertFalse(request.checkNotModified(currentETag)); - assertEquals(200, servletResponse.getStatus()); assertEquals(currentETag, servletResponse.getHeader("ETag")); } @Test public void checkNotModifiedUnpaddedETag() { - String eTag = "Foo"; - String paddedEtag = String.format("\"%s\"", eTag); - servletRequest.addHeader("If-None-Match", paddedEtag); - - assertTrue(request.checkNotModified(eTag)); + String etag = "Foo"; + String paddedETag = String.format("\"%s\"", etag); + servletRequest.addHeader("If-None-Match", paddedETag); + assertTrue(request.checkNotModified(etag)); assertEquals(304, servletResponse.getStatus()); - assertEquals(paddedEtag, servletResponse.getHeader("ETag")); + assertEquals(paddedETag, servletResponse.getHeader("ETag")); } @Test public void checkModifiedUnpaddedETag() { String currentETag = "Foo"; - String oldEtag = "Bar"; - servletRequest.addHeader("If-None-Match", oldEtag); + String oldETag = "Bar"; + servletRequest.addHeader("If-None-Match", oldETag); assertFalse(request.checkNotModified(currentETag)); - assertEquals(200, servletResponse.getStatus()); assertEquals(String.format("\"%s\"", currentETag), servletResponse.getHeader("ETag")); } @Test public void checkNotModifiedWildcardIsIgnored() { - String eTag = "\"Foo\""; + String etag = "\"Foo\""; servletRequest.addHeader("If-None-Match", "*"); - assertFalse(request.checkNotModified(eTag)); - + assertFalse(request.checkNotModified(etag)); assertEquals(200, servletResponse.getStatus()); - assertEquals(eTag, servletResponse.getHeader("ETag")); + assertEquals(etag, servletResponse.getHeader("ETag")); } @Test public void checkNotModifiedETagAndTimestamp() { - String eTag = "\"Foo\""; - servletRequest.addHeader("If-None-Match", eTag); + String etag = "\"Foo\""; + servletRequest.addHeader("If-None-Match", etag); servletRequest.addHeader("If-Modified-Since", currentDate.getTime()); - assertTrue(request.checkNotModified(eTag, currentDate.getTime())); - + assertTrue(request.checkNotModified(etag, currentDate.getTime())); assertEquals(304, servletResponse.getStatus()); - assertEquals(eTag, servletResponse.getHeader("ETag")); + assertEquals(etag, servletResponse.getHeader("ETag")); assertEquals(dateFormat.format(currentDate.getTime()), servletResponse.getHeader("Last-Modified")); } @Test // SPR-14224 public void checkNotModifiedETagAndModifiedTimestamp() { - String eTag = "\"Foo\""; - servletRequest.addHeader("If-None-Match", eTag); + String etag = "\"Foo\""; + servletRequest.addHeader("If-None-Match", etag); long currentEpoch = currentDate.getTime(); long oneMinuteAgo = currentEpoch - (1000 * 60); servletRequest.addHeader("If-Modified-Since", oneMinuteAgo); - assertTrue(request.checkNotModified(eTag, currentEpoch)); - + assertTrue(request.checkNotModified(etag, currentEpoch)); assertEquals(304, servletResponse.getStatus()); - assertEquals(eTag, servletResponse.getHeader("ETag")); + assertEquals(etag, servletResponse.getHeader("ETag")); assertEquals(dateFormat.format(currentEpoch), servletResponse.getHeader("Last-Modified")); } @Test - public void checkModifiedETagAndNotModifiedTimestamp() throws Exception { + public void checkModifiedETagAndNotModifiedTimestamp() { String currentETag = "\"Foo\""; - String oldEtag = "\"Bar\""; - servletRequest.addHeader("If-None-Match", oldEtag); + String oldETag = "\"Bar\""; + servletRequest.addHeader("If-None-Match", oldETag); long epochTime = currentDate.getTime(); servletRequest.addHeader("If-Modified-Since", epochTime); assertFalse(request.checkNotModified(currentETag, epochTime)); - assertEquals(200, servletResponse.getStatus()); assertEquals(currentETag, servletResponse.getHeader("ETag")); assertEquals(dateFormat.format(epochTime), servletResponse.getHeader("Last-Modified")); @@ -256,65 +246,60 @@ public class ServletWebRequestHttpMethodsTests { @Test public void checkNotModifiedETagWeakStrong() { - String eTag = "\"Foo\""; - String weakEtag = String.format("W/%s", eTag); - servletRequest.addHeader("If-None-Match", eTag); - - assertTrue(request.checkNotModified(weakEtag)); + String etag = "\"Foo\""; + String weakETag = String.format("W/%s", etag); + servletRequest.addHeader("If-None-Match", etag); + assertTrue(request.checkNotModified(weakETag)); assertEquals(304, servletResponse.getStatus()); - assertEquals(weakEtag, servletResponse.getHeader("ETag")); + assertEquals(weakETag, servletResponse.getHeader("ETag")); } @Test public void checkNotModifiedETagStrongWeak() { - String eTag = "\"Foo\""; - servletRequest.addHeader("If-None-Match", String.format("W/%s", eTag)); - - assertTrue(request.checkNotModified(eTag)); + String etag = "\"Foo\""; + servletRequest.addHeader("If-None-Match", String.format("W/%s", etag)); + assertTrue(request.checkNotModified(etag)); assertEquals(304, servletResponse.getStatus()); - assertEquals(eTag, servletResponse.getHeader("ETag")); + assertEquals(etag, servletResponse.getHeader("ETag")); } @Test public void checkNotModifiedMultipleETags() { - String eTag = "\"Bar\""; - String multipleETags = String.format("\"Foo\", %s", eTag); + String etag = "\"Bar\""; + String multipleETags = String.format("\"Foo\", %s", etag); servletRequest.addHeader("If-None-Match", multipleETags); - assertTrue(request.checkNotModified(eTag)); - + assertTrue(request.checkNotModified(etag)); assertEquals(304, servletResponse.getStatus()); - assertEquals(eTag, servletResponse.getHeader("ETag")); + assertEquals(etag, servletResponse.getHeader("ETag")); } @Test - public void checkNotModifiedTimestampWithLengthPart() throws Exception { + public void checkNotModifiedTimestampWithLengthPart() throws ParseException { long epochTime = dateFormat.parse(CURRENT_TIME).getTime(); servletRequest.setMethod("GET"); servletRequest.addHeader("If-Modified-Since", "Wed, 09 Apr 2014 09:57:42 GMT; length=13774"); assertTrue(request.checkNotModified(epochTime)); - assertEquals(304, servletResponse.getStatus()); assertEquals(dateFormat.format(epochTime), servletResponse.getHeader("Last-Modified")); } @Test - public void checkModifiedTimestampWithLengthPart() throws Exception { + public void checkModifiedTimestampWithLengthPart() throws ParseException { long epochTime = dateFormat.parse(CURRENT_TIME).getTime(); servletRequest.setMethod("GET"); servletRequest.addHeader("If-Modified-Since", "Wed, 08 Apr 2014 09:57:42 GMT; length=13774"); assertFalse(request.checkNotModified(epochTime)); - assertEquals(200, servletResponse.getStatus()); assertEquals(dateFormat.format(epochTime), servletResponse.getHeader("Last-Modified")); } @Test - public void checkNotModifiedTimestampConditionalPut() throws Exception { + public void checkNotModifiedTimestampConditionalPut() { long currentEpoch = currentDate.getTime(); long oneMinuteAgo = currentEpoch - (1000 * 60); servletRequest.setMethod("PUT"); @@ -326,7 +311,7 @@ public class ServletWebRequestHttpMethodsTests { } @Test - public void checkNotModifiedTimestampConditionalPutConflict() throws Exception { + public void checkNotModifiedTimestampConditionalPutConflict() { long currentEpoch = currentDate.getTime(); long oneMinuteAgo = currentEpoch - (1000 * 60); servletRequest.setMethod("PUT");