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 index 178dbdb64f..1f840e00af 100644 --- 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 @@ -42,7 +42,7 @@ public final class ClientCookieEncoder { throw new NullPointerException("cookie"); } - StringBuilder buf = new StringBuilder(); + StringBuilder buf = new StringBuilder(estimateClientLength(cookie)); encode(buf, cookie); return stripTrailingSeparator(buf); } @@ -52,7 +52,16 @@ public final class ClientCookieEncoder { throw new NullPointerException("cookies"); } - StringBuilder buf = new StringBuilder(); + int initialCapacity = 0; + for (Cookie c: cookies) { + if (c == null) { + break; + } + + initialCapacity += estimateClientLength(c); + } + + StringBuilder buf = new StringBuilder(initialCapacity); for (Cookie c: cookies) { if (c == null) { break; @@ -68,7 +77,16 @@ public final class ClientCookieEncoder { throw new NullPointerException("cookies"); } - StringBuilder buf = new StringBuilder(); + int initialCapacity = 0; + for (Cookie c: cookies) { + if (c == null) { + break; + } + + initialCapacity += estimateClientLength(c); + } + + StringBuilder buf = new StringBuilder(initialCapacity); for (Cookie c: cookies) { if (c == null) { break; 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 index 66e24a9d34..c57e00caa7 100644 --- 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 @@ -25,6 +25,77 @@ final class CookieEncoderUtil { return buf.toString(); } + static int estimateClientLength(Cookie c) { + int estimate = estimateLength(c.getName(), c.getValue()); + + if (c.getPath() != null) { + estimate += estimateLength(CookieHeaderNames.PATH, c.getPath()); + } + + if (c.getDomain() != null) { + estimate += estimateLength(CookieHeaderNames.DOMAIN, c.getDomain()); + } + + if (c.getVersion() > 0) { + estimate += 12; // '$Version=N; ' + int numPorts = c.getPorts().size(); + if (numPorts > 0) { + estimate += 10; // '$Port=""; ' + estimate += numPorts * 4; + } + } + + return estimate; + } + + static int estimateServerLength(Cookie c) { + int estimate = estimateLength(c.getName(), c.getValue()); + + if (c.getMaxAge() != Long.MIN_VALUE) { + estimate += 41; // 'Expires=Sun, 06 Nov 1994 08:49:37 +0900; ' + } + + if (c.getPath() != null) { + estimate += estimateLength(CookieHeaderNames.PATH, c.getPath()); + } + + if (c.getDomain() != null) { + estimate += estimateLength(CookieHeaderNames.DOMAIN, c.getDomain()); + } + if (c.isSecure()) { + estimate += 8; // 'Secure; ' + } + if (c.isHttpOnly()) { + estimate += 10; // 'HTTPOnly; ' + } + if (c.getVersion() > 0) { + estimate += 11; // 'Version=N; ' + if (c.getComment() != null) { + estimate += estimateLength(CookieHeaderNames.COMMENT, c.getComment()); + } + + if (c.getCommentUrl() != null) { + estimate += estimateLength(CookieHeaderNames.COMMENTURL, c.getCommentUrl()); + } + + int numPorts = c.getPorts().size(); + if (numPorts > 0) { + estimate += 9; // 'Port=""; ' + estimate += numPorts * 4; + } + + if (c.isDiscard()) { + estimate += 9; // 'Discard; ' + } + } + + return estimate; + } + + private static int estimateLength(String name, String value) { + return name.length() + value.length() + 6; + } + static void add(StringBuilder sb, String name, String val) { if (val == null) { addQuoted(sb, name, ""); 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 index f46176606b..c7f724c428 100644 --- 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 @@ -47,7 +47,7 @@ public final class ServerCookieEncoder { throw new NullPointerException("cookie"); } - StringBuilder buf = new StringBuilder(); + StringBuilder buf = new StringBuilder(estimateServerLength(cookie)); add(buf, cookie.getName(), cookie.getValue());