Skip to content

Commit 2e81bcc

Browse files
committed
Sort cookies as per FRC6265, close AsyncHttpClient#1048
1 parent 0e805db commit 2e81bcc

File tree

1 file changed

+47
-4
lines changed

1 file changed

+47
-4
lines changed

client/src/main/java/org/asynchttpclient/cookie/CookieEncoder.java

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,20 +12,63 @@
1212
*/
1313
package org.asynchttpclient.cookie;
1414

15-
import org.asynchttpclient.util.StringUtils;
16-
15+
import java.util.Arrays;
1716
import java.util.Collection;
17+
import java.util.Comparator;
18+
19+
import org.asynchttpclient.util.StringUtils;
1820

1921
public final class CookieEncoder {
2022

23+
/**
24+
* Sort cookies into decreasing order of path length, breaking ties by sorting into increasing chronological order of creation time, as recommended by RFC 6265.
25+
*/
26+
private static final Comparator<Cookie> COOKIE_COMPARATOR = new Comparator<Cookie>() {
27+
@Override
28+
public int compare(Cookie c1, Cookie c2) {
29+
String path1 = c1.getPath();
30+
String path2 = c2.getPath();
31+
// Cookies with unspecified path default to the path of the request. We don't
32+
// know the request path here, but we assume that the length of an unspecified
33+
// path is longer than any specified path (i.e. pathless cookies come first),
34+
// because setting cookies with a path longer than the request path is of
35+
// limited use.
36+
int len1 = path1 == null ? Integer.MAX_VALUE : path1.length();
37+
int len2 = path2 == null ? Integer.MAX_VALUE : path2.length();
38+
int diff = len2 - len1;
39+
if (diff != 0) {
40+
return diff;
41+
}
42+
// Rely on Java's sort stability to retain creation order in cases where
43+
// cookies have same path length.
44+
return -1;
45+
}
46+
};
47+
2148
private CookieEncoder() {
2249
}
2350

2451
public static String encode(Collection<Cookie> cookies) {
2552
StringBuilder sb = StringUtils.stringBuilder();
2653

27-
for (Cookie cookie : cookies) {
28-
add(sb, cookie.getName(), cookie.getValue(), cookie.isWrap());
54+
if (cookies.isEmpty()) {
55+
return "";
56+
57+
} else if (cookies.size() == 1) {
58+
Cookie cookie = cookies.iterator().next();
59+
if (cookie != null) {
60+
add(sb, cookie.getName(), cookie.getValue(), cookie.isWrap());
61+
}
62+
63+
} else {
64+
Cookie[] cookiesSorted = cookies.toArray(new Cookie[cookies.size()]);
65+
Arrays.sort(cookiesSorted, COOKIE_COMPARATOR);
66+
for (int i = 0; i < cookiesSorted.length; i++) {
67+
Cookie cookie = cookiesSorted[i];
68+
if (cookie != null) {
69+
add(sb, cookie.getName(), cookie.getValue(), cookie.isWrap());
70+
}
71+
}
2972
}
3073

3174
if (sb.length() > 0) {

0 commit comments

Comments
 (0)