Skip to content

Commit 80a0cf7

Browse files
committed
MockHttpServletResponse.getDateHeader returns -1 for non-existent header
Includes consistent getDateHeader results in both MockHttpServletResponse variants (spring-test and spring-web) Issue: SPR-16160
1 parent 0edf4d6 commit 80a0cf7

File tree

4 files changed

+113
-120
lines changed

4 files changed

+113
-120
lines changed

spring-test/src/main/java/org/springframework/mock/web/MockHttpServletResponse.java

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import java.io.PrintWriter;
2424
import java.io.UnsupportedEncodingException;
2525
import java.io.Writer;
26+
import java.text.DateFormat;
2627
import java.text.ParseException;
2728
import java.text.SimpleDateFormat;
2829
import java.util.ArrayList;
@@ -517,27 +518,33 @@ public void setDateHeader(String name, long value) {
517518
setHeaderValue(name, formatDate(value));
518519
}
519520

521+
@Override
522+
public void addDateHeader(String name, long value) {
523+
addHeaderValue(name, formatDate(value));
524+
}
525+
520526
public long getDateHeader(String name) {
521-
SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT, Locale.US);
522-
dateFormat.setTimeZone(GMT);
527+
String headerValue = getHeader(name);
528+
if (headerValue == null) {
529+
return -1;
530+
}
523531
try {
524-
return dateFormat.parse(getHeader(name)).getTime();
532+
return newDateFormat().parse(getHeader(name)).getTime();
525533
}
526534
catch (ParseException ex) {
527535
throw new IllegalArgumentException(
528-
"Value for header '" + name + "' is not a valid Date: " + getHeader(name));
536+
"Value for header '" + name + "' is not a valid Date: " + headerValue);
529537
}
530538
}
531539

