Skip to content

Commit 8290f5a

Browse files
arturobernalgok2c
authored andcommitted
BasicCookieStore: preserve creation time on cookie replacement
Required by RFC 6265 Section 5.3; affects cookie ordering (Section 5.4)
1 parent a21d2d1 commit 8290f5a

File tree

4 files changed

+49
-2
lines changed

4 files changed

+49
-2
lines changed

httpclient5/src/main/java/org/apache/hc/client5/http/cookie/BasicCookieStore.java

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,18 @@ public void addCookie(final Cookie cookie) {
8282
if (cookie != null) {
8383
lock.writeLock().lock();
8484
try {
85-
// first remove any old cookie that is equivalent
86-
cookies.remove(cookie);
85+
final Cookie oldCookie = cookies.ceiling(cookie);
86+
if (oldCookie != null && CookieIdentityComparator.INSTANCE.compare(oldCookie, cookie) == 0) {
87+
if (cookie instanceof SetCookie) {
88+
final Instant creationInstant = oldCookie.getCreationInstant();
89+
if (creationInstant != null) {
90+
((SetCookie) cookie).setCreationInstant(creationInstant);
91+
}
92+
}
93+
cookies.remove(oldCookie);
94+
} else {
95+
cookies.remove(cookie);
96+
}
8797
if (!cookie.isExpired(Instant.now())) {
8898
cookies.add(cookie);
8999
}

httpclient5/src/main/java/org/apache/hc/client5/http/cookie/SetCookie.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,5 +115,14 @@ default void setExpiryDate(Instant expiryDate) {
115115
default void setHttpOnly(final boolean httpOnly) {
116116
}
117117

118+
/**
119+
* Sets creation time of the cookie.
120+
*
121+
* @since 5.7
122+
*/
123+
default void setCreationInstant(final Instant creationInstant) {
124+
// no-op by default for backward compatibility
125+
}
126+
118127
}
119128

httpclient5/src/main/java/org/apache/hc/client5/http/impl/cookie/BasicClientCookie.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,11 @@ public void setCreationDate(final Instant creationDate) {
330330
this.creationDate = creationDate;
331331
}
332332

333+
@Override
334+
public void setCreationInstant(final Instant creationDate) {
335+
setCreationDate(creationDate);
336+
}
337+
333338
public void setAttribute(final String name, final String value) {
334339
this.attribs.put(name, value);
335340
}

httpclient5/src/test/java/org/apache/hc/client5/http/impl/cookie/TestBasicCookieStore.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,29 @@ void testExpiredCookie() {
7474
Assertions.assertEquals(0, list.size());
7575
}
7676

77+
@Test
78+
void testReplacementPreservesCreationTime() {
79+
final BasicCookieStore store = new BasicCookieStore();
80+
final Instant originalCreation = Instant.now().minus(1, ChronoUnit.DAYS);
81+
82+
final BasicClientCookie original = new BasicClientCookie("name1", "value1");
83+
original.setDomain("example.com");
84+
original.setPath("/");
85+
original.setCreationDate(originalCreation);
86+
store.addCookie(original);
87+
88+
final BasicClientCookie replacement = new BasicClientCookie("name1", "value2");
89+
replacement.setDomain("example.com");
90+
replacement.setPath("/");
91+
replacement.setCreationDate(Instant.now());
92+
store.addCookie(replacement);
93+
94+
final List<Cookie> list = store.getCookies();
95+
Assertions.assertEquals(1, list.size());
96+
Assertions.assertEquals("value2", list.get(0).getValue());
97+
Assertions.assertEquals(originalCreation, list.get(0).getCreationInstant());
98+
}
99+
77100
@Test
78101
void testSerialization() throws Exception {
79102
final BasicCookieStore orig = new BasicCookieStore();

0 commit comments

Comments
 (0)