HttpHeaders consistently ignores invalid date header values
Issue: SPR-14144
This commit is contained in:
parent
437ffa6067
commit
448621ac58
|
@ -779,12 +779,7 @@ public class HttpHeaders implements MultiValueMap<String, String>, Serializable
|
||||||
* January 1, 1970 GMT. Returns -1 when the date is unknown.
|
* January 1, 1970 GMT. Returns -1 when the date is unknown.
|
||||||
*/
|
*/
|
||||||
public long getExpires() {
|
public long getExpires() {
|
||||||
try {
|
return getFirstDate(EXPIRES, false);
|
||||||
return getFirstDate(EXPIRES);
|
|
||||||
}
|
|
||||||
catch (IllegalArgumentException ex) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -802,7 +797,7 @@ public class HttpHeaders implements MultiValueMap<String, String>, Serializable
|
||||||
* January 1, 1970 GMT. Returns -1 when the date is unknown.
|
* January 1, 1970 GMT. Returns -1 when the date is unknown.
|
||||||
*/
|
*/
|
||||||
public long getIfModifiedSince() {
|
public long getIfModifiedSince() {
|
||||||
return getFirstDate(IF_MODIFIED_SINCE);
|
return getFirstDate(IF_MODIFIED_SINCE, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -867,7 +862,7 @@ public class HttpHeaders implements MultiValueMap<String, String>, Serializable
|
||||||
* January 1, 1970 GMT. Returns -1 when the date is unknown.
|
* January 1, 1970 GMT. Returns -1 when the date is unknown.
|
||||||
*/
|
*/
|
||||||
public long getLastModified() {
|
public long getLastModified() {
|
||||||
return getFirstDate(LAST_MODIFIED);
|
return getFirstDate(LAST_MODIFIED, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -969,12 +964,33 @@ public class HttpHeaders implements MultiValueMap<String, String>, Serializable
|
||||||
* Parse the first header value for the given header name as a date,
|
* Parse the first header value for the given header name as a date,
|
||||||
* return -1 if there is no value, or raise {@link IllegalArgumentException}
|
* return -1 if there is no value, or raise {@link IllegalArgumentException}
|
||||||
* if the value cannot be parsed as a date.
|
* if the value cannot be parsed as a date.
|
||||||
|
* @param headerName the header name
|
||||||
|
* @return the parsed date header, or -1 if none
|
||||||
*/
|
*/
|
||||||
public long getFirstDate(String headerName) {
|
public long getFirstDate(String headerName) {
|
||||||
|
return getFirstDate(headerName, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse the first header value for the given header name as a date,
|
||||||
|
* return -1 if there is no value or also in case of an invalid value
|
||||||
|
* (if {@code rejectInvalid=false}), or raise {@link IllegalArgumentException}
|
||||||
|
* if the value cannot be parsed as a date.
|
||||||
|
* @param headerName the header name
|
||||||
|
* @param rejectInvalid whether to reject invalid values with an
|
||||||
|
* {@link IllegalArgumentException} ({@code true}) or rather return -1
|
||||||
|
* in that case ({@code false})
|
||||||
|
* @return the parsed date header, or -1 if none (or invalid)
|
||||||
|
*/
|
||||||
|
private long getFirstDate(String headerName, boolean rejectInvalid) {
|
||||||
String headerValue = getFirst(headerName);
|
String headerValue = getFirst(headerName);
|
||||||
if (headerValue == null) {
|
if (headerValue == null) {
|
||||||
|
// No header value sent at all
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
if (headerValue.length() >= 3) {
|
||||||
|
// Short "0" or "-1" like values are never valid HTTP date headers...
|
||||||
|
// Let's only bother with SimpleDateFormat parsing for long enough values.
|
||||||
for (String dateFormat : DATE_FORMATS) {
|
for (String dateFormat : DATE_FORMATS) {
|
||||||
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(dateFormat, Locale.US);
|
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(dateFormat, Locale.US);
|
||||||
simpleDateFormat.setTimeZone(GMT);
|
simpleDateFormat.setTimeZone(GMT);
|
||||||
|
@ -985,9 +1001,13 @@ public class HttpHeaders implements MultiValueMap<String, String>, Serializable
|
||||||
// ignore
|
// ignore
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if (rejectInvalid) {
|
||||||
throw new IllegalArgumentException("Cannot parse date value \"" + headerValue +
|
throw new IllegalArgumentException("Cannot parse date value \"" + headerValue +
|
||||||
"\" for \"" + headerName + "\" header");
|
"\" for \"" + headerName + "\" header");
|
||||||
}
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the given date under the given header name after formatting it as a string
|
* Set the given date under the given header name after formatting it as a string
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2015 the original author or authors.
|
* Copyright 2002-2016 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -30,14 +30,9 @@ import java.util.Locale;
|
||||||
import java.util.TimeZone;
|
import java.util.TimeZone;
|
||||||
|
|
||||||
import org.hamcrest.Matchers;
|
import org.hamcrest.Matchers;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.*;
|
||||||
import static org.junit.Assert.assertThat;
|
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
import static org.junit.Assert.assertFalse;
|
|
||||||
import static org.junit.Assert.assertNull;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unit tests for {@link org.springframework.http.HttpHeaders}.
|
* Unit tests for {@link org.springframework.http.HttpHeaders}.
|
||||||
|
@ -215,9 +210,7 @@ public class HttpHeadersTests {
|
||||||
assertEquals("Invalid Expires header", "Thu, 18 Dec 2008 10:20:00 GMT", headers.getFirst("expires"));
|
assertEquals("Invalid Expires header", "Thu, 18 Dec 2008 10:20:00 GMT", headers.getFirst("expires"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// SPR-10648 (example is from INT-3063)
|
@Test // SPR-10648 (example is from INT-3063)
|
||||||
|
|
||||||
@Test
|
|
||||||
public void expiresInvalidDate() {
|
public void expiresInvalidDate() {
|
||||||
headers.set("Expires", "-1");
|
headers.set("Expires", "-1");
|
||||||
assertEquals(-1, headers.getExpires());
|
assertEquals(-1, headers.getExpires());
|
||||||
|
@ -234,6 +227,18 @@ public class HttpHeadersTests {
|
||||||
headers.getFirst("if-modified-since"));
|
headers.getFirst("if-modified-since"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test // SPR-14144
|
||||||
|
public void invalidIfModifiedSinceHeader() {
|
||||||
|
headers.set(HttpHeaders.IF_MODIFIED_SINCE, "0");
|
||||||
|
assertEquals(-1, headers.getIfModifiedSince());
|
||||||
|
|
||||||
|
headers.set(HttpHeaders.IF_MODIFIED_SINCE, "-1");
|
||||||
|
assertEquals(-1, headers.getIfModifiedSince());
|
||||||
|
|
||||||
|
headers.set(HttpHeaders.IF_MODIFIED_SINCE, "XXX");
|
||||||
|
assertEquals(-1, headers.getIfModifiedSince());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void pragma() {
|
public void pragma() {
|
||||||
String pragma = "no-cache";
|
String pragma = "no-cache";
|
||||||
|
|
Loading…
Reference in New Issue