Merge remote-tracking branch 'origin/jetty-11.0.x' into jetty-12.0.x
This commit is contained in:
commit
b720d65f4f
|
@ -128,13 +128,12 @@ public class CookieCompliance implements ComplianceViolation.Mode
|
|||
* <p>A CookieCompliance mode that enforces <a href="https://tools.ietf.org/html/rfc6265">RFC 6265</a> compliance,
|
||||
* but allows:</p>
|
||||
* <ul>
|
||||
* <li>{@link Violation#ATTRIBUTES}</li>
|
||||
* <li>{@link Violation#INVALID_COOKIES}</li>
|
||||
* <li>{@link Violation#OPTIONAL_WHITE_SPACE}</li>
|
||||
* </ul>
|
||||
*/
|
||||
public static final CookieCompliance RFC6265 = new CookieCompliance("RFC6265", of(
|
||||
Violation.ATTRIBUTES, Violation.INVALID_COOKIES, Violation.OPTIONAL_WHITE_SPACE)
|
||||
Violation.INVALID_COOKIES, Violation.OPTIONAL_WHITE_SPACE)
|
||||
);
|
||||
|
||||
/**
|
||||
|
@ -146,6 +145,7 @@ public class CookieCompliance implements ComplianceViolation.Mode
|
|||
* <p>A CookieCompliance mode that enforces <a href="https://tools.ietf.org/html/rfc6265">RFC 6265</a> compliance,
|
||||
* but allows:</p>
|
||||
* <ul>
|
||||
* <li>{@link Violation#ATTRIBUTES}</li>
|
||||
* <li>{@link Violation#BAD_QUOTES}</li>
|
||||
* <li>{@link Violation#ESCAPE_IN_QUOTES}</li>
|
||||
* <li>{@link Violation#INVALID_COOKIES}</li>
|
||||
|
@ -153,8 +153,8 @@ public class CookieCompliance implements ComplianceViolation.Mode
|
|||
* <li>{@link Violation#SPECIAL_CHARS_IN_QUOTES}</li>
|
||||
* </ul>
|
||||
*/
|
||||
public static final CookieCompliance RFC6265_LEGACY = new CookieCompliance("RFC6265_LEGACY", of(
|
||||
Violation.BAD_QUOTES, Violation.ESCAPE_IN_QUOTES, Violation.INVALID_COOKIES, Violation.OPTIONAL_WHITE_SPACE, Violation.SPECIAL_CHARS_IN_QUOTES)
|
||||
public static final CookieCompliance RFC6265_LEGACY = new CookieCompliance("RFC6265_LEGACY", EnumSet.of(
|
||||
Violation.ATTRIBUTES, Violation.BAD_QUOTES, Violation.ESCAPE_IN_QUOTES, Violation.INVALID_COOKIES, Violation.OPTIONAL_WHITE_SPACE, Violation.SPECIAL_CHARS_IN_QUOTES)
|
||||
);
|
||||
|
||||
/**
|
||||
|
@ -214,40 +214,45 @@ public class CookieCompliance implements ComplianceViolation.Mode
|
|||
*/
|
||||
public static CookieCompliance from(String spec)
|
||||
{
|
||||
Set<Violation> violations;
|
||||
String[] elements = spec.split("\\s*,\\s*");
|
||||
switch (elements[0])
|
||||
CookieCompliance compliance = valueOf(spec);
|
||||
if (compliance == null)
|
||||
{
|
||||
case "0":
|
||||
violations = noneOf(Violation.class);
|
||||
break;
|
||||
|
||||
case "*":
|
||||
violations = allOf(Violation.class);
|
||||
break;
|
||||
|
||||
default:
|
||||
String[] elements = spec.split("\\s*,\\s*");
|
||||
Set<Violation> violations;
|
||||
switch (elements[0])
|
||||
{
|
||||
CookieCompliance mode = valueOf(elements[0]);
|
||||
violations = (mode == null) ? noneOf(Violation.class) : copyOf(mode.getAllowed());
|
||||
break;
|
||||
case "0" :
|
||||
violations = noneOf(Violation.class);
|
||||
break;
|
||||
|
||||
case "*" :
|
||||
violations = allOf(Violation.class);
|
||||
break;
|
||||
|
||||
default :
|
||||
{
|
||||
CookieCompliance mode = valueOf(elements[0]);
|
||||
if (mode == null)
|
||||
throw new IllegalArgumentException("Unknown base mode: " + elements[0]);
|
||||
violations = (mode.getAllowed().isEmpty()) ? noneOf(Violation.class) : copyOf(mode.getAllowed());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 1; i < elements.length; i++)
|
||||
{
|
||||
String element = elements[i];
|
||||
boolean exclude = element.startsWith("-");
|
||||
if (exclude)
|
||||
element = element.substring(1);
|
||||
Violation section = Violation.valueOf(element);
|
||||
if (exclude)
|
||||
violations.remove(section);
|
||||
else
|
||||
violations.add(section);
|
||||
}
|
||||
for (int i = 1; i < elements.length; i++)
|
||||
{
|
||||
String element = elements[i];
|
||||
boolean exclude = element.startsWith("-");
|
||||
if (exclude)
|
||||
element = element.substring(1);
|
||||
Violation section = Violation.valueOf(element);
|
||||
if (exclude)
|
||||
violations.remove(section);
|
||||
else
|
||||
violations.add(section);
|
||||
}
|
||||
|
||||
CookieCompliance compliance = new CookieCompliance("CUSTOM" + __custom.getAndIncrement(), violations);
|
||||
compliance = new CookieCompliance("CUSTOM" + __custom.getAndIncrement(), violations);
|
||||
}
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("CookieCompliance from {}->{}", spec, compliance);
|
||||
return compliance;
|
||||
|
@ -290,4 +295,10 @@ public class CookieCompliance implements ComplianceViolation.Mode
|
|||
{
|
||||
return this == mode || getAllowed().containsAll(mode.getAllowed());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return String.format("%s@%x%s", _name, hashCode(), _violations);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,9 +41,9 @@ public interface CookieParser
|
|||
return new RFC6265CookieParser(handler, compliance, complianceListener);
|
||||
}
|
||||
|
||||
void parseField(String field);
|
||||
void parseField(String field) throws InvalidCookieException;
|
||||
|
||||
default void parseFields(List<String> rawFields)
|
||||
default void parseFields(List<String> rawFields) throws InvalidCookieException
|
||||
{
|
||||
// For each cookie field
|
||||
for (String field : rawFields)
|
||||
|
@ -57,4 +57,30 @@ public interface CookieParser
|
|||
{
|
||||
void addCookie(String name, String value, int version, String domain, String path, String comment);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>The exception thrown when a cookie cannot be parsed and {@link CookieCompliance.Violation#INVALID_COOKIES} is not allowed.</p>
|
||||
*/
|
||||
class InvalidCookieException extends IllegalArgumentException
|
||||
{
|
||||
public InvalidCookieException()
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
public InvalidCookieException(String s)
|
||||
{
|
||||
super(s);
|
||||
}
|
||||
|
||||
public InvalidCookieException(String message, Throwable cause)
|
||||
{
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public InvalidCookieException(Throwable cause)
|
||||
{
|
||||
super(cause);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -85,7 +85,7 @@ public class RFC6265CookieParser implements CookieParser
|
|||
if (token == null)
|
||||
{
|
||||
if (!_complianceMode.allows(INVALID_COOKIES))
|
||||
throw new IllegalArgumentException("Invalid Cookie character");
|
||||
throw new InvalidCookieException("Invalid Cookie character");
|
||||
state = State.INVALID_COOKIE;
|
||||
continue;
|
||||
}
|
||||
|
@ -100,7 +100,7 @@ public class RFC6265CookieParser implements CookieParser
|
|||
|
||||
if (token.isRfc2616Token())
|
||||
{
|
||||
if (!StringUtil.isBlank(cookieName) && c != '$')
|
||||
if (!StringUtil.isBlank(cookieName) && !(c == '$' && (_complianceMode.allows(ATTRIBUTES) || _complianceMode.allows(ATTRIBUTE_VALUES))))
|
||||
{
|
||||
_handler.addCookie(cookieName, cookieValue, cookieVersion, cookieDomain, cookiePath, cookieComment);
|
||||
cookieName = null;
|
||||
|
@ -120,7 +120,7 @@ public class RFC6265CookieParser implements CookieParser
|
|||
}
|
||||
else
|
||||
{
|
||||
throw new IllegalArgumentException("Bad Cookie name");
|
||||
throw new InvalidCookieException("Bad Cookie name");
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -158,7 +158,7 @@ public class RFC6265CookieParser implements CookieParser
|
|||
}
|
||||
else
|
||||
{
|
||||
throw new IllegalArgumentException("Bad Cookie name");
|
||||
throw new InvalidCookieException("Bad Cookie name");
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -181,7 +181,7 @@ public class RFC6265CookieParser implements CookieParser
|
|||
}
|
||||
else
|
||||
{
|
||||
throw new IllegalArgumentException("Bad Cookie");
|
||||
throw new InvalidCookieException("Bad Cookie");
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -215,7 +215,7 @@ public class RFC6265CookieParser implements CookieParser
|
|||
}
|
||||
else
|
||||
{
|
||||
throw new IllegalArgumentException("Bad Cookie value");
|
||||
throw new InvalidCookieException("Bad Cookie value");
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -237,7 +237,7 @@ public class RFC6265CookieParser implements CookieParser
|
|||
}
|
||||
else
|
||||
{
|
||||
throw new IllegalArgumentException("Bad Cookie value");
|
||||
throw new InvalidCookieException("Bad Cookie value");
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -277,7 +277,7 @@ public class RFC6265CookieParser implements CookieParser
|
|||
}
|
||||
else
|
||||
{
|
||||
throw new IllegalArgumentException("Bad Cookie quoted value");
|
||||
throw new InvalidCookieException("Bad Cookie quoted value");
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -299,7 +299,7 @@ public class RFC6265CookieParser implements CookieParser
|
|||
}
|
||||
else
|
||||
{
|
||||
throw new IllegalArgumentException("Bad Cookie quoted value");
|
||||
throw new InvalidCookieException("Bad Cookie quoted value");
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -323,7 +323,7 @@ public class RFC6265CookieParser implements CookieParser
|
|||
}
|
||||
else
|
||||
{
|
||||
throw new IllegalStateException("Comma cookie separator");
|
||||
throw new InvalidCookieException("Comma cookie separator");
|
||||
}
|
||||
}
|
||||
else if ((c == ' ' || c == '\t') && _complianceMode.allows(OPTIONAL_WHITE_SPACE))
|
||||
|
@ -332,7 +332,6 @@ public class RFC6265CookieParser implements CookieParser
|
|||
continue;
|
||||
}
|
||||
|
||||
boolean knownAttribute = true;
|
||||
if (StringUtil.isBlank(attributeName))
|
||||
{
|
||||
cookieValue = value;
|
||||
|
@ -358,7 +357,10 @@ public class RFC6265CookieParser implements CookieParser
|
|||
cookieVersion = Integer.parseInt(value);
|
||||
break;
|
||||
default:
|
||||
knownAttribute = false;
|
||||
if (!_complianceMode.allows(INVALID_COOKIES))
|
||||
throw new IllegalArgumentException("Invalid Cookie attribute");
|
||||
reportComplianceViolation(INVALID_COOKIES, field);
|
||||
state = State.INVALID_COOKIE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -366,31 +368,17 @@ public class RFC6265CookieParser implements CookieParser
|
|||
{
|
||||
reportComplianceViolation(ATTRIBUTES, field);
|
||||
}
|
||||
else if (_complianceMode.allows(INVALID_COOKIES))
|
||||
{
|
||||
reportComplianceViolation(INVALID_COOKIES, field);
|
||||
state = State.INVALID_COOKIE;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new IllegalArgumentException("Invalid Cookie with attributes");
|
||||
cookieName = attributeName;
|
||||
cookieValue = value;
|
||||
}
|
||||
attributeName = null;
|
||||
}
|
||||
value = null;
|
||||
|
||||
if (!knownAttribute)
|
||||
{
|
||||
if (!_complianceMode.allows(INVALID_COOKIES))
|
||||
throw new IllegalArgumentException("Invalid Cookie attribute");
|
||||
reportComplianceViolation(INVALID_COOKIES, field);
|
||||
state = State.INVALID_COOKIE;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (state == State.END)
|
||||
throw new IllegalStateException("Invalid cookie");
|
||||
throw new InvalidCookieException("Invalid cookie");
|
||||
break;
|
||||
|
||||
case INVALID_COOKIE:
|
||||
|
|
|
@ -85,58 +85,12 @@ public class RFC6265CookieParserLenientTest
|
|||
Arguments.of("!f!o!o!=wat", "!f!o!o!", "wat"),
|
||||
Arguments.of("__MyHost=Foo", "__MyHost", "Foo"),
|
||||
Arguments.of("some-thing-else=to-parse", "some-thing-else", "to-parse"),
|
||||
// RFC2109 - names with attr/token syntax starting with '$' (and not a cookie reserved word)
|
||||
// See https://tools.ietf.org/html/draft-ietf-httpbis-cookie-prefixes-00#section-5.2
|
||||
// Cannot pass names through as jakarta.servlet.http.Cookie class does not allow them
|
||||
Arguments.of("$foo=bar", null, null),
|
||||
Arguments.of("$foo=bar", "$foo", "bar"),
|
||||
|
||||
// Tests that conform to RFC6265
|
||||
Arguments.of("abc=foobar!", "abc", "foobar!"),
|
||||
Arguments.of("abc=\"foobar!\"", "abc", "foobar!")
|
||||
|
||||
/* TODO need to discuss if we should support these cases
|
||||
,
|
||||
// UTF-8 raw values (not encoded) - VIOLATION of RFC6265
|
||||
Arguments.of("2sides=\u262F", null, null), // 2 byte (YIN YANG) - rejected due to not being DQUOTED
|
||||
Arguments.of("currency=\"\u20AC\"", "currency", "\u20AC"), // 3 byte (EURO SIGN)
|
||||
Arguments.of("gothic=\"\uD800\uDF48\"", "gothic", "\uD800\uDF48"), // 4 byte (GOTHIC LETTER HWAIR)
|
||||
|
||||
// Spaces
|
||||
Arguments.of("foo=bar baz", "foo", "bar baz"),
|
||||
Arguments.of("foo=\"bar baz\"", "foo", "bar baz"),
|
||||
Arguments.of("z=a b c d e f g", "z", "a b c d e f g"),
|
||||
|
||||
// Bad tspecials usage - VIOLATION of RFC6265
|
||||
Arguments.of("foo=bar;baz", "foo", "bar"),
|
||||
Arguments.of("foo=\"bar;baz\"", "foo", "bar;baz"),
|
||||
Arguments.of("z=a;b,c:d;e/f[g]", "z", "a"),
|
||||
Arguments.of("z=\"a;b,c:d;e/f[g]\"", "z", "a;b,c:d;e/f[g]"),
|
||||
Arguments.of("name=quoted=\"\\\"badly\\\"\"", "name", "quoted=\"\\\"badly\\\"\""), // someone attempting to escape a DQUOTE from within a DQUOTED pair)
|
||||
|
||||
// Quoted with other Cookie keywords
|
||||
Arguments.of("x=\"$Version=0\"", "x", "$Version=0"),
|
||||
Arguments.of("x=\"$Path=/\"", "x", "$Path=/"),
|
||||
Arguments.of("x=\"$Path=/ $Domain=.foo.com\"", "x", "$Path=/ $Domain=.foo.com"),
|
||||
Arguments.of("x=\" $Path=/ $Domain=.foo.com \"", "x", " $Path=/ $Domain=.foo.com "),
|
||||
Arguments.of("a=\"b; $Path=/a; c=d; $PATH=/c; e=f\"; $Path=/e/", "a", "b; $Path=/a; c=d; $PATH=/c; e=f"), // VIOLATES RFC6265
|
||||
|
||||
// Lots of equals signs
|
||||
Arguments.of("query=b=c&d=e", "query", "b=c&d=e"),
|
||||
|
||||
// Escaping
|
||||
Arguments.of("query=%7B%22sessionCount%22%3A5%2C%22sessionTime%22%3A14151%7D", "query", "%7B%22sessionCount%22%3A5%2C%22sessionTime%22%3A14151%7D"),
|
||||
|
||||
// Google cookies (seen in wild, has `tspecials` of ':' in value)
|
||||
Arguments.of("GAPS=1:A1aaaAaAA1aaAAAaa1a11a:aAaaAa-aaA1-", "GAPS", "1:A1aaaAaAA1aaAAAaa1a11a:aAaaAa-aaA1-"),
|
||||
|
||||
// Strong abuse of cookie spec (lots of tspecials) - VIOLATION of RFC6265
|
||||
Arguments.of("$Version=0; rToken=F_TOKEN''!--\"</a>=&{()}", "rToken", "F_TOKEN''!--\"</a>=&{()}"),
|
||||
|
||||
// Commas that were not commas
|
||||
Arguments.of("name=foo,bar", "name", "foo,bar"),
|
||||
Arguments.of("name=foo , bar", "name", "foo , bar"),
|
||||
Arguments.of("name=foo , bar, bob", "name", "foo , bar, bob")
|
||||
*/
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -23,7 +23,6 @@ import org.junit.jupiter.params.provider.MethodSource;
|
|||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
public class RFC6265CookieParserTest
|
||||
{
|
||||
|
@ -36,7 +35,7 @@ public class RFC6265CookieParserTest
|
|||
String rawCookie = "$Version=\"1\"; Customer=\"WILE_E_COYOTE\"; $Path=\"/acme\"";
|
||||
|
||||
// Test with RFC 2965.
|
||||
TestCookieParser parser = new TestCookieParser(CookieCompliance.RFC2965_LEGACY);
|
||||
TestCookieParser parser = new TestCookieParser(CookieCompliance.RFC2965);
|
||||
List<Cookie> cookies = parser.parseFields(rawCookie);
|
||||
|
||||
assertThat("Cookies.length", cookies.size(), is(1));
|
||||
|
@ -44,18 +43,45 @@ public class RFC6265CookieParserTest
|
|||
// There are 2 attributes, so 2 violations.
|
||||
assertThat(parser.violations.size(), is(2));
|
||||
|
||||
// Same test with RFC 6265.
|
||||
// Same test with RFC6265.
|
||||
parser = new TestCookieParser(CookieCompliance.RFC6265);
|
||||
cookies = parser.parseFields(rawCookie);
|
||||
assertThat("Cookies.length", cookies.size(), is(3));
|
||||
assertCookie("Cookies[0]", cookies.get(0), "$Version", "1", 0, null);
|
||||
assertCookie("Cookies[1]", cookies.get(1), "Customer", "WILE_E_COYOTE", 0, null);
|
||||
assertCookie("Cookies[2]", cookies.get(2), "$Path", "/acme", 0, null);
|
||||
|
||||
// There attributes are seen as just normal cookies, so no violations
|
||||
assertThat(parser.violations.size(), is(0));
|
||||
|
||||
// Same again, but allow attributes which are ignored
|
||||
parser = new TestCookieParser(CookieCompliance.from("RFC6265,ATTRIBUTES"));
|
||||
cookies = parser.parseFields(rawCookie);
|
||||
assertThat("Cookies.length", cookies.size(), is(1));
|
||||
assertCookie("Cookies[0]", cookies.get(0), "Customer", "WILE_E_COYOTE", 0, null);
|
||||
// There are 2 attributes, so 2 violations.
|
||||
|
||||
// There attributes are seen as just normal cookies, so no violations
|
||||
assertThat(parser.violations.size(), is(2));
|
||||
|
||||
// Same again, but allow attributes which are not ignored
|
||||
parser = new TestCookieParser(CookieCompliance.from("RFC6265,ATTRIBUTE_VALUES"));
|
||||
cookies = parser.parseFields(rawCookie);
|
||||
assertThat("Cookies.length", cookies.size(), is(1));
|
||||
assertCookie("Cookies[0]", cookies.get(0), "Customer", "WILE_E_COYOTE", 1, "/acme");
|
||||
|
||||
// There attributes are seen as just normal cookies, so no violations
|
||||
assertThat(parser.violations.size(), is(2));
|
||||
|
||||
// Same test with RFC 6265 strict should throw.
|
||||
TestCookieParser strictParser = new TestCookieParser(CookieCompliance.RFC6265_STRICT);
|
||||
assertThrows(IllegalArgumentException.class, () -> strictParser.parseFields(rawCookie));
|
||||
parser = new TestCookieParser(CookieCompliance.RFC6265_STRICT);
|
||||
cookies = parser.parseFields(rawCookie);
|
||||
assertThat("Cookies.length", cookies.size(), is(3));
|
||||
assertCookie("Cookies[0]", cookies.get(0), "$Version", "1", 0, null);
|
||||
assertCookie("Cookies[1]", cookies.get(1), "Customer", "WILE_E_COYOTE", 0, null);
|
||||
assertCookie("Cookies[2]", cookies.get(2), "$Path", "/acme", 0, null);
|
||||
|
||||
// There attributes are seen as just normal cookies, so no violations
|
||||
assertThat(parser.violations.size(), is(0));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -68,12 +94,30 @@ public class RFC6265CookieParserTest
|
|||
"Customer=\"WILE_E_COYOTE\"; $Path=\"/acme\"; " +
|
||||
"Part_Number=\"Rocket_Launcher_0001\"; $Path=\"/acme\"";
|
||||
|
||||
Cookie[] cookies = parseCookieHeaders(CookieCompliance.RFC2965_LEGACY, rawCookie);
|
||||
Cookie[] cookies = parseCookieHeaders(CookieCompliance.RFC2965, rawCookie);
|
||||
|
||||
assertThat("Cookies.length", cookies.length, is(2));
|
||||
assertCookie("Cookies[0]", cookies[0], "Customer", "WILE_E_COYOTE", 1, "/acme");
|
||||
assertCookie("Cookies[1]", cookies[1], "Part_Number", "Rocket_Launcher_0001", 1, "/acme");
|
||||
|
||||
cookies = parseCookieHeaders(CookieCompliance.RFC6265, rawCookie);
|
||||
assertThat("Cookies.length", cookies.length, is(5));
|
||||
assertCookie("Cookies[0]", cookies[0], "$Version", "1", 0, null);
|
||||
assertCookie("Cookies[1]", cookies[1], "Customer", "WILE_E_COYOTE", 0, null);
|
||||
assertCookie("Cookies[2]", cookies[2], "$Path", "/acme", 0, null);
|
||||
assertCookie("Cookies[3]", cookies[3], "Part_Number", "Rocket_Launcher_0001", 0, null);
|
||||
assertCookie("Cookies[4]", cookies[4], "$Path", "/acme", 0, null);
|
||||
|
||||
cookies = parseCookieHeaders(CookieCompliance.from("RFC6265,ATTRIBUTES"), rawCookie);
|
||||
assertThat("Cookies.length", cookies.length, is(2));
|
||||
assertCookie("Cookies[0]", cookies[0], "Customer", "WILE_E_COYOTE", 0, null);
|
||||
assertCookie("Cookies[1]", cookies[1], "Part_Number", "Rocket_Launcher_0001", 0, null);
|
||||
|
||||
cookies = parseCookieHeaders(CookieCompliance.from("RFC6265,ATTRIBUTE_VALUES"), rawCookie);
|
||||
assertThat("Cookies.length", cookies.length, is(2));
|
||||
assertCookie("Cookies[0]", cookies[0], "Customer", "WILE_E_COYOTE", 1, "/acme");
|
||||
assertCookie("Cookies[1]", cookies[1], "Part_Number", "Rocket_Launcher_0001", 1, "/acme");
|
||||
|
||||
/* TODO Is this a better interpretation of dollar attributes
|
||||
cookies = parseCookieHeaders(CookieCompliance.RFC6265, rawCookie);
|
||||
assertThat("Cookies.length", cookies.length, is(4));
|
||||
|
@ -95,7 +139,7 @@ public class RFC6265CookieParserTest
|
|||
"Part_Number=\"Rocket_Launcher_0001\"; $Path=\"/acme\"; " +
|
||||
"Shipping=\"FedEx\"; $Path=\"/acme\"";
|
||||
|
||||
Cookie[] cookies = parseCookieHeaders(CookieCompliance.RFC2965_LEGACY, rawCookie);
|
||||
Cookie[] cookies = parseCookieHeaders(CookieCompliance.RFC2965, rawCookie);
|
||||
|
||||
assertThat("Cookies.length", cookies.length, is(3));
|
||||
assertCookie("Cookies[0]", cookies[0], "Customer", "WILE_E_COYOTE", 1, "/acme");
|
||||
|
@ -113,7 +157,7 @@ public class RFC6265CookieParserTest
|
|||
"Part_Number=\"Riding_Rocket_0023\"; $Path=\"/acme/ammo\"; " +
|
||||
"Part_Number=\"Rocket_Launcher_0001\"; $Path=\"/acme\"";
|
||||
|
||||
Cookie[] cookies = parseCookieHeaders(CookieCompliance.RFC2965_LEGACY, rawCookie);
|
||||
Cookie[] cookies = parseCookieHeaders(CookieCompliance.RFC2965, rawCookie);
|
||||
|
||||
assertThat("Cookies.length", cookies.length, is(2));
|
||||
assertCookie("Cookies[0]", cookies[0], "Part_Number", "Riding_Rocket_0023", 1, "/acme/ammo");
|
||||
|
@ -130,7 +174,7 @@ public class RFC6265CookieParserTest
|
|||
"session_id=\"1234\"; " +
|
||||
"session_id=\"1111\"; $Domain=\".cracker.edu\"";
|
||||
|
||||
Cookie[] cookies = parseCookieHeaders(CookieCompliance.RFC2965_LEGACY, rawCookie);
|
||||
Cookie[] cookies = parseCookieHeaders(CookieCompliance.RFC2965, rawCookie);
|
||||
|
||||
assertThat("Cookies.length", cookies.length, is(2));
|
||||
assertCookie("Cookies[0]", cookies[0], "session_id", "1234", 1, null);
|
||||
|
@ -146,15 +190,25 @@ public class RFC6265CookieParserTest
|
|||
String rawCookie = "$Version=\"1\"; session_id=\"1234\", " +
|
||||
"$Version=\"1\"; session_id=\"1111\"; $Domain=\".cracker.edu\"";
|
||||
|
||||
Cookie[] cookies = parseCookieHeaders(CookieCompliance.RFC2965_LEGACY, rawCookie);
|
||||
Cookie[] cookies = parseCookieHeaders(CookieCompliance.RFC2965, rawCookie);
|
||||
|
||||
assertThat("Cookies.length", cookies.length, is(2));
|
||||
assertCookie("Cookies[0]", cookies[0], "session_id", "1234", 1, null);
|
||||
assertCookie("Cookies[1]", cookies[1], "session_id", "1111", 1, null);
|
||||
|
||||
cookies = parseCookieHeaders(CookieCompliance.RFC6265, rawCookie);
|
||||
assertThat("Cookies.length", cookies.length, is(1));
|
||||
assertCookie("Cookies[1]", cookies[0], "session_id", "1111", 0, null);
|
||||
assertThat("Cookies.length", cookies.length, is(3));
|
||||
assertCookie("Cookies[0]", cookies[0], "$Version", "1", 0, null);
|
||||
assertCookie("Cookies[1]", cookies[1], "session_id", "1111", 0, null);
|
||||
assertCookie("Cookies[2]", cookies[2], "$Domain", ".cracker.edu", 0, null);
|
||||
|
||||
cookies = parseCookieHeaders(CookieCompliance.from("RFC6265,COMMA_SEPARATOR"), rawCookie);
|
||||
assertThat("Cookies.length", cookies.length, is(5));
|
||||
assertCookie("Cookies[0]", cookies[0], "$Version", "1", 0, null);
|
||||
assertCookie("Cookies[1]", cookies[1], "session_id", "1234", 0, null);
|
||||
assertCookie("Cookies[3]", cookies[2], "$Version", "1", 0, null);
|
||||
assertCookie("Cookies[3]", cookies[3], "session_id", "1111", 0, null);
|
||||
assertCookie("Cookies[4]", cookies[4], "$Domain", ".cracker.edu", 0, null);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -210,7 +264,8 @@ public class RFC6265CookieParserTest
|
|||
|
||||
Cookie[] cookies = parseCookieHeaders(CookieCompliance.RFC6265, rawCookie);
|
||||
|
||||
assertThat("Cookies.length", cookies.length, is(0));
|
||||
assertThat("Cookies.length", cookies.length, is(1));
|
||||
assertCookie("Cookies[0]", cookies[0], "$key", "value", 0, null);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -245,7 +300,7 @@ public class RFC6265CookieParserTest
|
|||
public void testRFC2965QuotedEscape()
|
||||
{
|
||||
String rawCookie = "A=\"double\\\"quote\"";
|
||||
Cookie[] cookies = parseCookieHeaders(CookieCompliance.RFC2965_LEGACY, rawCookie);
|
||||
Cookie[] cookies = parseCookieHeaders(CookieCompliance.RFC2965, rawCookie);
|
||||
|
||||
assertThat("Cookies.length", cookies.length, is(1));
|
||||
assertCookie("Cookies[0]", cookies[0], "A", "double\"quote", 0, null);
|
||||
|
@ -255,16 +310,12 @@ public class RFC6265CookieParserTest
|
|||
public void testRFC2965QuotedSpecial()
|
||||
{
|
||||
String rawCookie = "A=\", ;\"";
|
||||
Cookie[] cookies = parseCookieHeaders(CookieCompliance.RFC2965_LEGACY, rawCookie);
|
||||
Cookie[] cookies = parseCookieHeaders(CookieCompliance.RFC2965, rawCookie);
|
||||
|
||||
assertThat("Cookies.length", cookies.length, is(1));
|
||||
assertCookie("Cookies[0]", cookies[0], "A", ", ;", 0, null);
|
||||
}
|
||||
|
||||
// TODO:
|
||||
// $X; N=V
|
||||
// $X=Y; N=V
|
||||
|
||||
public static List<Param> parameters()
|
||||
{
|
||||
return Arrays.asList(
|
||||
|
@ -290,8 +341,8 @@ public class RFC6265CookieParserTest
|
|||
new Param("A=\"1\u0007\"; B=2; C=3", "B=2", "C=3"),
|
||||
new Param("€"),
|
||||
new Param("@={}"),
|
||||
new Param("$X=Y; N=V", "N=V"),
|
||||
new Param("N=V; $X=Y", "N=V")
|
||||
new Param("$X=Y; N=V", "$X=Y", "N=V"),
|
||||
new Param("N=V; $X=Y", "N=V", "$X=Y")
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -73,8 +73,9 @@
|
|||
<Set name="persistentConnectionsEnabled" property="jetty.httpConfig.persistentConnectionsEnabled"/>
|
||||
<Set name="httpCompliance"><Call class="org.eclipse.jetty.http.HttpCompliance" name="from"><Arg><Property name="jetty.httpConfig.compliance" deprecated="jetty.http.compliance" default="RFC7230"/></Arg></Call></Set>
|
||||
<Set name="uriCompliance"><Call class="org.eclipse.jetty.http.UriCompliance" name="from"><Arg><Property name="jetty.httpConfig.uriCompliance" default="SAFE"/></Arg></Call></Set>
|
||||
<Set name="requestCookieCompliance"><Call class="org.eclipse.jetty.http.CookieCompliance" name="valueOf"><Arg><Property name="jetty.httpConfig.requestCookieCompliance" default="RFC6265"/></Arg></Call></Set>
|
||||
<Set name="responseCookieCompliance"><Call class="org.eclipse.jetty.http.CookieCompliance" name="valueOf"><Arg><Property name="jetty.httpConfig.responseCookieCompliance" default="RFC6265"/></Arg></Call></Set>
|
||||
<Set name="requestCookieCompliance"><Call class="org.eclipse.jetty.http.CookieCompliance" name="from"><Arg><Property name="jetty.httpConfig.requestCookieCompliance" default="RFC6265"/></Arg></Call></Set>
|
||||
<Set name="responseCookieCompliance"><Call class="org.eclipse.jetty.http.CookieCompliance" name="from"><Arg><Property name="jetty.httpConfig.responseCookieCompliance" default="RFC6265"/></Arg></Call></Set>
|
||||
<Set name="multiPartFormDataCompliance"><Call class="org.eclipse.jetty.server.MultiPartFormDataCompliance" name="valueOf"><Arg><Property name="jetty.httpConfig.multiPartFormDataCompliance" default="RFC7578"/></Arg></Call></Set>
|
||||
<Set name="relativeRedirectAllowed"><Property name="jetty.httpConfig.relativeRedirectAllowed" default="false"/></Set>
|
||||
<Set name="useInputDirectByteBuffers" property="jetty.httpConfig.useInputDirectByteBuffers"/>
|
||||
<Set name="useOutputDirectByteBuffers" property="jetty.httpConfig.useOutputDirectByteBuffers"/>
|
||||
|
|
|
@ -75,7 +75,7 @@ etc/jetty.xml
|
|||
## URI Compliance: DEFAULT, LEGACY, RFC3986, RFC3986_UNAMBIGUOUS, UNSAFE
|
||||
# jetty.httpConfig.uriCompliance=DEFAULT
|
||||
|
||||
## Cookie compliance mode for parsing request Cookie headers: RFC2965, RFC6265
|
||||
## Cookie compliance mode for parsing request Cookie headers: RFC6265_STRICT, RFC6265, RFC6265_LEGACY, RFC2965, RFC2965_LEGACY
|
||||
# jetty.httpConfig.requestCookieCompliance=RFC6265
|
||||
|
||||
## Cookie compliance mode for generating response Set-Cookie: RFC2965, RFC6265
|
||||
|
|
|
@ -135,11 +135,9 @@ public final class HttpCookieUtils
|
|||
|
||||
public static String getSetCookie(HttpCookie httpCookie, CookieCompliance compliance)
|
||||
{
|
||||
if (compliance == CookieCompliance.RFC6265)
|
||||
if (compliance == null || CookieCompliance.RFC6265_LEGACY.compliesWith(compliance))
|
||||
return getRFC6265SetCookie(httpCookie);
|
||||
if (compliance == CookieCompliance.RFC2965)
|
||||
return getRFC2965SetCookie(httpCookie);
|
||||
throw new IllegalStateException();
|
||||
return getRFC2965SetCookie(httpCookie);
|
||||
}
|
||||
|
||||
public static String getRFC2965SetCookie(HttpCookie httpCookie)
|
||||
|
|
|
@ -0,0 +1,211 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others.
|
||||
//
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License v. 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
|
||||
// which is available at https://www.apache.org/licenses/LICENSE-2.0.
|
||||
//
|
||||
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.server;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.eclipse.jetty.http.CookieCompliance;
|
||||
import org.eclipse.jetty.http.CookieParser;
|
||||
import org.eclipse.jetty.http.HttpHeader;
|
||||
import org.eclipse.jetty.http.HttpTester;
|
||||
import org.eclipse.jetty.server.handler.AbstractHandler;
|
||||
import org.eclipse.jetty.util.UrlEncoded;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.Cookie;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
import static org.eclipse.jetty.http.CookieCompliance.RFC2965;
|
||||
import static org.eclipse.jetty.http.CookieCompliance.RFC2965_LEGACY;
|
||||
import static org.eclipse.jetty.http.CookieCompliance.RFC6265;
|
||||
import static org.eclipse.jetty.http.CookieCompliance.RFC6265_LEGACY;
|
||||
import static org.eclipse.jetty.http.CookieCompliance.RFC6265_STRICT;
|
||||
import static org.eclipse.jetty.http.CookieCompliance.from;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
import static org.hamcrest.Matchers.nullValue;
|
||||
|
||||
public class ServerHttpCookieTest
|
||||
{
|
||||
private Server _server;
|
||||
private LocalConnector _connector;
|
||||
private HttpConfiguration _httpConfiguration;
|
||||
|
||||
@BeforeEach
|
||||
public void beforeEach() throws Exception
|
||||
{
|
||||
_server = new Server();
|
||||
_connector = new LocalConnector(_server);
|
||||
_server.addConnector(_connector);
|
||||
_server.setHandler(new AbstractHandler()
|
||||
{
|
||||
@Override
|
||||
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
|
||||
{
|
||||
HttpConfiguration config = baseRequest.getHttpChannel().getHttpConfiguration();
|
||||
baseRequest.setHandled(true);
|
||||
String setCookie = baseRequest.getParameter("SetCookie");
|
||||
if (setCookie != null)
|
||||
{
|
||||
CookieParser parser = CookieParser.newParser((name, value, version, domain, path, comment) ->
|
||||
{
|
||||
Cookie cookie = new Cookie(name, value);
|
||||
if (version > 0)
|
||||
cookie.setVersion(version);
|
||||
if (domain != null)
|
||||
cookie.setDomain(domain);
|
||||
if (path != null)
|
||||
cookie.setPath(path);
|
||||
if (comment != null)
|
||||
cookie.setComment(comment);
|
||||
response.addCookie(cookie);
|
||||
}, RFC2965, null);
|
||||
parser.parseField(setCookie);
|
||||
}
|
||||
|
||||
Cookie[] cookies = request.getCookies();
|
||||
StringBuilder out = new StringBuilder();
|
||||
if (cookies != null)
|
||||
{
|
||||
for (Cookie cookie : cookies)
|
||||
{
|
||||
out
|
||||
.append("[")
|
||||
.append(cookie.getName())
|
||||
.append('=')
|
||||
.append(cookie.getValue());
|
||||
|
||||
if (cookie.getVersion() > 0)
|
||||
out.append(";Version=").append(cookie.getVersion());
|
||||
if (cookie.getPath() != null)
|
||||
out.append(";Path=").append(cookie.getPath());
|
||||
if (cookie.getDomain() != null)
|
||||
out.append(";Domain=").append(cookie.getDomain());
|
||||
out.append("]\n");
|
||||
}
|
||||
}
|
||||
response.getWriter().println(out);
|
||||
}
|
||||
});
|
||||
_httpConfiguration = _connector.getConnectionFactory(HttpConnectionFactory.class).getHttpConfiguration();
|
||||
_server.start();
|
||||
}
|
||||
|
||||
public static Stream<Arguments> requestCases()
|
||||
{
|
||||
return Stream.of(
|
||||
Arguments.of(RFC6265_STRICT, "Cookie: name=value", 200, "Version=", List.of("[name=value]").toArray(new String[0])),
|
||||
|
||||
// Attribute tests
|
||||
// TODO $name attributes are ignored because servlet 5.0 Cookie class rejects them. They are not ignored in servlet 6.0
|
||||
Arguments.of(RFC6265_STRICT, "Cookie: $version=1; name=value", 200, "Version=", List.of("[name=value]").toArray(new String[0])),
|
||||
Arguments.of(RFC6265, "Cookie: $version=1; name=value", 200, "Version=", List.of("[name=value]").toArray(new String[0])),
|
||||
Arguments.of(RFC6265, "Cookie: name=value;$path=/path", 200, "Path=", List.of("[name=value]").toArray(new String[0])),
|
||||
Arguments.of(from("RFC6265,ATTRIBUTES"), "Cookie: name=value;$path=/path", 200, "/path", List.of("name=value").toArray(new String[0])),
|
||||
Arguments.of(from("RFC6265_STRICT,ATTRIBUTE_VALUES"), "Cookie: name=value;$path=/path", 200, null, List.of("name=value;Path=/path").toArray(new String[0])),
|
||||
Arguments.of(RFC2965, "Cookie: name=value;$path=/path", 200, null, List.of("name=value;Path=/path").toArray(new String[0])),
|
||||
Arguments.of(RFC2965, "Cookie: $Version=1;name=value;$path=/path", 200, null, List.of("name=value;Version=1;Path=/path").toArray(new String[0])),
|
||||
Arguments.of(RFC2965, "Cookie: $Version=1;name=value;$path=/path;$Domain=host", 200, null, List.of("name=value;Version=1;Path=/path;Domain=host").toArray(new String[0])),
|
||||
|
||||
// multiple cookie tests
|
||||
Arguments.of(RFC6265_STRICT, "Cookie: name=value; other=extra", 200, "Version=", List.of("[name=value]", "[other=extra]").toArray(new String[0])),
|
||||
Arguments.of(RFC6265_STRICT, "Cookie: name=value, other=extra", 400, null, List.of("BadMessageException", "Comma cookie separator").toArray(new String[0])),
|
||||
Arguments.of(from("RFC6265_STRICT,COMMA_SEPARATOR,"), "Cookie: name=value, other=extra", 200, "Version=", List.of("[name=value]", "[other=extra]").toArray(new String[0])),
|
||||
Arguments.of(RFC6265, "Cookie: name=value, other=extra", 200, "name=value", null),
|
||||
Arguments.of(RFC6265_LEGACY, "Cookie: name=value, other=extra", 200, null, List.of("[name=value, other=extra]").toArray(new String[0])),
|
||||
Arguments.of(RFC6265_LEGACY, "Cookie: name=value; other=extra", 200, null, List.of("[name=value]", "other=extra]").toArray(new String[0])),
|
||||
Arguments.of(RFC2965, "Cookie: name=value, other=extra", 200, "Version=", List.of("[name=value]", "[other=extra]").toArray(new String[0])),
|
||||
Arguments.of(RFC2965_LEGACY, "Cookie: name=value, other=extra", 200, "Version=", List.of("[name=value]", "[other=extra]").toArray(new String[0])),
|
||||
|
||||
// white space
|
||||
Arguments.of(RFC6265_STRICT, "Cookie: name =value", 400, null, List.of("BadMessageException", "Bad Cookie name").toArray(new String[0])),
|
||||
Arguments.of(from("RFC6265,OPTIONAL_WHITE_SPACE"), "Cookie: name =value", 200, null, List.of("name=value").toArray(new String[0])),
|
||||
|
||||
// bad characters
|
||||
Arguments.of(RFC6265_STRICT, "Cookie: name=va\\ue", 400, null, List.of("BadMessageException", "Bad Cookie value").toArray(new String[0])),
|
||||
Arguments.of(RFC6265_STRICT, "Cookie: name=\"value\"", 200, "Version=", List.of("[name=value]").toArray(new String[0])),
|
||||
Arguments.of(RFC6265_STRICT, "Cookie: name=\"value;other=extra\"", 400, null, List.of("BadMessageException", "Bad Cookie quoted value").toArray(new String[0])),
|
||||
Arguments.of(RFC6265, "Cookie: name=\"value;other=extra\"", 200, "name=value", null),
|
||||
Arguments.of(RFC6265_LEGACY, "Cookie: name=\"value;other=extra\"", 200, null, List.of("[name=value;other=extra]").toArray(new String[0])),
|
||||
Arguments.of(RFC2965, "Cookie: name=\"value;other=extra\"", 200, null, List.of("[name=value;other=extra]").toArray(new String[0])),
|
||||
Arguments.of(RFC2965, "Cookie: name=\"value;other=extra", 200, "name=value", null),
|
||||
Arguments.of(RFC2965_LEGACY, "Cookie: name=\"value;other=extra\"", 200, null, List.of("[name=value;other=extra]").toArray(new String[0])),
|
||||
Arguments.of(RFC2965_LEGACY, "Cookie: name=\"value;other=extra", 200, null, List.of("[name=\"value;other=extra]").toArray(new String[0])),
|
||||
|
||||
// TCK check
|
||||
Arguments.of(RFC6265, "Cookie: $Version=1; name1=value1; $Domain=hostname; $Path=/servlet_jsh_cookie_web", 200, null, List.of("name1=value1").toArray(new String[0]))
|
||||
);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("requestCases")
|
||||
public void testRequestCookies(CookieCompliance compliance, String cookie, int status, String unexpected, String... expectations) throws Exception
|
||||
{
|
||||
_httpConfiguration.setRequestCookieCompliance(compliance);
|
||||
|
||||
HttpTester.Response response = HttpTester.parseResponse(_connector.getResponse("GET / HTTP/1.0\r\n" + cookie + "\r\n\r\n"));
|
||||
|
||||
assertThat(response.getStatus(), equalTo(status));
|
||||
|
||||
if (unexpected != null)
|
||||
assertThat(response.getContent(), not(containsString(unexpected)));
|
||||
|
||||
if (expectations != null)
|
||||
for (String expected : expectations)
|
||||
assertThat(response.getContent(), containsString(expected));
|
||||
}
|
||||
|
||||
public static Stream<Arguments> responseCases()
|
||||
{
|
||||
return Stream.of(
|
||||
Arguments.of(RFC6265_STRICT, "name=value", "name=value"),
|
||||
Arguments.of(RFC6265, "name=value", "name=value"),
|
||||
Arguments.of(RFC6265_LEGACY, "name=value", "name=value"),
|
||||
Arguments.of(RFC2965, "name=value", "name=value"),
|
||||
Arguments.of(RFC2965_LEGACY, "name=value", "name=value"),
|
||||
|
||||
Arguments.of(RFC6265_STRICT, "name=value;$version=1;$path=/path;$domain=domain", "name=value; Path=/path; Domain=domain"),
|
||||
Arguments.of(RFC6265, "name=value;$version=1;$path=/path;$domain=domain", "name=value; Path=/path; Domain=domain"),
|
||||
Arguments.of(RFC6265_LEGACY, "name=value;$version=1;$path=/path;$domain=domain", "name=value; Path=/path; Domain=domain"),
|
||||
Arguments.of(RFC2965, "name=value;$version=1;$path=/path;$domain=domain", "name=value;Version=1;Path=/path;Domain=domain"),
|
||||
Arguments.of(RFC2965_LEGACY, "name=value;$version=1;$path=/path;$domain=domain", "name=value;Version=1;Path=/path;Domain=domain"),
|
||||
|
||||
Arguments.of(RFC6265, "name=value", "name=value")
|
||||
);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("responseCases")
|
||||
public void testResponseCookies(CookieCompliance compliance, String cookie, String expected) throws Exception
|
||||
{
|
||||
_httpConfiguration.setResponseCookieCompliance(compliance);
|
||||
|
||||
HttpTester.Response response = HttpTester.parseResponse(_connector.getResponse("GET /?SetCookie=" + UrlEncoded.encodeString(cookie) + " HTTP/1.0\r\n\r\n"));
|
||||
assertThat(response.getStatus(), equalTo(200));
|
||||
|
||||
String setCookie = response.get(HttpHeader.SET_COOKIE);
|
||||
if (expected == null)
|
||||
assertThat(setCookie, nullValue());
|
||||
else
|
||||
assertThat(setCookie, equalTo(expected));
|
||||
}
|
||||
}
|
|
@ -17,9 +17,11 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
|
||||
import jakarta.servlet.http.Cookie;
|
||||
import org.eclipse.jetty.http.BadMessageException;
|
||||
import org.eclipse.jetty.http.ComplianceViolation;
|
||||
import org.eclipse.jetty.http.CookieCompliance;
|
||||
import org.eclipse.jetty.http.CookieParser;
|
||||
import org.eclipse.jetty.http.HttpStatus;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
@ -95,7 +97,14 @@ public class Cookies implements CookieParser.Handler
|
|||
if (_parsed)
|
||||
return _cookies;
|
||||
|
||||
_parser.parseFields(_rawFields);
|
||||
try
|
||||
{
|
||||
_parser.parseFields(_rawFields);
|
||||
}
|
||||
catch (CookieParser.InvalidCookieException invalidCookieException)
|
||||
{
|
||||
throw new BadMessageException(HttpStatus.BAD_REQUEST_400, invalidCookieException.getMessage(), invalidCookieException);
|
||||
}
|
||||
_cookies = _cookieList.toArray(new Cookie[0]);
|
||||
_cookieList.clear();
|
||||
_parsed = true;
|
||||
|
|
Loading…
Reference in New Issue