532-
@Override
533-
public void addDateHeader(String name, long value) {
534-
addHeaderValue(name, formatDate(value));
540+
private String formatDate(long date) {
541+
return newDateFormat().format(new Date(date));
535542
}
536543

537-
private String formatDate(long date) {
544+
private DateFormat newDateFormat() {
538545
SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT, Locale.US);
539546
dateFormat.setTimeZone(GMT);
540-
return dateFormat.format(new Date(date));
547+
return dateFormat;
541548
}
542549

543550
@Override

spring-test/src/test/java/org/springframework/mock/web/MockHttpServletResponseTests.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,12 @@ public void getInvalidDateHeader() {
291291
response.getDateHeader("Last-Modified");
292292
}
293293

294+
@Test // SPR-16160
295+
public void getNonExistentDateHeader() {
296+
assertNull(response.getHeader("Last-Modified"));
297+
assertEquals(-1, response.getDateHeader("Last-Modified"));
298+
}
299+
294300
@Test // SPR-10414
295301
public void modifyStatusAfterSendError() throws IOException {
296302
response.sendError(HttpServletResponse.SC_NOT_FOUND);

spring-web/src/test/java/org/springframework/mock/web/test/MockHttpServletResponse.java

Lines changed: 29 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -23,16 +23,17 @@
2323
import java.io.PrintWriter;
2424
import java.io.UnsupportedEncodingException;
2525
import java.io.Writer;
26-
import java.time.Instant;
27-
import java.time.ZoneId;
28-
import java.time.ZonedDateTime;
29-
import java.time.format.DateTimeParseException;
26+
import java.text.DateFormat;
27+
import java.text.ParseException;
28+
import java.text.SimpleDateFormat;
3029
import java.util.ArrayList;
3130
import java.util.Collection;
3231
import java.util.Collections;
32+
import java.util.Date;
3333
import java.util.List;
3434
import java.util.Locale;
3535
import java.util.Map;
36+
import java.util.TimeZone;
3637
import javax.servlet.ServletOutputStream;
3738
import javax.servlet.http.Cookie;
3839
import javax.servlet.http.HttpServletResponse;
@@ -44,8 +45,6 @@
4445
import org.springframework.util.StringUtils;
4546
import org.springframework.web.util.WebUtils;
4647

47-
import static java.time.format.DateTimeFormatter.*;
48-
4948
/**
5049
* Mock implementation of the {@link javax.servlet.http.HttpServletResponse} interface.
5150
*
@@ -60,7 +59,9 @@ public class MockHttpServletResponse implements HttpServletResponse {
6059

6160
private static final String CHARSET_PREFIX = "charset=";
6261

63-
private static final ZoneId GMT = ZoneId.of("GMT");
62+
private static final String DATE_FORMAT = "EEE, dd MMM yyyy HH:mm:ss zzz";
63+
64+
private static final TimeZone GMT = TimeZone.getTimeZone("GMT");
6465

6566

6667
//---------------------------------------------------------------------
@@ -292,7 +293,7 @@ public void reset() {
292293
this.characterEncoding = null;
293294
this.contentLength = 0;
294295
this.contentType = null;
295-
this.locale = null;
296+
this.locale = Locale.getDefault();
296297
this.cookies.clear();
297298
this.headers.clear();
298299
this.status = HttpServletResponse.SC_OK;
@@ -302,9 +303,7 @@ public void reset() {
302303
@Override
303304
public void setLocale(Locale locale) {
304305
this.locale = locale;
305-
if (locale != null) {
306-
doAddHeaderValue(HttpHeaders.ACCEPT_LANGUAGE, locale.toLanguageTag(), true);
307-
}
306+
doAddHeaderValue(HttpHeaders.ACCEPT_LANGUAGE, locale.toLanguageTag(), true);
308307
}
309308

310309
@Override
@@ -507,25 +506,33 @@ public void setDateHeader(String name, long value) {
507506
setHeaderValue(name, formatDate(value));
508507
}
509508

509+
@Override
510+
public void addDateHeader(String name, long value) {
511+
addHeaderValue(name, formatDate(value));
512+
}
513+
510514
public long getDateHeader(String name) {
515+
String headerValue = getHeader(name);
516+
if (headerValue == null) {
517+
return -1;
518+
}
511519
try {
512-
return ZonedDateTime.parse(getHeader(name), RFC_1123_DATE_TIME).toInstant().toEpochMilli();
520+
return newDateFormat().parse(getHeader(name)).getTime();
513521
}
514-
catch (DateTimeParseException ex) {
522+
catch (ParseException ex) {
515523
throw new IllegalArgumentException(
516-
"Value for header '" + name + "' is not a valid Date: " + getHeader(name));
524+
"Value for header '" + name + "' is not a valid Date: " + headerValue);
517525
}
518526
}
519527

520-
@Override
521-
public void addDateHeader(String name, long value) {
522-
addHeaderValue(name, formatDate(value));
528+
private String formatDate(long date) {
529+
return newDateFormat().format(new Date(date));
523530
}
524531

525-
private String formatDate(long date) {
526-
Instant instant = Instant.ofEpochMilli(date);
527-
ZonedDateTime zonedDateTime = ZonedDateTime.ofInstant(instant, GMT);
528-
return RFC_1123_DATE_TIME.format(zonedDateTime);
532+
private DateFormat newDateFormat() {
533+
SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT, Locale.US);
534+
dateFormat.setTimeZone(GMT);
535+
return dateFormat;
529536
}
530537

531538
@Override
@@ -576,7 +583,7 @@ else if (HttpHeaders.ACCEPT_LANGUAGE.equalsIgnoreCase(name)) {
576583
HttpHeaders headers = new HttpHeaders();
577584
headers.add(HttpHeaders.ACCEPT_LANGUAGE, value.toString());
578585
List<Locale> locales = headers.getAcceptLanguageAsLocales();
579-
setLocale(locales.isEmpty() ? null : locales.get(0));
586+
this.locale = (!locales.isEmpty() ? locales.get(0) : Locale.getDefault());
580587
return true;
581588
}
582589
else {

0 commit comments

Comments
 (0)