diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/ClientCookieEncoder.java b/codec-http/src/main/java/io/netty/handler/codec/http/ClientCookieEncoder.java new file mode 100644 index 0000000000..4dafb2a9c3 --- /dev/null +++ b/codec-http/src/main/java/io/netty/handler/codec/http/ClientCookieEncoder.java @@ -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. + *
+ * // Example
+ * {@link HttpRequest} req = ...;
+ * res.setHeader("Cookie", {@link ClientCookieEncoder}.encode("JSESSIONID", "1234"));
+ * 
+ * + * @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 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 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 + } +} diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/CookieDecoder.java b/codec-http/src/main/java/io/netty/handler/codec/http/CookieDecoder.java index 1c1f4c4c47..2592c010ea 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/CookieDecoder.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/CookieDecoder.java @@ -32,12 +32,13 @@ import java.util.TreeSet; * Set<{@link Cookie}> cookies = new {@link CookieDecoder}().decode(value); * * - * @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 decode(String header) { + public static Set decode(String header) { List names = new ArrayList(8); List values = new ArrayList(8); extractKeyValuePairs(header, names, values); @@ -289,4 +290,8 @@ public class CookieDecoder { values.add(value); } } + + private CookieDecoder() { + // Unused + } } diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/CookieEncoder.java b/codec-http/src/main/java/io/netty/handler/codec/http/CookieEncoder.java deleted file mode 100644 index a1acd5a4a6..0000000000 --- a/codec-http/src/main/java/io/netty/handler/codec/http/CookieEncoder.java +++ /dev/null @@ -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. - *

- * 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. - *

- * // 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());
- * 
- * - * @see CookieDecoder - * - * @apiviz.stereotype utility - * @apiviz.has io.netty.handler.codec.http.Cookie oneway - - encodes - */ -public class CookieEncoder { - - private final Set cookies = new TreeSet(); - 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. - * - * Be aware that calling this method will clear the {@link Cookie}s you added to - * this encoder. - */ - 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); - } -} diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/CookieEncoderUtil.java b/codec-http/src/main/java/io/netty/handler/codec/http/CookieEncoderUtil.java new file mode 100644 index 0000000000..8891dee841 --- /dev/null +++ b/codec-http/src/main/java/io/netty/handler/codec/http/CookieEncoderUtil.java @@ -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 + } +} diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/HttpRequest.java b/codec-http/src/main/java/io/netty/handler/codec/http/HttpRequest.java index c3f25c0e82..a6cfe6a1b3 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/HttpRequest.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/HttpRequest.java @@ -23,10 +23,12 @@ package io.netty.handler.codec.http; *

