Skip to content

Commit 281736f

Browse files
justin-taysbrannen
authored andcommitted
Update MockCookie to use Servlet 6.0 APIs and semantics for "attributes"
Closes gh-30263
1 parent 6bfc70b commit 281736f

File tree

2 files changed

+83
-13
lines changed

2 files changed

+83
-13
lines changed

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

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -39,16 +39,14 @@
3939
@SuppressWarnings("removal")
4040
public class MockCookie extends Cookie {
4141

42-
private static final long serialVersionUID = 4312531139502726325L;
42+
private static final long serialVersionUID = 1198809317225300389L;
4343

44+
private static final String SAME_SITE = "SameSite";
45+
private static final String EXPIRES = "Expires";
4446

4547
@Nullable
4648
private ZonedDateTime expires;
4749

48-
@Nullable
49-
private String sameSite;
50-
51-
5250
/**
5351
* Construct a new {@link MockCookie} with the supplied name and value.
5452
* @param name the name
@@ -64,7 +62,7 @@ public MockCookie(String name, String value) {
6462
* @since 5.1.11
6563
*/
6664
public void setExpires(@Nullable ZonedDateTime expires) {
67-
this.expires = expires;
65+
setAttribute(EXPIRES, expires != null ? expires.format(DateTimeFormatter.RFC_1123_DATE_TIME) : null);
6866
}
6967

7068
/**
@@ -85,7 +83,7 @@ public ZonedDateTime getExpires() {
8583
* @see <a href="https://tools.ietf.org/html/draft-ietf-httpbis-rfc6265bis#section-4.1.2.7">RFC6265 bis</a>
8684
*/
8785
public void setSameSite(@Nullable String sameSite) {
88-
this.sameSite = sameSite;
86+
setAttribute(SAME_SITE, sameSite);
8987
}
9088

9189
/**
@@ -94,10 +92,9 @@ public void setSameSite(@Nullable String sameSite) {
9492
*/
9593
@Nullable
9694
public String getSameSite() {
97-
return this.sameSite;
95+
return getAttribute(SAME_SITE);
9896
}
9997

100-
10198
/**
10299
* Factory method that parses the value of the supplied "Set-Cookie" header.
103100
* @param setCookieHeader the "Set-Cookie" value; never {@code null} or empty
@@ -122,7 +119,7 @@ public static MockCookie parse(String setCookieHeader) {
122119
else if (StringUtils.startsWithIgnoreCase(attribute, "Max-Age")) {
123120
cookie.setMaxAge(Integer.parseInt(extractAttributeValue(attribute, setCookieHeader)));
124121
}
125-
else if (StringUtils.startsWithIgnoreCase(attribute, "Expires")) {
122+
else if (StringUtils.startsWithIgnoreCase(attribute, EXPIRES)) {
126123
try {
127124
cookie.setExpires(ZonedDateTime.parse(extractAttributeValue(attribute, setCookieHeader),
128125
DateTimeFormatter.RFC_1123_DATE_TIME));
@@ -140,7 +137,7 @@ else if (StringUtils.startsWithIgnoreCase(attribute, "Secure")) {
140137
else if (StringUtils.startsWithIgnoreCase(attribute, "HttpOnly")) {
141138
cookie.setHttpOnly(true);
142139
}
143-
else if (StringUtils.startsWithIgnoreCase(attribute, "SameSite")) {
140+
else if (StringUtils.startsWithIgnoreCase(attribute, SAME_SITE)) {
144141
cookie.setSameSite(extractAttributeValue(attribute, setCookieHeader));
145142
}
146143
else if (StringUtils.startsWithIgnoreCase(attribute, "Comment")) {
@@ -157,6 +154,14 @@ private static String extractAttributeValue(String attribute, String header) {
157154
return nameAndValue[1];
158155
}
159156

157+
@Override
158+
public void setAttribute(String name, @Nullable String value) {
159+
if(EXPIRES.equalsIgnoreCase(name)) {
160+
this.expires = value != null ? ZonedDateTime.parse(value, DateTimeFormatter.RFC_1123_DATE_TIME) : null;
161+
}
162+
super.setAttribute(name, value);
163+
}
164+
160165
@Override
161166
public String toString() {
162167
return new ToStringCreator(this)
@@ -168,9 +173,9 @@ public String toString() {
168173
.append("Comment", getComment())
169174
.append("Secure", getSecure())
170175
.append("HttpOnly", isHttpOnly())
171-
.append("SameSite", this.sameSite)
176+
.append(SAME_SITE, getSameSite())
172177
.append("Max-Age", getMaxAge())
173-
.append("Expires", (this.expires != null ?
178+
.append(EXPIRES, (this.expires != null ?
174179
DateTimeFormatter.RFC_1123_DATE_TIME.format(this.expires) : null))
175180
.toString();
176181
}

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

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,15 @@
1818

1919
import java.time.ZonedDateTime;
2020
import java.time.format.DateTimeFormatter;
21+
import java.time.format.DateTimeParseException;
2122

2223
import org.junit.jupiter.api.Test;
2324
import org.junit.jupiter.params.ParameterizedTest;
2425
import org.junit.jupiter.params.provider.ValueSource;
2526

2627
import static org.assertj.core.api.Assertions.assertThat;
2728
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
29+
import static org.assertj.core.api.Assertions.assertThatThrownBy;
2830

2931
/**
3032
* Unit tests for {@link MockCookie}.
@@ -136,4 +138,67 @@ void parseHeaderWithAttributesCaseSensitivity() {
136138
assertThat(cookie.getSameSite()).isEqualTo("Lax");
137139
}
138140

141+
@Test
142+
void setSameSiteShouldSetAttribute() {
143+
MockCookie cookie = new MockCookie("SESSION", "123");
144+
cookie.setSameSite("Strict");
145+
146+
assertThat(cookie.getAttribute("samesite")).isEqualTo("Strict");
147+
}
148+
149+
@Test
150+
void setExpiresShouldSetAttribute() {
151+
MockCookie cookie = new MockCookie("SESSION", "123");
152+
cookie.setExpires(ZonedDateTime.parse("Tue, 8 Oct 2019 19:50:00 GMT",
153+
DateTimeFormatter.RFC_1123_DATE_TIME));
154+
155+
assertThat(cookie.getAttribute("expires")).isEqualTo("Tue, 8 Oct 2019 19:50:00 GMT");
156+
}
157+
158+
@Test
159+
void setSameSiteNullShouldClear() {
160+
MockCookie cookie = new MockCookie("SESSION", "123");
161+
cookie.setSameSite("Strict");
162+
assertThat(cookie.getSameSite()).isEqualTo("Strict");
163+
164+
cookie.setSameSite(null);
165+
assertThat(cookie.getSameSite()).isNull();
166+
assertThat(cookie.getAttribute("samesite")).isNull();
167+
}
168+
169+
@Test
170+
void setExpiresNullShouldClear() {
171+
MockCookie cookie = new MockCookie("SESSION", "123");
172+
cookie.setExpires(ZonedDateTime.parse("Tue, 8 Oct 2019 19:50:00 GMT",
173+
DateTimeFormatter.RFC_1123_DATE_TIME));
174+
assertThat(cookie.getExpires()).isEqualTo(ZonedDateTime.parse("Tue, 8 Oct 2019 19:50:00 GMT",
175+
DateTimeFormatter.RFC_1123_DATE_TIME));
176+
177+
cookie.setExpires(null);
178+
assertThat(cookie.getExpires()).isNull();
179+
assertThat(cookie.getAttribute("expires")).isNull();
180+
}
181+
182+
@Test
183+
void setAttributeSameSiteShouldSetSameSite() {
184+
MockCookie cookie = new MockCookie("SESSION", "123");
185+
cookie.setAttribute("samesite", "Lax");
186+
187+
assertThat(cookie.getSameSite()).isEqualTo("Lax");
188+
}
189+
190+
@Test
191+
void setAttributeExpiresShouldSetExpires() {
192+
MockCookie cookie = new MockCookie("SESSION", "123");
193+
cookie.setAttribute("expires", "Tue, 8 Oct 2019 19:50:00 GMT");
194+
195+
assertThat(cookie.getExpires()).isEqualTo(ZonedDateTime.parse("Tue, 8 Oct 2019 19:50:00 GMT",
196+
DateTimeFormatter.RFC_1123_DATE_TIME));
197+
}
198+
199+
@Test
200+
void setInvalidAttributeExpiresShouldThrow() {
201+
MockCookie cookie = new MockCookie("SESSION", "123");
202+
assertThatThrownBy(() -> cookie.setAttribute("expires", "12345")).isInstanceOf(DateTimeParseException.class);
203+
}
139204
}

0 commit comments

Comments
 (0)