Re-enable support for invalid Expires attributes in MockCookie

Changes introduced in commit 9b2087618b
caused a regression for Cookie support in MockHttpServletResponse.
Specifically, an Expires attribute that cannot be parsed using
`ZonedDateTime.parse()` now results in an exception; whereas,
previously an entry such as `Expires=0` was allowed.

This commit fixes this issue in MockCookie by catching and ignoring any
DateTimeException thrown while attempting to parse an Expires attribute.

Closes gh-23911
This commit is contained in:
Sam Brannen
2019-11-06 18:28:28 +01:00
parent 9960ed55aa
commit 29599a93a4
4 changed files with 57 additions and 4 deletions

View File

@@ -16,6 +16,7 @@
package org.springframework.mock.web;
import java.time.DateTimeException;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
@@ -31,6 +32,7 @@ import org.springframework.util.StringUtils;
*
* @author Vedran Pavic
* @author Juergen Hoeller
* @author Sam Brannen
* @since 5.1
*/
public class MockCookie extends Cookie {
@@ -119,8 +121,13 @@ public class MockCookie extends Cookie {
cookie.setMaxAge(Integer.parseInt(extractAttributeValue(attribute, setCookieHeader)));
}
else if (StringUtils.startsWithIgnoreCase(attribute, "Expires")) {
cookie.setExpires(ZonedDateTime.parse(extractAttributeValue(attribute, setCookieHeader),
DateTimeFormatter.RFC_1123_DATE_TIME));
try {
cookie.setExpires(ZonedDateTime.parse(extractAttributeValue(attribute, setCookieHeader),
DateTimeFormatter.RFC_1123_DATE_TIME));
}
catch (DateTimeException ex) {
// ignore invalid date formats
}
}
else if (StringUtils.startsWithIgnoreCase(attribute, "Path")) {
cookie.setPath(extractAttributeValue(attribute, setCookieHeader));

View File

@@ -20,6 +20,8 @@ import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
@@ -79,6 +81,15 @@ class MockCookieTests {
assertThat(cookie.getSameSite()).isEqualTo("Lax");
}
@ParameterizedTest
@ValueSource(strings = {"0", "bogus"})
void parseHeaderWithInvalidExpiresAttribute(String expiresValue) {
MockCookie cookie = MockCookie.parse("SESSION=123; Expires=" + expiresValue);
assertCookie(cookie, "SESSION", "123");
assertThat(cookie.getExpires()).isNull();
}
private void assertCookie(MockCookie cookie, String name, String value) {
assertThat(cookie.getName()).isEqualTo(name);
assertThat(cookie.getValue()).isEqualTo(value);

View File

@@ -362,6 +362,20 @@ class MockHttpServletResponseTests {
assertThat(response.getHeader(HttpHeaders.SET_COOKIE)).isEqualTo(cookieValue);
}
/**
* @since 5.1.12
*/
@Test
void setCookieHeaderWithZeroExpiresAttribute() {
String cookieValue = "SESSION=123; Path=/; Max-Age=100; Expires=0";
response.setHeader(HttpHeaders.SET_COOKIE, cookieValue);
assertNumCookies(1);
String header = response.getHeader(HttpHeaders.SET_COOKIE);
assertThat(header).isNotEqualTo(cookieValue);
// We don't assert the actual Expires value since it is based on the current time.
assertThat(header).startsWith("SESSION=123; Path=/; Max-Age=100; Expires=");
}
@Test
void addCookieHeader() {
response.addHeader(HttpHeaders.SET_COOKIE, "SESSION=123; Path=/; Secure; HttpOnly; SameSite=Lax");
@@ -386,6 +400,20 @@ class MockHttpServletResponseTests {
assertThat(response.getHeader(HttpHeaders.SET_COOKIE)).isEqualTo(cookieValue);
}
/**
* @since 5.1.12
*/
@Test
void addCookieHeaderWithZeroExpiresAttribute() {
String cookieValue = "SESSION=123; Path=/; Max-Age=100; Expires=0";
response.addHeader(HttpHeaders.SET_COOKIE, cookieValue);
assertNumCookies(1);
String header = response.getHeader(HttpHeaders.SET_COOKIE);
assertThat(header).isNotEqualTo(cookieValue);
// We don't assert the actual Expires value since it is based on the current time.
assertThat(header).startsWith("SESSION=123; Path=/; Max-Age=100; Expires=");
}
@Test
void addCookie() {
MockCookie mockCookie = new MockCookie("SESSION", "123");

View File

@@ -16,6 +16,7 @@
package org.springframework.mock.web.test;
import java.time.DateTimeException;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
@@ -31,6 +32,7 @@ import org.springframework.util.StringUtils;
*
* @author Vedran Pavic
* @author Juergen Hoeller
* @author Sam Brannen
* @since 5.1
*/
public class MockCookie extends Cookie {
@@ -119,8 +121,13 @@ public class MockCookie extends Cookie {
cookie.setMaxAge(Integer.parseInt(extractAttributeValue(attribute, setCookieHeader)));
}
else if (StringUtils.startsWithIgnoreCase(attribute, "Expires")) {
cookie.setExpires(ZonedDateTime.parse(extractAttributeValue(attribute, setCookieHeader),
DateTimeFormatter.RFC_1123_DATE_TIME));
try {
cookie.setExpires(ZonedDateTime.parse(extractAttributeValue(attribute, setCookieHeader),
DateTimeFormatter.RFC_1123_DATE_TIME));
}
catch (DateTimeException ex) {
// ignore invalid date formats
}
}
else if (StringUtils.startsWithIgnoreCase(attribute, "Path")) {
cookie.setPath(extractAttributeValue(attribute, setCookieHeader));