Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ public class NewCookieHeaderProvider implements HeaderDelegate<NewCookie> {
private static final String SECURE = "Secure";
private static final String EXPIRES = "Expires";
private static final String HTTP_ONLY = "HttpOnly";
private static final String SAME_SITE = "SameSite";

/** from RFC 2068, token special case characters */

Expand All @@ -59,10 +60,14 @@ public NewCookie fromString(String c) {
Date expires = null;
boolean httpOnly = false;
int version = Cookie.DEFAULT_VERSION;
NewCookie.SameSite sameSite = null;

String[] tokens = c.split(";");
for (String token : tokens) {
String theToken = token.trim();
if (theToken.isEmpty()) {
continue;
}

int sepIndex = theToken.indexOf('=');
String paramName = sepIndex != -1 ? theToken.substring(0, sepIndex) : theToken;
Expand Down Expand Up @@ -94,7 +99,10 @@ public NewCookie fromString(String c) {
httpOnly = true;
} else if (paramName.equalsIgnoreCase(VERSION)) {
version = Integer.parseInt(paramValue);
} else if (paramValue != null) {
} else if (paramName.equalsIgnoreCase(SAME_SITE)) {
sameSite = toSameSite(paramValue);
} else if (paramValue != null && name == null) {
// The cookie's own name=value pair comes first; unrecognized attributes after it are ignored
name = paramName;
value = paramValue;
}
Expand All @@ -104,7 +112,8 @@ public NewCookie fromString(String c) {
throw new IllegalArgumentException("Set-Cookie is malformed : " + c);
}

return new NewCookie(name, value, path, domain, version, comment, maxAge, expires, isSecure, httpOnly);
return new NewCookie(name, value, path, domain, version, comment, maxAge, expires, isSecure, httpOnly,
sameSite);
}

@Override
Expand Down Expand Up @@ -137,11 +146,38 @@ public String toString(NewCookie value) {
if (value.isHttpOnly()) {
sb.append(';').append(HTTP_ONLY);
}
if (value.getSameSite() != null) {
sb.append(';').append(SAME_SITE).append('=').append(toAttributeValue(value.getSameSite()));
}
sb.append(';').append(VERSION).append('=').append(value.getVersion());
return sb.toString();

}

/**
* Matches the SameSite attribute value case-insensitively; an unrecognized value is ignored,
* as the RFC 6265bis draft specifies.
*/
private static NewCookie.SameSite toSameSite(String attributeValue) {
for (NewCookie.SameSite sameSite : NewCookie.SameSite.values()) {
if (sameSite.name().equalsIgnoreCase(attributeValue)) {
return sameSite;
}
}
return null;
}

private static String toAttributeValue(NewCookie.SameSite sameSite) {
Comment thread
reta marked this conversation as resolved.
Outdated
switch (sameSite) {
case STRICT:
return "Strict";
case LAX:
return "Lax";
default:
return "None";
}
}

/**
* Append the input value string to the given buffer, wrapping it with
* quotes if need be.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;

public class NewCookieHeaderProviderTest {
Expand Down Expand Up @@ -151,4 +152,64 @@ public void testToStringWithPathSlalshOnly() {
+ "Path=/path;Secure;Version=1", c.toString());
}

@Test
public void testFromStringWithSameSite() {
NewCookie c = NewCookie.valueOf("foo=bar;SameSite=Lax;Path=/");
assertEquals("foo", c.getName());
assertEquals("bar", c.getValue());
assertEquals("/", c.getPath());
assertEquals(NewCookie.SameSite.LAX, c.getSameSite());
}

@Test
public void testFromStringWithSameSiteIsCaseInsensitive() {
NewCookie c = NewCookie.valueOf("foo=bar; samesite=none; Secure");
assertEquals("foo", c.getName());
assertEquals("bar", c.getValue());
assertTrue(c.isSecure());
assertEquals(NewCookie.SameSite.NONE, c.getSameSite());
}

@Test
public void testFromStringWithUnrecognizedSameSiteValue() {
NewCookie c = NewCookie.valueOf("foo=bar;SameSite=Unknown");
assertEquals("foo", c.getName());
assertEquals("bar", c.getValue());
assertNull(c.getSameSite());
}

@Test
public void testFromStringIgnoresUnknownAttributes() {
NewCookie c = NewCookie.valueOf("foo=bar;Priority=High;Path=path");
assertEquals("foo", c.getName());
assertEquals("bar", c.getValue());
assertEquals("path", c.getPath());
}

@Test
public void testFromStringSkipsEmptySegments() {
NewCookie c = NewCookie.valueOf(" ; foo=bar;;Path=path");
assertEquals("foo", c.getName());
assertEquals("bar", c.getValue());
assertEquals("path", c.getPath());
}

@Test
public void testToStringWithSameSite() {
NewCookie c = new NewCookie.Builder("foo").value("bar").path("path")
.sameSite(NewCookie.SameSite.STRICT).build();
assertEquals("foo=bar;Path=path;SameSite=Strict;Version=1", c.toString());
}

@Test
public void testSameSiteRoundTrip() {
NewCookie c = NewCookie.valueOf(
new NewCookie.Builder("foo").value("bar").sameSite(NewCookie.SameSite.NONE).secure(true).build()
.toString());
assertEquals("foo", c.getName());
assertEquals("bar", c.getValue());
assertTrue(c.isSecure());
assertEquals(NewCookie.SameSite.NONE, c.getSameSite());
}

}
Loading