* 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 { diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/HttpResponse.java b/codec-http/src/main/java/io/netty/handler/codec/http/HttpResponse.java index 8f664d83d0..0eb4023ea4 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/HttpResponse.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/HttpResponse.java @@ -21,11 +21,13 @@ package io.netty.handler.codec.http; * *

Accessing Cookie

*

- * 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 { diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/ServerCookieEncoder.java b/codec-http/src/main/java/io/netty/handler/codec/http/ServerCookieEncoder.java new file mode 100644 index 0000000000..6caa7f1e31 --- /dev/null +++ b/codec-http/src/main/java/io/netty/handler/codec/http/ServerCookieEncoder.java @@ -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. + *

+ * // Example
+ * {@link HttpRequest} req = ...;
+ * res.setHeader("Set-Cookie", {@link ServerCookieEncoder}.encode("JSESSIONID", "1234"));
+ * 
+ * + * @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 encode(Cookie... cookies) { + if (cookies == null) { + throw new NullPointerException("cookies"); + } + + List encoded = new ArrayList(cookies.length); + for (Cookie c: cookies) { + if (c == null) { + break; + } + encoded.add(encode(c)); + } + return encoded; + } + + public static List encode(Collection cookies) { + if (cookies == null) { + throw new NullPointerException("cookies"); + } + + List encoded = new ArrayList(cookies.size()); + for (Cookie c: cookies) { + if (c == null) { + break; + } + encoded.add(encode(c)); + } + return encoded; + } + + public static List encode(Iterable cookies) { + if (cookies == null) { + throw new NullPointerException("cookies"); + } + + List encoded = new ArrayList(); + for (Cookie c: cookies) { + if (c == null) { + break; + } + encoded.add(encode(c)); + } + return encoded; + } + + private ServerCookieEncoder() { + // Unused + } +} diff --git a/codec-http/src/test/java/io/netty/handler/codec/http/CookieDecoderTest.java b/codec-http/src/test/java/io/netty/handler/codec/http/CookieDecoderTest.java index 11982f1199..2055e4994b 100644 --- a/codec-http/src/test/java/io/netty/handler/codec/http/CookieDecoderTest.java +++ b/codec-http/src/test/java/io/netty/handler/codec/http/CookieDecoderTest.java @@ -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 cookies = cookieDecoder.decode(cookieString); + Set 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 cookies = cookieDecoder.decode(cookieString); + Set 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 cookies = cookieDecoder.decode(cookieString); + Set 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 cookies = cookieDecoder.decode(cookieString); + Set 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 cookies = cookieDecoder.decode(cookieString); + Set 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 cookies = decoder.decode(c1 + c2 + c3); + Set cookies = CookieDecoder.decode(c1 + c2 + c3); assertEquals(3, cookies.size()); Iterator 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 cookies = new CookieDecoder().decode(source); + Set cookies = CookieDecoder.decode(source); Iterator 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 cookies = new CookieDecoder().decode(source); + Set cookies = CookieDecoder.decode(source); Iterator it = cookies.iterator(); Cookie c; @@ -275,7 +269,7 @@ public class CookieDecoderTest { "h=\"';,\\x\""; - Set cookies = new CookieDecoder().decode(source); + Set cookies = CookieDecoder.decode(source); Iterator 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 cookies = new CookieDecoder().decode(source); + Set cookies = CookieDecoder.decode(source); Iterator 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 cookies = new CookieDecoder().decode(source); + Set 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=®ion=BE;" + " expires=Sat, 01-Dec-2012 10:53:31 GMT; path=/"; - Set cookies = new CookieDecoder().decode(source); + Set cookies = CookieDecoder.decode(source); Cookie c = cookies.iterator().next(); assertEquals("timeZoneName=(GMT+04:00) Moscow, St. Petersburg, Volgograd&promocode=®ion=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 cookies = new CookieDecoder().decode(src); + Set 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 cookies = new CookieDecoder().decode(src); + Set 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 cookies = new CookieDecoder().decode("bh=\"" + longValue + "\";"); + Set cookies = CookieDecoder.decode("bh=\"" + longValue + "\";"); assertEquals(1, cookies.size()); Cookie c = cookies.iterator().next(); assertEquals("bh", c.getName()); diff --git a/codec-http/src/test/java/io/netty/handler/codec/http/CookieEncoderTest.java b/codec-http/src/test/java/io/netty/handler/codec/http/CookieEncoderTest.java index 5887d1d979..ff701c1235 100644 --- a/codec-http/src/test/java/io/netty/handler/codec/http/CookieEncoderTest.java +++ b/codec-http/src/test/java/io/netty/handler/codec/http/CookieEncoderTest.java @@ -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(); - assertNotNull(encodedCookie1); - assertNotNull(encodedCookie2); - + String encodedCookie1 = ClientCookieEncoder.encode(); + List encodedCookie2 = ServerCookieEncoder.encode(); + assertNotNull(encodedCookie1); + assertNotNull(encodedCookie2); } - } diff --git a/example/src/main/java/io/netty/example/http/snoop/HttpSnoopClient.java b/example/src/main/java/io/netty/example/http/snoop/HttpSnoopClient.java index 0ce85e67fe..89918eeb7a 100644 --- a/example/src/main/java/io/netty/example/http/snoop/HttpSnoopClient.java +++ b/example/src/main/java/io/netty/example/http/snoop/HttpSnoopClient.java @@ -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); diff --git a/example/src/main/java/io/netty/example/http/snoop/HttpSnoopServerHandler.java b/example/src/main/java/io/netty/example/http/snoop/HttpSnoopServerHandler.java index cb08c3e0bc..2d99d18f95 100644 --- a/example/src/main/java/io/netty/example/http/snoop/HttpSnoopServerHandler.java +++ b/example/src/main/java/io/netty/example/http/snoop/HttpSnoopServerHandler.java @@ -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 cookies = cookieDecoder.decode(cookieString); + Set 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()); + for (Cookie cookie: cookies) { + 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.