Make CookieEncoder and CookieDecoder stateless

- Also: CookieEncoder is split into ServerCookieEncoder and
  ClientCookieEncoder
This commit is contained in:
Trustin Lee 2012-06-26 05:26:54 +09:00
parent 1be9bbf62c
commit 6d2f6d697d
11 changed files with 411 additions and 351 deletions

View File

@ -0,0 +1,122 @@
package io.netty.handler.codec.http;
import static io.netty.handler.codec.http.CookieEncoderUtil.*;
import java.util.Collection;
/**
* Encodes client-side {@link Cookie}s into an HTTP header value. This encoder can encode
* the HTTP cookie version 0, 1, and 2.
* <pre>
* // Example
* {@link HttpRequest} req = ...;
* res.setHeader("Cookie", {@link ClientCookieEncoder}.encode("JSESSIONID", "1234"));
* </pre>
*
* @see CookieDecoder
*
* @apiviz.stereotype utility
* @apiviz.has io.netty.handler.codec.http.Cookie oneway - - encodes
*/
public final class ClientCookieEncoder {
/**
* Encodes the specified cookie into an HTTP header value.
*/
public static String encode(String name, String value) {
return encode(new DefaultCookie(name, value));
}
public static String encode(Cookie cookie) {
if (cookie == null) {
throw new NullPointerException("cookie");
}
StringBuilder buf = new StringBuilder();
encode(buf, cookie);
return stripTrailingSeparator(buf);
}
public static String encode(Cookie... cookies) {
if (cookies == null) {
throw new NullPointerException("cookies");
}
StringBuilder buf = new StringBuilder();
for (Cookie c: cookies) {
if (c == null) {
break;
}
encode(buf, c);
}
return stripTrailingSeparator(buf);
}
public static String encode(Collection<Cookie> cookies) {
if (cookies == null) {
throw new NullPointerException("cookies");
}
StringBuilder buf = new StringBuilder();
for (Cookie c: cookies) {
if (c == null) {
break;
}
encode(buf, c);
}
return stripTrailingSeparator(buf);
}
public static String encode(Iterable<Cookie> cookies) {
if (cookies == null) {
throw new NullPointerException("cookies");
}
StringBuilder buf = new StringBuilder();
for (Cookie c: cookies) {
if (c == null) {
break;
}
encode(buf, c);
}
return stripTrailingSeparator(buf);
}
private static void encode(StringBuilder buf, Cookie c) {
if (c.getVersion() >= 1) {
add(buf, '$' + CookieHeaderNames.VERSION, 1);
}
add(buf, c.getName(), c.getValue());
if (c.getPath() != null) {
add(buf, '$' + CookieHeaderNames.PATH, c.getPath());
}
if (c.getDomain() != null) {
add(buf, '$' + CookieHeaderNames.DOMAIN, c.getDomain());
}
if (c.getVersion() >= 1) {
if (!c.getPorts().isEmpty()) {
buf.append('$');
buf.append(CookieHeaderNames.PORT);
buf.append((char) HttpConstants.EQUALS);
buf.append((char) HttpConstants.DOUBLE_QUOTE);
for (int port: c.getPorts()) {
buf.append(port);
buf.append((char) HttpConstants.COMMA);
}
buf.setCharAt(buf.length() - 1, (char) HttpConstants.DOUBLE_QUOTE);
buf.append((char) HttpConstants.SEMICOLON);
}
}
}
private ClientCookieEncoder() {
// Unused
}
}

View File

