Make CookieEncoder and CookieDecoder stateless
- Also: CookieEncoder is split into ServerCookieEncoder and ClientCookieEncoder
This commit is contained in:
parent
1be9bbf62c
commit
6d2f6d697d
@ -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
|
||||||
|
}
|
||||||
|
}
|
@ -32,12 +32,13 @@ import java.util.TreeSet;
|
|||||||
* Set<{@link Cookie}> cookies = new {@link CookieDecoder}().decode(value);
|
* Set<{@link Cookie}> cookies = new {@link CookieDecoder}().decode(value);
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* @see CookieEncoder
|
* @see ClientCookieEncoder
|
||||||
|
* @see ServerCookieEncoder
|
||||||
*
|
*
|
||||||
* @apiviz.stereotype utility
|
* @apiviz.stereotype utility
|
||||||
* @apiviz.has io.netty.handler.codec.http.Cookie oneway - - decodes
|
* @apiviz.has io.netty.handler.codec.http.Cookie oneway - - decodes
|
||||||
*/
|
*/
|
||||||
public class CookieDecoder {
|
public final class CookieDecoder {
|
||||||
|
|
||||||
private static final String COMMA = ",";
|
private static final String COMMA = ",";
|
||||||
|
|
||||||
@ -46,7 +47,7 @@ public class CookieDecoder {
|
|||||||
*
|
*
|
||||||
* @return the decoded {@link Cookie}s
|
* @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> names = new ArrayList<String>(8);
|
||||||
List<String> values = new ArrayList<String>(8);
|
List<String> values = new ArrayList<String>(8);
|
||||||
extractKeyValuePairs(header, names, values);
|
extractKeyValuePairs(header, names, values);
|
||||||
@ -289,4 +290,8 @@ public class CookieDecoder {
|
|||||||
values.add(value);
|
values.add(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private CookieDecoder() {
|
||||||
|
// Unused
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
@ -23,10 +23,12 @@ package io.netty.handler.codec.http;
|
|||||||
* <p>
|
* <p>
|
||||||
* Unlike the Servlet API, a query string is constructed and decomposed by
|
* Unlike the Servlet API, a query string is constructed and decomposed by
|
||||||
* {@link QueryStringEncoder} and {@link QueryStringDecoder}. {@link Cookie}
|
* {@link QueryStringEncoder} and {@link QueryStringDecoder}. {@link Cookie}
|
||||||
* support is also provided separately via {@link CookieEncoder} and
|
* support is also provided separately via {@link CookieDecoder}, {@link ClientCookieEncoder},
|
||||||
* {@link CookieDecoder}.
|
* and {@link @ServerCookieEncoder}.
|
||||||
|
*
|
||||||
* @see HttpResponse
|
* @see HttpResponse
|
||||||
* @see CookieEncoder
|
* @see ClientCookieEncoder
|
||||||
|
* @see ServerCookieEncoder
|
||||||
* @see CookieDecoder
|
* @see CookieDecoder
|
||||||
*/
|
*/
|
||||||
public interface HttpRequest extends HttpMessage {
|
public interface HttpRequest extends HttpMessage {
|
||||||
|
@ -21,11 +21,13 @@ package io.netty.handler.codec.http;
|
|||||||
*
|
*
|
||||||
* <h3>Accessing Cookie</h3>
|
* <h3>Accessing Cookie</h3>
|
||||||
* <p>
|
* <p>
|
||||||
* Unlike the Servlet API, {@link Cookie} support is provided separately via
|
* Unlike the Servlet API, {@link Cookie} support is provided separately via {@link CookieDecoder},
|
||||||
* {@link CookieEncoder} and {@link CookieDecoder}.
|
* {@link ClientCookieEncoder}, and {@link ServerCookieEncoder}.
|
||||||
|
*
|
||||||
* @see HttpRequest
|
* @see HttpRequest
|
||||||
* @see CookieEncoder
|
|
||||||
* @see CookieDecoder
|
* @see CookieDecoder
|
||||||
|
* @see ClientCookieEncoder
|
||||||
|
* @see ServerCookieEncoder
|
||||||
*/
|
*/
|
||||||
public interface HttpResponse extends HttpMessage {
|
public interface HttpResponse extends HttpMessage {
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
@ -31,8 +31,7 @@ public class CookieDecoderTest {
|
|||||||
String cookieString = "myCookie=myValue;expires=XXX;path=/apathsomewhere;domain=.adomainsomewhere;secure;";
|
String cookieString = "myCookie=myValue;expires=XXX;path=/apathsomewhere;domain=.adomainsomewhere;secure;";
|
||||||
cookieString = cookieString.replace("XXX", new HttpHeaderDateFormat().format(new Date(System.currentTimeMillis() + 50000)));
|
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());
|
assertEquals(1, cookies.size());
|
||||||
Cookie cookie = cookies.iterator().next();
|
Cookie cookie = cookies.iterator().next();
|
||||||
assertNotNull(cookie);
|
assertNotNull(cookie);
|
||||||
@ -62,8 +61,7 @@ public class CookieDecoderTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testDecodingSingleCookieV0ExtraParamsIgnored() {
|
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;";
|
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());
|
assertEquals(1, cookies.size());
|
||||||
Cookie cookie = cookies.iterator().next();
|
Cookie cookie = cookies.iterator().next();
|
||||||
assertNotNull(cookie);
|
assertNotNull(cookie);
|
||||||
@ -81,8 +79,7 @@ public class CookieDecoderTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testDecodingSingleCookieV1() {
|
public void testDecodingSingleCookieV1() {
|
||||||
String cookieString = "myCookie=myValue;max-age=50;path=/apathsomewhere;domain=.adomainsomewhere;secure;comment=this is a comment;version=1;";
|
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());
|
assertEquals(1, cookies.size());
|
||||||
Cookie cookie = cookies.iterator().next();
|
Cookie cookie = cookies.iterator().next();
|
||||||
assertEquals("myValue", cookie.getValue());
|
assertEquals("myValue", cookie.getValue());
|
||||||
@ -101,8 +98,7 @@ public class CookieDecoderTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testDecodingSingleCookieV1ExtraParamsIgnored() {
|
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;";
|
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());
|
assertEquals(1, cookies.size());
|
||||||
Cookie cookie = cookies.iterator().next();
|
Cookie cookie = cookies.iterator().next();
|
||||||
assertNotNull(cookie);
|
assertNotNull(cookie);
|
||||||
@ -120,8 +116,7 @@ public class CookieDecoderTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testDecodingSingleCookieV2() {
|
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;";
|
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());
|
assertEquals(1, cookies.size());
|
||||||
Cookie cookie = cookies.iterator().next();
|
Cookie cookie = cookies.iterator().next();
|
||||||
assertNotNull(cookie);
|
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 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 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;";
|
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());
|
assertEquals(3, cookies.size());
|
||||||
Iterator<Cookie> it = cookies.iterator();
|
Iterator<Cookie> it = cookies.iterator();
|
||||||
Cookie cookie = it.next();
|
Cookie cookie = it.next();
|
||||||
@ -196,7 +190,7 @@ public class CookieDecoderTest {
|
|||||||
"Part_Number=\"Riding_Rocket_0023\"; $Path=\"/acme/ammo\"; " +
|
"Part_Number=\"Riding_Rocket_0023\"; $Path=\"/acme/ammo\"; " +
|
||||||
"Part_Number=\"Rocket_Launcher_0001\"; $Path=\"/acme\"";
|
"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();
|
Iterator<Cookie> it = cookies.iterator();
|
||||||
Cookie c;
|
Cookie c;
|
||||||
|
|
||||||
@ -231,7 +225,7 @@ public class CookieDecoderTest {
|
|||||||
"$Version=\"1\"; session_id=\"1234\", " +
|
"$Version=\"1\"; session_id=\"1234\", " +
|
||||||
"$Version=\"1\"; session_id=\"1111\"; $Domain=\".cracker.edu\"";
|
"$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();
|
Iterator<Cookie> it = cookies.iterator();
|
||||||
Cookie c;
|
Cookie c;
|
||||||
|
|
||||||
@ -275,7 +269,7 @@ public class CookieDecoderTest {
|
|||||||
"h=\"';,\\x\"";
|
"h=\"';,\\x\"";
|
||||||
|
|
||||||
|
|
||||||
Set<Cookie> cookies = new CookieDecoder().decode(source);
|
Set<Cookie> cookies = CookieDecoder.decode(source);
|
||||||
Iterator<Cookie> it = cookies.iterator();
|
Iterator<Cookie> it = cookies.iterator();
|
||||||
Cookie c;
|
Cookie c;
|
||||||
|
|
||||||
@ -322,7 +316,7 @@ public class CookieDecoderTest {
|
|||||||
"__utma=48461872.1094088325.1258140131.1258140131.1258140131.1; " +
|
"__utma=48461872.1094088325.1258140131.1258140131.1258140131.1; " +
|
||||||
"__utmb=48461872.13.10.1258140131; __utmc=48461872; " +
|
"__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";
|
"__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();
|
Iterator<Cookie> it = cookies.iterator();
|
||||||
Cookie c;
|
Cookie c;
|
||||||
|
|
||||||
@ -361,7 +355,7 @@ public class CookieDecoderTest {
|
|||||||
|
|
||||||
String source = "Format=EU; expires=Fri, 31-Dec-9999 23:59:59 GMT; path=/";
|
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();
|
Cookie c = cookies.iterator().next();
|
||||||
assertTrue(Math.abs(expectedMaxAge - c.getMaxAge()) < 2);
|
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;" +
|
String source = "UserCookie=timeZoneName=(GMT+04:00) Moscow, St. Petersburg, Volgograd&promocode=®ion=BE;" +
|
||||||
" expires=Sat, 01-Dec-2012 10:53:31 GMT; path=/";
|
" 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();
|
Cookie c = cookies.iterator().next();
|
||||||
assertEquals("timeZoneName=(GMT+04:00) Moscow, St. Petersburg, Volgograd&promocode=®ion=BE", c.getValue());
|
assertEquals("timeZoneName=(GMT+04:00) Moscow, St. Petersburg, Volgograd&promocode=®ion=BE", c.getValue());
|
||||||
@ -381,7 +375,7 @@ public class CookieDecoderTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testDecodingWeirdNames1() {
|
public void testDecodingWeirdNames1() {
|
||||||
String src = "path=; expires=Mon, 01-Jan-1990 00:00:00 GMT; path=/; domain=.www.google.com";
|
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();
|
Cookie c = cookies.iterator().next();
|
||||||
assertEquals("path", c.getName());
|
assertEquals("path", c.getName());
|
||||||
assertEquals("", c.getValue());
|
assertEquals("", c.getValue());
|
||||||
@ -391,7 +385,7 @@ public class CookieDecoderTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testDecodingWeirdNames2() {
|
public void testDecodingWeirdNames2() {
|
||||||
String src = "HTTPOnly=";
|
String src = "HTTPOnly=";
|
||||||
Set<Cookie> cookies = new CookieDecoder().decode(src);
|
Set<Cookie> cookies = CookieDecoder.decode(src);
|
||||||
Cookie c = cookies.iterator().next();
|
Cookie c = cookies.iterator().next();
|
||||||
assertEquals("HTTPOnly", c.getName());
|
assertEquals("HTTPOnly", c.getName());
|
||||||
assertEquals("", c.getValue());
|
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!$?mi!!!!'=KqtH!$?mx!!!!'=KqtH!$D7]!!!!#=J_#p!$D@T!!!!#=J_#p!$V<g!!!!" +
|
||||||
"'=KqtH";
|
"'=KqtH";
|
||||||
|
|
||||||
Set<Cookie> cookies = new CookieDecoder().decode("bh=\"" + longValue + "\";");
|
Set<Cookie> cookies = CookieDecoder.decode("bh=\"" + longValue + "\";");
|
||||||
assertEquals(1, cookies.size());
|
assertEquals(1, cookies.size());
|
||||||
Cookie c = cookies.iterator().next();
|
Cookie c = cookies.iterator().next();
|
||||||
assertEquals("bh", c.getName());
|
assertEquals("bh", c.getName());
|
||||||
|
@ -19,6 +19,7 @@ import static org.junit.Assert.*;
|
|||||||
|
|
||||||
import java.text.DateFormat;
|
import java.text.DateFormat;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
@ -28,8 +29,6 @@ public class CookieEncoderTest {
|
|||||||
String result = "myCookie=myValue;Expires=XXX;Path=/apathsomewhere;Domain=.adomainsomewhere;Secure";
|
String result = "myCookie=myValue;Expires=XXX;Path=/apathsomewhere;Domain=.adomainsomewhere;Secure";
|
||||||
DateFormat df = new HttpHeaderDateFormat();
|
DateFormat df = new HttpHeaderDateFormat();
|
||||||
Cookie cookie = new DefaultCookie("myCookie", "myValue");
|
Cookie cookie = new DefaultCookie("myCookie", "myValue");
|
||||||
CookieEncoder encoder = new CookieEncoder(true);
|
|
||||||
encoder.addCookie(cookie);
|
|
||||||
cookie.setComment("this is a Comment");
|
cookie.setComment("this is a Comment");
|
||||||
cookie.setCommentUrl("http://aurl.com");
|
cookie.setCommentUrl("http://aurl.com");
|
||||||
cookie.setDomain(".adomainsomewhere");
|
cookie.setDomain(".adomainsomewhere");
|
||||||
@ -39,7 +38,7 @@ public class CookieEncoderTest {
|
|||||||
cookie.setPorts(80, 8080);
|
cookie.setPorts(80, 8080);
|
||||||
cookie.setSecure(true);
|
cookie.setSecure(true);
|
||||||
|
|
||||||
String encodedCookie = encoder.encode();
|
String encodedCookie = ServerCookieEncoder.encode(cookie);
|
||||||
|
|
||||||
long currentTime = System.currentTimeMillis();
|
long currentTime = System.currentTimeMillis();
|
||||||
boolean fail = true;
|
boolean fail = true;
|
||||||
@ -61,15 +60,13 @@ public class CookieEncoderTest {
|
|||||||
public void testEncodingSingleCookieV1() {
|
public void testEncodingSingleCookieV1() {
|
||||||
String result = "myCookie=myValue;Max-Age=50;Path=\"/apathsomewhere\";Domain=.adomainsomewhere;Secure;Comment=\"this is a Comment\";Version=1";
|
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");
|
Cookie cookie = new DefaultCookie("myCookie", "myValue");
|
||||||
CookieEncoder encoder = new CookieEncoder(true);
|
|
||||||
encoder.addCookie(cookie);
|
|
||||||
cookie.setVersion(1);
|
cookie.setVersion(1);
|
||||||
cookie.setComment("this is a Comment");
|
cookie.setComment("this is a Comment");
|
||||||
cookie.setDomain(".adomainsomewhere");
|
cookie.setDomain(".adomainsomewhere");
|
||||||
cookie.setMaxAge(50);
|
cookie.setMaxAge(50);
|
||||||
cookie.setPath("/apathsomewhere");
|
cookie.setPath("/apathsomewhere");
|
||||||
cookie.setSecure(true);
|
cookie.setSecure(true);
|
||||||
String encodedCookie = encoder.encode();
|
String encodedCookie = ServerCookieEncoder.encode(cookie);
|
||||||
assertEquals(result, encodedCookie);
|
assertEquals(result, encodedCookie);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,8 +74,6 @@ public class CookieEncoderTest {
|
|||||||
public void testEncodingSingleCookieV2() {
|
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";
|
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");
|
Cookie cookie = new DefaultCookie("myCookie", "myValue");
|
||||||
CookieEncoder encoder = new CookieEncoder(true);
|
|
||||||
encoder.addCookie(cookie);
|
|
||||||
cookie.setVersion(1);
|
cookie.setVersion(1);
|
||||||
cookie.setComment("this is a Comment");
|
cookie.setComment("this is a Comment");
|
||||||
cookie.setCommentUrl("http://aurl.com");
|
cookie.setCommentUrl("http://aurl.com");
|
||||||
@ -88,29 +83,15 @@ public class CookieEncoderTest {
|
|||||||
cookie.setPath("/apathsomewhere");
|
cookie.setPath("/apathsomewhere");
|
||||||
cookie.setPorts(80, 8080);
|
cookie.setPorts(80, 8080);
|
||||||
cookie.setSecure(true);
|
cookie.setSecure(true);
|
||||||
String encodedCookie = encoder.encode();
|
String encodedCookie = ServerCookieEncoder.encode(cookie);
|
||||||
assertEquals(result, encodedCookie);
|
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
|
@Test
|
||||||
public void testEncodingMultipleClientCookies() {
|
public void testEncodingMultipleClientCookies() {
|
||||||
String c1 = "$Version=1;myCookie=myValue;$Path=\"/apathsomewhere\";$Domain=.adomainsomewhere;$Port=\"80,8080\";";
|
String c1 = "$Version=1;myCookie=myValue;$Path=\"/apathsomewhere\";$Domain=.adomainsomewhere;$Port=\"80,8080\";";
|
||||||
String c2 = "$Version=1;myCookie2=myValue2;$Path=\"/anotherpathsomewhere\";$Domain=.anotherdomainsomewhere;";
|
String c2 = "$Version=1;myCookie2=myValue2;$Path=\"/anotherpathsomewhere\";$Domain=.anotherdomainsomewhere;";
|
||||||
String c3 = "$Version=1;myCookie3=myValue3";
|
String c3 = "$Version=1;myCookie3=myValue3";
|
||||||
CookieEncoder encoder = new CookieEncoder(false);
|
|
||||||
Cookie cookie = new DefaultCookie("myCookie", "myValue");
|
Cookie cookie = new DefaultCookie("myCookie", "myValue");
|
||||||
cookie.setVersion(1);
|
cookie.setVersion(1);
|
||||||
cookie.setComment("this is a Comment");
|
cookie.setComment("this is a Comment");
|
||||||
@ -121,7 +102,6 @@ public class CookieEncoderTest {
|
|||||||
cookie.setPath("/apathsomewhere");
|
cookie.setPath("/apathsomewhere");
|
||||||
cookie.setPorts(80, 8080);
|
cookie.setPorts(80, 8080);
|
||||||
cookie.setSecure(true);
|
cookie.setSecure(true);
|
||||||
encoder.addCookie(cookie);
|
|
||||||
Cookie cookie2 = new DefaultCookie("myCookie2", "myValue2");
|
Cookie cookie2 = new DefaultCookie("myCookie2", "myValue2");
|
||||||
cookie2.setVersion(1);
|
cookie2.setVersion(1);
|
||||||
cookie2.setComment("this is another Comment");
|
cookie2.setComment("this is another Comment");
|
||||||
@ -130,23 +110,17 @@ public class CookieEncoderTest {
|
|||||||
cookie2.setDiscard(false);
|
cookie2.setDiscard(false);
|
||||||
cookie2.setPath("/anotherpathsomewhere");
|
cookie2.setPath("/anotherpathsomewhere");
|
||||||
cookie2.setSecure(false);
|
cookie2.setSecure(false);
|
||||||
encoder.addCookie(cookie2);
|
|
||||||
Cookie cookie3 = new DefaultCookie("myCookie3", "myValue3");
|
Cookie cookie3 = new DefaultCookie("myCookie3", "myValue3");
|
||||||
cookie3.setVersion(1);
|
cookie3.setVersion(1);
|
||||||
encoder.addCookie(cookie3);
|
String encodedCookie = ClientCookieEncoder.encode(cookie, cookie2, cookie3);
|
||||||
String encodedCookie = encoder.encode();
|
|
||||||
assertEquals(c1 + c2 + c3, encodedCookie);
|
assertEquals(c1 + c2 + c3, encodedCookie);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testEncodingWithNoCookies() {
|
public void testEncodingWithNoCookies() {
|
||||||
CookieEncoder encoderForServer = new CookieEncoder(true);
|
String encodedCookie1 = ClientCookieEncoder.encode();
|
||||||
String encodedCookie1 = encoderForServer.encode();
|
List<String> encodedCookie2 = ServerCookieEncoder.encode();
|
||||||
CookieEncoder encoderForClient = new CookieEncoder(false);
|
assertNotNull(encodedCookie1);
|
||||||
String encodedCookie2 = encoderForClient.encode();
|
assertNotNull(encodedCookie2);
|
||||||
assertNotNull(encodedCookie1);
|
|
||||||
assertNotNull(encodedCookie2);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,8 @@ import io.netty.bootstrap.Bootstrap;
|
|||||||
import io.netty.channel.Channel;
|
import io.netty.channel.Channel;
|
||||||
import io.netty.channel.socket.nio.NioEventLoop;
|
import io.netty.channel.socket.nio.NioEventLoop;
|
||||||
import io.netty.channel.socket.nio.NioSocketChannel;
|
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.DefaultHttpRequest;
|
||||||
import io.netty.handler.codec.http.HttpHeaders;
|
import io.netty.handler.codec.http.HttpHeaders;
|
||||||
import io.netty.handler.codec.http.HttpMethod;
|
import io.netty.handler.codec.http.HttpMethod;
|
||||||
@ -79,10 +80,11 @@ public class HttpSnoopClient {
|
|||||||
request.setHeader(HttpHeaders.Names.ACCEPT_ENCODING, HttpHeaders.Values.GZIP);
|
request.setHeader(HttpHeaders.Names.ACCEPT_ENCODING, HttpHeaders.Values.GZIP);
|
||||||
|
|
||||||
// Set some example cookies.
|
// Set some example cookies.
|
||||||
CookieEncoder httpCookieEncoder = new CookieEncoder(false);
|
request.setHeader(
|
||||||
httpCookieEncoder.addCookie("my-cookie", "foo");
|
HttpHeaders.Names.COOKIE,
|
||||||
httpCookieEncoder.addCookie("another-cookie", "bar");
|
ClientCookieEncoder.encode(
|
||||||
request.setHeader(HttpHeaders.Names.COOKIE, httpCookieEncoder.encode());
|
new DefaultCookie("my-cookie", "foo"),
|
||||||
|
new DefaultCookie("another-cookie", "bar")));
|
||||||
|
|
||||||
// Send the HTTP request.
|
// Send the HTTP request.
|
||||||
ch.write(request);
|
ch.write(request);
|
||||||
|
@ -27,7 +27,6 @@ import io.netty.channel.ChannelHandlerContext;
|
|||||||
import io.netty.channel.ChannelInboundMessageHandlerAdapter;
|
import io.netty.channel.ChannelInboundMessageHandlerAdapter;
|
||||||
import io.netty.handler.codec.http.Cookie;
|
import io.netty.handler.codec.http.Cookie;
|
||||||
import io.netty.handler.codec.http.CookieDecoder;
|
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.DefaultHttpResponse;
|
||||||
import io.netty.handler.codec.http.HttpChunk;
|
import io.netty.handler.codec.http.HttpChunk;
|
||||||
import io.netty.handler.codec.http.HttpChunkTrailer;
|
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.HttpRequest;
|
||||||
import io.netty.handler.codec.http.HttpResponse;
|
import io.netty.handler.codec.http.HttpResponse;
|
||||||
import io.netty.handler.codec.http.QueryStringDecoder;
|
import io.netty.handler.codec.http.QueryStringDecoder;
|
||||||
|
import io.netty.handler.codec.http.ServerCookieEncoder;
|
||||||
import io.netty.util.CharsetUtil;
|
import io.netty.util.CharsetUtil;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -137,23 +137,17 @@ public class HttpSnoopServerHandler extends ChannelInboundMessageHandlerAdapter<
|
|||||||
// Encode the cookie.
|
// Encode the cookie.
|
||||||
String cookieString = request.getHeader(COOKIE);
|
String cookieString = request.getHeader(COOKIE);
|
||||||
if (cookieString != null) {
|
if (cookieString != null) {
|
||||||
CookieDecoder cookieDecoder = new CookieDecoder();
|
Set<Cookie> cookies = CookieDecoder.decode(cookieString);
|
||||||
Set<Cookie> cookies = cookieDecoder.decode(cookieString);
|
|
||||||
if (!cookies.isEmpty()) {
|
if (!cookies.isEmpty()) {
|
||||||
// Reset the cookies if necessary.
|
// Reset the cookies if necessary.
|
||||||
CookieEncoder cookieEncoder = new CookieEncoder(true);
|
for (Cookie cookie: cookies) {
|
||||||
for (Cookie cookie : cookies) {
|
response.addHeader(SET_COOKIE, ServerCookieEncoder.encode(cookie));
|
||||||
cookieEncoder.addCookie(cookie);
|
|
||||||
response.addHeader(SET_COOKIE, cookieEncoder.encode());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Browser sent no cookie. Add some.
|
// Browser sent no cookie. Add some.
|
||||||
CookieEncoder cookieEncoder = new CookieEncoder(true);
|
response.addHeader(SET_COOKIE, ServerCookieEncoder.encode("key1", "value1"));
|
||||||
cookieEncoder.addCookie("key1", "value1");
|
response.addHeader(SET_COOKIE, ServerCookieEncoder.encode("key2", "value2"));
|
||||||
response.addHeader(SET_COOKIE, cookieEncoder.encode());
|
|
||||||
cookieEncoder.addCookie("key2", "value2");
|
|
||||||
response.addHeader(SET_COOKIE, cookieEncoder.encode());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write the response.
|
// Write the response.
|
||||||
|
Loading…
Reference in New Issue
Block a user