From 609e065fcf830d73b606d2d786af489e0b7dc0b6 Mon Sep 17 00:00:00 2001 From: Scott Mitchell Date: Tue, 31 Mar 2015 14:23:51 -0700 Subject: [PATCH] HTTP/2 Headers Code Using String instead of AsciiString Motivation: The HTTP/2 headers code should be using binary string (currently AsciiString) objects instead of String objects. The DefaultHttp2HeadersEncoder was still using String for sensitiveHeaders. Modifications: - Remove the usage of String from DefaultHttp2HeadersEncoder. - Introduce an interface to determine if a header name/value is sensitive or not to 1. prevent necessarily creating/copying sets. 2. Allow the name/value to be considered when checking if sensitive. Result: No more String in DefaultHttp2HeadersEncoder and less required set creation/operations. --- .../http2/DefaultHttp2HeadersEncoder.java | 17 +++++------ .../codec/http2/Http2HeadersEncoder.java | 29 +++++++++++++++++++ 2 files changed, 36 insertions(+), 10 deletions(-) diff --git a/codec-http2/src/main/java/io/netty/handler/codec/http2/DefaultHttp2HeadersEncoder.java b/codec-http2/src/main/java/io/netty/handler/codec/http2/DefaultHttp2HeadersEncoder.java index a1f950b1b0..114d5e2ad2 100644 --- a/codec-http2/src/main/java/io/netty/handler/codec/http2/DefaultHttp2HeadersEncoder.java +++ b/codec-http2/src/main/java/io/netty/handler/codec/http2/DefaultHttp2HeadersEncoder.java @@ -16,10 +16,11 @@ package io.netty.handler.codec.http2; import static io.netty.handler.codec.http2.Http2CodecUtil.DEFAULT_HEADER_TABLE_SIZE; -import static io.netty.handler.codec.http2.Http2Error.INTERNAL_ERROR; import static io.netty.handler.codec.http2.Http2Error.COMPRESSION_ERROR; +import static io.netty.handler.codec.http2.Http2Error.INTERNAL_ERROR; import static io.netty.handler.codec.http2.Http2Error.PROTOCOL_ERROR; import static io.netty.handler.codec.http2.Http2Exception.connectionError; +import static io.netty.util.internal.ObjectUtil.checkNotNull; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufOutputStream; import io.netty.handler.codec.AsciiString; @@ -28,26 +29,23 @@ import io.netty.handler.codec.BinaryHeaders.EntryVisitor; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; -import java.util.Collections; import java.util.Map.Entry; -import java.util.Set; -import java.util.TreeSet; import com.twitter.hpack.Encoder; public class DefaultHttp2HeadersEncoder implements Http2HeadersEncoder, Http2HeadersEncoder.Configuration { private final Encoder encoder; private final ByteArrayOutputStream tableSizeChangeOutput = new ByteArrayOutputStream(); - private final Set sensitiveHeaders = new TreeSet(String.CASE_INSENSITIVE_ORDER); + private final SensitivityDetector sensitivityDetector; private final Http2HeaderTable headerTable; public DefaultHttp2HeadersEncoder() { - this(DEFAULT_HEADER_TABLE_SIZE, Collections.emptySet()); + this(DEFAULT_HEADER_TABLE_SIZE, NEVER_SENSITIVE); } - public DefaultHttp2HeadersEncoder(int maxHeaderTableSize, Set sensitiveHeaders) { + public DefaultHttp2HeadersEncoder(int maxHeaderTableSize, SensitivityDetector sensitivityDetector) { + this.sensitivityDetector = checkNotNull(sensitivityDetector, "sensitiveDetector"); encoder = new Encoder(maxHeaderTableSize); - this.sensitiveHeaders.addAll(sensitiveHeaders); headerTable = new Http2HeaderTableEncoder(); } @@ -111,8 +109,7 @@ public class DefaultHttp2HeadersEncoder implements Http2HeadersEncoder, Http2Hea } private void encodeHeader(AsciiString key, AsciiString value, OutputStream stream) throws IOException { - boolean sensitive = sensitiveHeaders.contains(key.toString()); - encoder.encodeHeader(stream, key.array(), value.array(), sensitive); + encoder.encodeHeader(stream, key.array(), value.array(), sensitivityDetector.isSensitive(key, value)); } /** diff --git a/codec-http2/src/main/java/io/netty/handler/codec/http2/Http2HeadersEncoder.java b/codec-http2/src/main/java/io/netty/handler/codec/http2/Http2HeadersEncoder.java index b88d773b5c..ee8a2904ad 100644 --- a/codec-http2/src/main/java/io/netty/handler/codec/http2/Http2HeadersEncoder.java +++ b/codec-http2/src/main/java/io/netty/handler/codec/http2/Http2HeadersEncoder.java @@ -16,6 +16,7 @@ package io.netty.handler.codec.http2; import io.netty.buffer.ByteBuf; +import io.netty.handler.codec.AsciiString; /** * Encodes {@link Http2Headers} into HPACK-encoded headers blocks. @@ -31,6 +32,24 @@ public interface Http2HeadersEncoder { Http2HeaderTable headerTable(); } + /** + * Determine if a header name/value pair is treated as + * sensitive. + * If the object can be dynamically modified and shared across multiple connections it may need to be thread safe. + */ + interface SensitivityDetector { + /** + * Determine if a header {@code name}/{@code value} pair should be treated as + * sensitive. + * @param name The name for the header. + * @param value The value of the header. + * @return {@code true} if a header {@code name}/{@code value} pair should be treated as + * sensitive. + * {@code false} otherwise. + */ + boolean isSensitive(AsciiString name, AsciiString value); + } + /** * Encodes the given headers and writes the output headers block to the given output buffer. * @@ -43,4 +62,14 @@ public interface Http2HeadersEncoder { * Get the {@link Configuration} for this {@link Http2HeadersEncoder} */ Configuration configuration(); + + /** + * Always return {@code false} for {@link SensitivityDetector#isSensitive(AsciiString, AsciiString)}. + */ + SensitivityDetector NEVER_SENSITIVE = new SensitivityDetector() { + @Override + public boolean isSensitive(AsciiString name, AsciiString value) { + return false; + } + }; }