@ -32,12 +32,13 @@ import java.util.TreeSet;
* Set&lt;{@link Cookie}&gt; cookies = new {@link CookieDecoder}().decode(value);
* </pre>
*
* @see CookieEncoder
* @see ClientCookieEncoder
* @see ServerCookieEncoder
*
* @apiviz.stereotype utility
* @apiviz.has io.netty.handler.codec.http.Cookie oneway - - decodes
*/
public class CookieDecoder {
public final class CookieDecoder {
private static final String COMMA = ",";
@ -46,7 +47,7 @@ public class CookieDecoder {
*
* @return the decoded {@link Cookie}s
*/
public Set<Cookie> decode(String header) {
public static Set<Cookie> decode(String header) {
List<String> names = new ArrayList<String>(8);
List<String> values = new ArrayList<String>(8);
extractKeyValuePairs(header, names, values);
@ -289,4 +290,8 @@ public class CookieDecoder {
values.add(value);
}
}
private CookieDecoder() {
// Unused
}
}

View File

@ -1,269 +0,0 @@
/*
* Copyright 2012 The Netty Project
*
* The Netty Project licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package io.netty.handler.codec.http;
import java.util.Date;
import java.util.Set;
import java.util.TreeSet;
/**
* Encodes {@link Cookie}s into an HTTP header value. This encoder can encode
* the HTTP cookie version 0, 1, and 2.
* <p>
* This encoder is stateful. It maintains an internal data structure that
* holds the {@link Cookie}s added by the {@link #addCookie(String, String)}
* method. Once {@link #encode()} is called, all added {@link Cookie}s are
* encoded into an HTTP header value and all {@link Cookie}s in the internal
* data structure are removed so that the encoder can start over.
* <pre>
* // Client-side example
* {@link HttpRequest} req = ...;
* {@link CookieEncoder} encoder = new {@link CookieEncoder}(false);
* encoder.addCookie("JSESSIONID", "1234");
* res.setHeader("Cookie", encoder.encode());
*
* // Server-side example
* {@link HttpResponse} res = ...;
* {@link CookieEncoder} encoder = new {@link CookieEncoder}(true);
* encoder.addCookie("JSESSIONID", "1234");
* res.setHeader("Set-Cookie", encoder.encode());
* </pre>
*
* @see CookieDecoder
*
* @apiviz.stereotype utility
* @apiviz.has io.netty.handler.codec.http.Cookie oneway - - encodes
*/
public class CookieEncoder {
private final Set<Cookie> cookies = new TreeSet<Cookie>();
private final boolean server;
/**
* Creates a new encoder.
*
* @param server {@code true} if and only if this encoder is supposed to
* encode server-side cookies. {@code false} if and only if
* this encoder is supposed to encode client-side cookies.
*/
public CookieEncoder(boolean server) {
this.server = server;
}
/**
* Adds a new {@link Cookie} created with the specified name and value to
* this encoder.
*/
public void addCookie(String name, String value) {
addCookie(new DefaultCookie(name, value));
}
/**
* Adds the specified {@link Cookie} to this encoder.
*/
public void addCookie(Cookie cookie) {
cookies.add(cookie);
}
/**
* Encodes the {@link Cookie}s which were added by {@link #addCookie(Cookie)}
* so far into an HTTP header value. If no {@link Cookie}s were added,
* an empty string is returned.
*
* <strong>Be aware that calling this method will clear the {@link Cookie}s you added to
* this encoder.</strong>
*/
public String encode() {
String answer;
if (server) {
answer = encodeServerSide();
} else {
answer = encodeClientSide();
}
cookies.clear();
return answer;
}
private String encodeServerSide() {
if (cookies.size() > 1) {
throw new IllegalStateException(
"encode() can encode only one cookie on server mode: " + cookies.size() + " cookies added");
}
StringBuilder sb = new StringBuilder();
for (Cookie cookie: cookies) {
add(sb, cookie.getName(), cookie.getValue());
if (cookie.getMaxAge() >= 0) {
if (cookie.getVersion() == 0) {
addUnquoted(sb, CookieHeaderNames.EXPIRES,
new HttpHeaderDateFormat().format(
new Date(System.currentTimeMillis() +
cookie.getMaxAge() * 1000L)));
} else {
add(sb, CookieHeaderNames.MAX_AGE, cookie.getMaxAge());
}
}
if (cookie.getPath() != null) {
if (cookie.getVersion() > 0) {
add(sb, CookieHeaderNames.PATH, cookie.getPath());
} else {
addUnquoted(sb, CookieHeaderNames.PATH, cookie.getPath());
}
}
if (cookie.getDomain() != null) {
if (cookie.getVersion() > 0) {
add(sb, CookieHeaderNames.DOMAIN, cookie.getDomain());
} else {
addUnquoted(sb, CookieHeaderNames.DOMAIN, cookie.getDomain());
}
}
if (cookie.isSecure()) {
sb.append(CookieHeaderNames.SECURE);
sb.append((char) HttpConstants.SEMICOLON);
}
if (cookie.isHttpOnly()) {
sb.append(CookieHeaderNames.HTTPONLY);
sb.append((char) HttpConstants.SEMICOLON);
}
if (cookie.getVersion() >= 1) {
if (cookie.getComment() != null) {
add(sb, CookieHeaderNames.COMMENT, cookie.getComment());
}
add(sb, CookieHeaderNames.VERSION, 1);
if (cookie.getCommentUrl() != null) {
addQuoted(sb, CookieHeaderNames.COMMENTURL, cookie.getCommentUrl());
}
if (!cookie.getPorts().isEmpty()) {
sb.append(CookieHeaderNames.PORT);
sb.append((char) HttpConstants.EQUALS);
sb.append((char) HttpConstants.DOUBLE_QUOTE);
for (int port: cookie.getPorts()) {
sb.append(port);
sb.append((char) HttpConstants.COMMA);
}
sb.setCharAt(sb.length() - 1, (char) HttpConstants.DOUBLE_QUOTE);
sb.append((char) HttpConstants.SEMICOLON);
}
if (cookie.isDiscard()) {
sb.append(CookieHeaderNames.DISCARD);
sb.append((char) HttpConstants.SEMICOLON);
}
}
}
if (sb.length() > 0) {
sb.setLength(sb.length() - 1);
}
return sb.toString();
}
private String encodeClientSide() {
StringBuilder sb = new StringBuilder();
for (Cookie cookie: cookies) {
if (cookie.getVersion() >= 1) {
add(sb, '$' + CookieHeaderNames.VERSION, 1);
}
add(sb, cookie.getName(), cookie.getValue());
if (cookie.getPath() != null) {
add(sb, '$' + CookieHeaderNames.PATH, cookie.getPath());
}
if (cookie.getDomain() != null) {
add(sb, '$' + CookieHeaderNames.DOMAIN, cookie.getDomain());
}
if (cookie.getVersion() >= 1) {
if (!cookie.getPorts().isEmpty()) {
sb.append('$');
sb.append(CookieHeaderNames.PORT);
sb.append((char) HttpConstants.EQUALS);
sb.append((char) HttpConstants.DOUBLE_QUOTE);
for (int port: cookie.getPorts()) {
sb.append(port);
sb.append((char) HttpConstants.COMMA);
}
sb.setCharAt(sb.length() - 1, (char) HttpConstants.DOUBLE_QUOTE);
sb.append((char) HttpConstants.SEMICOLON);
}
}
}
if (sb.length() > 0) {
sb.setLength(sb.length() - 1);
}
return sb.toString();
}
private static void add(StringBuilder sb, String name, String val) {
if (val == null) {
addQuoted(sb, name, "");
return;
}
for (int i = 0; i < val.length(); i ++) {
char c = val.charAt(i);
switch (c) {
case '\t': case ' ': case '"': case '(': case ')': case ',':
case '/': case ':': case ';': case '<': case '=': case '>':
case '?': case '@': case '[': case '\\': case ']':
case '{': case '}':
addQuoted(sb, name, val);
return;
}
}
addUnquoted(sb, name, val);
}
private static void addUnquoted(StringBuilder sb, String name, String val) {
sb.append(name);
sb.append((char) HttpConstants.EQUALS);
sb.append(val);
sb.append((char) HttpConstants.SEMICOLON);
}
private static void addQuoted(StringBuilder sb, String name, String val) {
if (val == null) {
val = "";
}
sb.append(name);
sb.append((char) HttpConstants.EQUALS);
sb.append((char) HttpConstants.DOUBLE_QUOTE);
sb.append(val.replace("\\", "\\\\").replace("\"", "\\\""));
sb.append((char) HttpConstants.DOUBLE_QUOTE);
sb.append((char) HttpConstants.SEMICOLON);
}
private static void add(StringBuilder sb, String name, long val) {
sb.append(name);
sb.append((char) HttpConstants.EQUALS);
sb.append(val);
sb.append((char) HttpConstants.SEMICOLON);
}
}

View File

@ -0,0 +1,79 @@
/*
* Copyright 2012 The Netty Project
*
* The Netty Project licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package io.netty.handler.codec.http;
final class CookieEncoderUtil {
static String stripTrailingSeparator(StringBuilder buf) {
if (buf.length() > 0) {
buf.setLength(buf.length() - 1);
}
return buf.toString();
}
static void add(StringBuilder sb, String name, String val) {
if (val == null) {
addQuoted(sb, name, "");
return;
}
for (int i = 0; i < val.length(); i ++) {
char c = val.charAt(i);
switch (c) {
case '\t': case ' ': case '"': case '(': case ')': case ',':
case '/': case ':': case ';': case '<': case '=': case '>':
case '?': case '@': case '[': case '\\': case ']':
case '{': case '}':
addQuoted(sb, name, val);
return;
}
}
addUnquoted(sb, name, val);
}
static void addUnquoted(StringBuilder sb, String name, String val) {
sb.append(name);
sb.append((char) HttpConstants.EQUALS);
sb.append(val);
sb.append((char) HttpConstants.SEMICOLON);
}
static void addQuoted(StringBuilder sb, String name, String val) {
if (val == null) {
val = "";
}
sb.append(name);
sb.append((char) HttpConstants.EQUALS);
sb.append((char) HttpConstants.DOUBLE_QUOTE);
sb.append(val.replace("\\", "\\\\").replace("\"", "\\\""));
sb.append((char) HttpConstants.DOUBLE_QUOTE);
sb.append((char) HttpConstants.SEMICOLON);
}
static void add(StringBuilder sb, String name, long val) {
sb.append(name);
sb.append((char) HttpConstants.EQUALS);
sb.append(val);
sb.append((char) HttpConstants.SEMICOLON);
}
private CookieEncoderUtil() {
// Unused
}
}

View File

@ -23,10 +23,12 @@ package io.netty.handler.codec.http;
* <p>
* Unlike the Servlet API, a query string is constructed and decomposed by
* {@link QueryStringEncoder} and {@link QueryStringDecoder}. {@link Cookie}
* support is also provided separately via {@link CookieEncoder} and
* {@link CookieDecoder}.
* support is also provided separately via {@link CookieDecoder}, {@link ClientCookieEncoder},
* and {@link @ServerCookieEncoder}.
*
* @see HttpResponse
* @see CookieEncoder
* @see ClientCookieEncoder
* @see ServerCookieEncoder
* @see CookieDecoder
*/
public interface HttpRequest extends HttpMessage {

View File

@ -21,11 +21,13 @@ package io.netty.handler.codec.http;
*
* <h3>Accessing Cookie</h3>
* <p>
* Unlike the Servlet API, {@link Cookie} support is provided separately via
* {@link CookieEncoder} and {@link CookieDecoder}.
* Unlike the Servlet API, {@link Cookie} support is provided separately via {@link CookieDecoder},
* {@link ClientCookieEncoder}, and {@link ServerCookieEncoder}.
*
* @see HttpRequest
* @see CookieEncoder
* @see CookieDecoder
* @see ClientCookieEncoder
* @see ServerCookieEncoder
*/
public interface HttpResponse extends HttpMessage {

View File

@ -0,0 +1,155 @@
package io.netty.handler.codec.http;
import static io.netty.handler.codec.http.CookieEncoderUtil.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;
/**
* Encodes server-side {@link Cookie}s into HTTP header values. This encoder can encode
* the HTTP cookie version 0, 1, and 2.
* <pre>
* // Example
* {@link HttpRequest} req = ...;
* res.setHeader("Set-Cookie", {@link ServerCookieEncoder}.encode("JSESSIONID", "1234"));
* </pre>
*
* @see CookieDecoder
*
* @apiviz.stereotype utility
* @apiviz.has io.netty.handler.codec.http.Cookie oneway - - encodes
*/
public final class ServerCookieEncoder {
/**
* Encodes the specified cookie into an HTTP header value.
*/
public static String encode(String name, String value) {
return encode(new DefaultCookie(name, value));
}
public static String encode(Cookie cookie) {
if (cookie == null) {
throw new NullPointerException("cookie");
}
StringBuilder buf = new StringBuilder();
add(buf, cookie.getName(), cookie.getValue());
if (cookie.getMaxAge() >= 0) {
if (cookie.getVersion() == 0) {
addUnquoted(buf, CookieHeaderNames.EXPIRES,
new HttpHeaderDateFormat().format(
new Date(System.currentTimeMillis() +
cookie.getMaxAge() * 1000L)));
} else {
add(buf, CookieHeaderNames.MAX_AGE, cookie.getMaxAge());
}
}
if (cookie.getPath() != null) {
if (cookie.getVersion() > 0) {
add(buf, CookieHeaderNames.PATH, cookie.getPath());
} else {
addUnquoted(buf, CookieHeaderNames.PATH, cookie.getPath());
}
}
if (cookie.getDomain() != null) {
if (cookie.getVersion() > 0) {
add(buf, CookieHeaderNames.DOMAIN, cookie.getDomain());
} else {
addUnquoted(buf, CookieHeaderNames.DOMAIN, cookie.getDomain());
}
}
if (cookie.isSecure()) {
buf.append(CookieHeaderNames.SECURE);
buf.append((char) HttpConstants.SEMICOLON);
}
if (cookie.isHttpOnly()) {
buf.append(CookieHeaderNames.HTTPONLY);
buf.append((char) HttpConstants.SEMICOLON);
}
if (cookie.getVersion() >= 1) {
if (cookie.getComment() != null) {
add(buf, CookieHeaderNames.COMMENT, cookie.getComment());
}
add(buf, CookieHeaderNames.VERSION, 1);
if (cookie.getCommentUrl() != null) {
addQuoted(buf, CookieHeaderNames.COMMENTURL, cookie.getCommentUrl());
}
if (!cookie.getPorts().isEmpty()) {
buf.append(CookieHeaderNames.PORT);
buf.append((char) HttpConstants.EQUALS);
buf.append((char) HttpConstants.DOUBLE_QUOTE);
for (int port: cookie.getPorts()) {
buf.append(port);
buf.append((char) HttpConstants.COMMA);
}
buf.setCharAt(buf.length() - 1, (char) HttpConstants.DOUBLE_QUOTE);
buf.append((char) HttpConstants.SEMICOLON);
}
if (cookie.isDiscard()) {
buf.append(CookieHeaderNames.DISCARD);
buf.append((char) HttpConstants.SEMICOLON);
}
}
return stripTrailingSeparator(buf);
}
public static List<String> encode(Cookie... cookies) {
if (cookies == null) {
throw new NullPointerException("cookies");
}
List<String> encoded = new ArrayList<String>(cookies.length);
for (Cookie c: cookies) {
if (c == null) {
break;
}
encoded.add(encode(c));
}
return encoded;
}
public static List<String> encode(Collection<Cookie> cookies) {
if (cookies == null) {
throw new NullPointerException("cookies");
}
List<String> encoded = new ArrayList<String>(cookies.size());
for (Cookie c: cookies) {
if (c == null) {
break;
}
encoded.add(encode(c));
}
return encoded;
}
public static List<String> encode(Iterable<Cookie> cookies) {
if (cookies == null) {
throw new NullPointerException("cookies");
}
List<String> encoded = new ArrayList<String>();
for (Cookie c: cookies) {
if (c == null) {
break;
}
encoded.add(encode(c));
}
return encoded;
}
private ServerCookieEncoder() {
// Unused
}
}

View File

@ -31,8 +31,7 @@ public class CookieDecoderTest {
String cookieString = "myCookie=myValue;expires=XXX;path=/apathsomewhere;domain=.adomainsomewhere;secure;";
cookieString = cookieString.replace("XXX", new HttpHeaderDateFormat().format(new Date(System.currentTimeMillis() + 50000)));
CookieDecoder cookieDecoder = new CookieDecoder();
Set<Cookie> cookies = cookieDecoder.decode(cookieString);
Set<Cookie> cookies = CookieDecoder.decode(cookieString);
assertEquals(1, cookies.size());
Cookie cookie = cookies.iterator().next();
assertNotNull(cookie);
@ -62,8 +61,7 @@ public class CookieDecoderTest {
@Test
public void testDecodingSingleCookieV0ExtraParamsIgnored() {
String cookieString = "myCookie=myValue;max-age=50;path=/apathsomewhere;domain=.adomainsomewhere;secure;comment=this is a comment;version=0;commentURL=http://aurl.com;port=\"80,8080\";discard;";
CookieDecoder cookieDecoder = new CookieDecoder();
Set<Cookie> cookies = cookieDecoder.decode(cookieString);
Set<Cookie> cookies = CookieDecoder.decode(cookieString);
assertEquals(1, cookies.size());
Cookie cookie = cookies.iterator().next();
assertNotNull(cookie);
@ -81,8 +79,7 @@ public class CookieDecoderTest {
@Test
public void testDecodingSingleCookieV1() {
String cookieString = "myCookie=myValue;max-age=50;path=/apathsomewhere;domain=.adomainsomewhere;secure;comment=this is a comment;version=1;";
CookieDecoder cookieDecoder = new CookieDecoder();
Set<Cookie> cookies = cookieDecoder.decode(cookieString);
Set<Cookie> cookies = CookieDecoder.decode(cookieString);
assertEquals(1, cookies.size());
Cookie cookie = cookies.iterator().next();
assertEquals("myValue", cookie.getValue());
@ -101,8 +98,7 @@ public class CookieDecoderTest {
@Test
public void testDecodingSingleCookieV1ExtraParamsIgnored() {
String cookieString = "myCookie=myValue;max-age=50;path=/apathsomewhere;domain=.adomainsomewhere;secure;comment=this is a comment;version=1;commentURL=http://aurl.com;port='80,8080';discard;";
CookieDecoder cookieDecoder = new CookieDecoder();
Set<Cookie> cookies = cookieDecoder.decode(cookieString);
Set<Cookie> cookies = CookieDecoder.decode(cookieString);
assertEquals(1, cookies.size());
Cookie cookie = cookies.iterator().next();
assertNotNull(cookie);
@ -120,8 +116,7 @@ public class CookieDecoderTest {
@Test
public void testDecodingSingleCookieV2() {
String cookieString = "myCookie=myValue;max-age=50;path=/apathsomewhere;domain=.adomainsomewhere;secure;comment=this is a comment;version=2;commentURL=http://aurl.com;port=\"80,8080\";discard;";
CookieDecoder cookieDecoder = new CookieDecoder();
Set<Cookie> cookies = cookieDecoder.decode(cookieString);
Set<Cookie> cookies = CookieDecoder.decode(cookieString);
assertEquals(1, cookies.size());
Cookie cookie = cookies.iterator().next();
assertNotNull(cookie);
@ -145,9 +140,8 @@ public class CookieDecoderTest {
String c1 = "myCookie=myValue;max-age=50;path=/apathsomewhere;domain=.adomainsomewhere;secure;comment=this is a comment;version=2;commentURL=\"http://aurl.com\";port='80,8080';discard;";
String c2 = "myCookie2=myValue2;max-age=0;path=/anotherpathsomewhere;domain=.anotherdomainsomewhere;comment=this is another comment;version=2;commentURL=http://anotherurl.com;";
String c3 = "myCookie3=myValue3;max-age=0;version=2;";
CookieDecoder decoder = new CookieDecoder();
Set<Cookie> cookies = decoder.decode(c1 + c2 + c3);
Set<Cookie> cookies = CookieDecoder.decode(c1 + c2 + c3);
assertEquals(3, cookies.size());
Iterator<Cookie> it = cookies.iterator();
Cookie cookie = it.next();
@ -196,7 +190,7 @@ public class CookieDecoderTest {
"Part_Number=\"Riding_Rocket_0023\"; $Path=\"/acme/ammo\"; " +
"Part_Number=\"Rocket_Launcher_0001\"; $Path=\"/acme\"";
Set<Cookie> cookies = new CookieDecoder().decode(source);
Set<Cookie> cookies = CookieDecoder.decode(source);
Iterator<Cookie> it = cookies.iterator();
Cookie c;
@ -231,7 +225,7 @@ public class CookieDecoderTest {
"$Version=\"1\"; session_id=\"1234\", " +
"$Version=\"1\"; session_id=\"1111\"; $Domain=\".cracker.edu\"";
Set<Cookie> cookies = new CookieDecoder().decode(source);
Set<Cookie> cookies = CookieDecoder.decode(source);
Iterator<Cookie> it = cookies.iterator();
Cookie c;
@ -275,7 +269,7 @@ public class CookieDecoderTest {
"h=\"';,\\x\"";
Set<Cookie> cookies = new CookieDecoder().decode(source);
Set<Cookie> cookies = CookieDecoder.decode(source);
Iterator<Cookie> it = cookies.iterator();
Cookie c;
@ -322,7 +316,7 @@ public class CookieDecoderTest {
"__utma=48461872.1094088325.1258140131.1258140131.1258140131.1; " +
"__utmb=48461872.13.10.1258140131; __utmc=48461872; " +
"__utmz=48461872.1258140131.1.1.utmcsr=overstock.com|utmccn=(referral)|utmcmd=referral|utmcct=/Home-Garden/Furniture/Clearance,/clearance,/32/dept.html";
Set<Cookie> cookies = new CookieDecoder().decode(source);
Set<Cookie> cookies = CookieDecoder.decode(source);
Iterator<Cookie> it = cookies.iterator();
Cookie c;
@ -361,7 +355,7 @@ public class CookieDecoderTest {
String source = "Format=EU; expires=Fri, 31-Dec-9999 23:59:59 GMT; path=/";
Set<Cookie> cookies = new CookieDecoder().decode(source);
Set<Cookie> cookies = CookieDecoder.decode(source);
Cookie c = cookies.iterator().next();
assertTrue(Math.abs(expectedMaxAge - c.getMaxAge()) < 2);
@ -372,7 +366,7 @@ public class CookieDecoderTest {
String source = "UserCookie=timeZoneName=(GMT+04:00) Moscow, St. Petersburg, Volgograd&promocode=&region=BE;" +
" expires=Sat, 01-Dec-2012 10:53:31 GMT; path=/";
Set<Cookie> cookies = new CookieDecoder().decode(source);
Set<Cookie> cookies = CookieDecoder.decode(source);
Cookie c = cookies.iterator().next();
assertEquals("timeZoneName=(GMT+04:00) Moscow, St. Petersburg, Volgograd&promocode=&region=BE", c.getValue());
@ -381,7 +375,7 @@ public class CookieDecoderTest {
@Test
public void testDecodingWeirdNames1() {
String src = "path=; expires=Mon, 01-Jan-1990 00:00:00 GMT; path=/; domain=.www.google.com";
Set<Cookie> cookies = new CookieDecoder().decode(src);
Set<Cookie> cookies = CookieDecoder.decode(src);
Cookie c = cookies.iterator().next();
assertEquals("path", c.getName());
assertEquals("", c.getValue());
@ -391,7 +385,7 @@ public class CookieDecoderTest {
@Test
public void testDecodingWeirdNames2() {
String src = "HTTPOnly=";
Set<Cookie> cookies = new CookieDecoder().decode(src);
Set<Cookie> cookies = CookieDecoder.decode(src);
Cookie c = cookies.iterator().next();
assertEquals("HTTPOnly", c.getName());
assertEquals("", c.getValue());
@ -445,7 +439,7 @@ public class CookieDecoderTest {
"%=KqtH!$?mi!!!!'=KqtH!$?mx!!!!'=KqtH!$D7]!!!!#=J_#p!$D@T!!!!#=J_#p!$V<g!!!!" +
"'=KqtH";
Set<Cookie> cookies = new CookieDecoder().decode("bh=\"" + longValue + "\";");
Set<Cookie> cookies = CookieDecoder.decode("bh=\"" + longValue + "\";");
assertEquals(1, cookies.size());
Cookie c = cookies.iterator().next();
assertEquals("bh", c.getName());

View File

@ -19,6 +19,7 @@ import static org.junit.Assert.*;
import java.text.DateFormat;
import java.util.Date;
import java.util.List;
import org.junit.Test;
@ -28,8 +29,6 @@ public class CookieEncoderTest {
String result = "myCookie=myValue;Expires=XXX;Path=/apathsomewhere;Domain=.adomainsomewhere;Secure";
DateFormat df = new HttpHeaderDateFormat();
Cookie cookie = new DefaultCookie("myCookie", "myValue");
CookieEncoder encoder = new CookieEncoder(true);
encoder.addCookie(cookie);
cookie.setComment("this is a Comment");
cookie.setCommentUrl("http://aurl.com");
cookie.setDomain(".adomainsomewhere");
@ -39,7 +38,7 @@ public class CookieEncoderTest {
cookie.setPorts(80, 8080);
cookie.setSecure(true);
String encodedCookie = encoder.encode();
String encodedCookie = ServerCookieEncoder.encode(cookie);
long currentTime = System.currentTimeMillis();
boolean fail = true;
@ -61,15 +60,13 @@ public class CookieEncoderTest {
public void testEncodingSingleCookieV1() {
String result = "myCookie=myValue;Max-Age=50;Path=\"/apathsomewhere\";Domain=.adomainsomewhere;Secure;Comment=\"this is a Comment\";Version=1";
Cookie cookie = new DefaultCookie("myCookie", "myValue");
CookieEncoder encoder = new CookieEncoder(true);
encoder.addCookie(cookie);
cookie.setVersion(1);
cookie.setComment("this is a Comment");
cookie.setDomain(".adomainsomewhere");
cookie.setMaxAge(50);
cookie.setPath("/apathsomewhere");
cookie.setSecure(true);
String encodedCookie = encoder.encode();
String encodedCookie = ServerCookieEncoder.encode(cookie);
assertEquals(result, encodedCookie);
}
@ -77,8 +74,6 @@ public class CookieEncoderTest {
public void testEncodingSingleCookieV2() {
String result = "myCookie=myValue;Max-Age=50;Path=\"/apathsomewhere\";Domain=.adomainsomewhere;Secure;Comment=\"this is a Comment\";Version=1;CommentURL=\"http://aurl.com\";Port=\"80,8080\";Discard";
Cookie cookie = new DefaultCookie("myCookie", "myValue");
CookieEncoder encoder = new CookieEncoder(true);
encoder.addCookie(cookie);
cookie.setVersion(1);
cookie.setComment("this is a Comment");
cookie.setCommentUrl("http://aurl.com");
@ -88,29 +83,15 @@ public class CookieEncoderTest {
cookie.setPath("/apathsomewhere");
cookie.setPorts(80, 8080);
cookie.setSecure(true);
String encodedCookie = encoder.encode();
String encodedCookie = ServerCookieEncoder.encode(cookie);
assertEquals(result, encodedCookie);
}
@Test
public void testEncodingMultipleServerCookies() {
CookieEncoder encoder = new CookieEncoder(true);
encoder.addCookie("a", "b");
encoder.addCookie("b", "c");
try {
encoder.encode();
fail();
} catch (IllegalStateException e) {
// Expected
}
}
@Test
public void testEncodingMultipleClientCookies() {
String c1 = "$Version=1;myCookie=myValue;$Path=\"/apathsomewhere\";$Domain=.adomainsomewhere;$Port=\"80,8080\";";
String c2 = "$Version=1;myCookie2=myValue2;$Path=\"/anotherpathsomewhere\";$Domain=.anotherdomainsomewhere;";
String c3 = "$Version=1;myCookie3=myValue3";
CookieEncoder encoder = new CookieEncoder(false);
Cookie cookie = new DefaultCookie("myCookie", "myValue");
cookie.setVersion(1);
cookie.setComment("this is a Comment");
@ -121,7 +102,6 @@ public class CookieEncoderTest {
cookie.setPath("/apathsomewhere");
cookie.setPorts(80, 8080);
cookie.setSecure(true);
encoder.addCookie(cookie);
Cookie cookie2 = new DefaultCookie("myCookie2", "myValue2");
cookie2.setVersion(1);
cookie2.setComment("this is another Comment");
@ -130,23 +110,17 @@ public class CookieEncoderTest {
cookie2.setDiscard(false);
cookie2.setPath("/anotherpathsomewhere");
cookie2.setSecure(false);
encoder.addCookie(cookie2);
Cookie cookie3 = new DefaultCookie("myCookie3", "myValue3");
cookie3.setVersion(1);
encoder.addCookie(cookie3);
String encodedCookie = encoder.encode();
String encodedCookie = ClientCookieEncoder.encode(cookie, cookie2, cookie3);
assertEquals(c1 + c2 + c3, encodedCookie);
}
@Test
public void testEncodingWithNoCookies() {
CookieEncoder encoderForServer = new CookieEncoder(true);
String encodedCookie1 = encoderForServer.encode();
CookieEncoder encoderForClient = new CookieEncoder(false);
String encodedCookie2 = encoderForClient.encode();
String encodedCookie1 = ClientCookieEncoder.encode();
List<String> encodedCookie2 = ServerCookieEncoder.encode();
assertNotNull(encodedCookie1);
assertNotNull(encodedCookie2);
}
}

View File

@ -19,7 +19,8 @@ import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.socket.nio.NioEventLoop;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.http.CookieEncoder;
import io.netty.handler.codec.http.ClientCookieEncoder;
import io.netty.handler.codec.http.DefaultCookie;
import io.netty.handler.codec.http.DefaultHttpRequest;
import io.netty.handler.codec.http.HttpHeaders;
import io.netty.handler.codec.http.HttpMethod;
@ -79,10 +80,11 @@ public class HttpSnoopClient {
request.setHeader(HttpHeaders.Names.ACCEPT_ENCODING, HttpHeaders.Values.GZIP);
// Set some example cookies.
CookieEncoder httpCookieEncoder = new CookieEncoder(false);
httpCookieEncoder.addCookie("my-cookie", "foo");
httpCookieEncoder.addCookie("another-cookie", "bar");
request.setHeader(HttpHeaders.Names.COOKIE, httpCookieEncoder.encode());
request.setHeader(
HttpHeaders.Names.COOKIE,
ClientCookieEncoder.encode(
new DefaultCookie("my-cookie", "foo"),
new DefaultCookie("another-cookie", "bar")));
// Send the HTTP request.
ch.write(request);

View File

@ -27,7 +27,6 @@ import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundMessageHandlerAdapter;
import io.netty.handler.codec.http.Cookie;
import io.netty.handler.codec.http.CookieDecoder;
import io.netty.handler.codec.http.CookieEncoder;
import io.netty.handler.codec.http.DefaultHttpResponse;
import io.netty.handler.codec.http.HttpChunk;
import io.netty.handler.codec.http.HttpChunkTrailer;
@ -35,6 +34,7 @@ import io.netty.handler.codec.http.HttpHeaders;
import io.netty.handler.codec.http.HttpRequest;
import io.netty.handler.codec.http.HttpResponse;
import io.netty.handler.codec.http.QueryStringDecoder;
import io.netty.handler.codec.http.ServerCookieEncoder;
import io.netty.util.CharsetUtil;
import java.util.List;
@ -137,23 +137,17 @@ public class HttpSnoopServerHandler extends ChannelInboundMessageHandlerAdapter<
// Encode the cookie.
String cookieString = request.getHeader(COOKIE);
if (cookieString != null) {
CookieDecoder cookieDecoder = new CookieDecoder();
Set<Cookie> cookies = cookieDecoder.decode(cookieString);
Set<Cookie> cookies = CookieDecoder.decode(cookieString);
if (!cookies.isEmpty()) {
// Reset the cookies if necessary.
CookieEncoder cookieEncoder = new CookieEncoder(true);
for (Cookie cookie: cookies) {
cookieEncoder.addCookie(cookie);
response.addHeader(SET_COOKIE, cookieEncoder.encode());
response.addHeader(SET_COOKIE, ServerCookieEncoder.encode(cookie));
}
}
} else {
// Browser sent no cookie. Add some.
CookieEncoder cookieEncoder = new CookieEncoder(true);
cookieEncoder.addCookie("key1", "value1");
response.addHeader(SET_COOKIE, cookieEncoder.encode());
cookieEncoder.addCookie("key2", "value2");
response.addHeader(SET_COOKIE, cookieEncoder.encode());
response.addHeader(SET_COOKIE, ServerCookieEncoder.encode("key1", "value1"));
response.addHeader(SET_COOKIE, ServerCookieEncoder.encode("key2", "value2"));
}
// Write the response.