You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hc.apache.org by ol...@apache.org on 2016/03/08 21:04:26 UTC

svn commit: r1734137 [2/2] - in /httpcomponents/httpcore/trunk: httpcore5-h2/src/main/java/org/apache/hc/core5/http2/hpack/ httpcore5-h2/src/test/java/org/apache/hc/core5/http2/hpack/ httpcore5/src/main/java/org/apache/hc/core5/http/ httpcore5/src/main...

Added: httpcomponents/httpcore/trunk/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/hpack/TestHPackCoding.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/hpack/TestHPackCoding.java?rev=1734137&view=auto
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/hpack/TestHPackCoding.java (added)
+++ httpcomponents/httpcore/trunk/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/hpack/TestHPackCoding.java Tue Mar  8 20:04:26 2016
@@ -0,0 +1,1007 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF 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.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.hc.core5.http2.hpack;
+
+import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.hc.core5.http.Header;
+import org.apache.hc.core5.http.message.BasicHeader;
+import org.apache.hc.core5.util.ByteArrayBuffer;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class TestHPackCoding {
+
+    @Test
+    public void testIntegerEncodingRFC7541Examples() throws Exception {
+
+        final ByteArrayBuffer buffer = new ByteArrayBuffer(16);
+        HPackEncoder.encodeInt(buffer, 5, 10, 0x0);
+
+        Assert.assertEquals(1, buffer.length());
+        Assert.assertEquals(0b00001010, buffer.byteAt(0) & 0xFF);
+
+        buffer.clear();
+        HPackEncoder.encodeInt(buffer, 5, 1337, 0x0);
+
+        Assert.assertEquals(3, buffer.length());
+        Assert.assertEquals(0b00011111, buffer.byteAt(0) & 0xFF);
+        Assert.assertEquals(0b10011010, buffer.byteAt(1) & 0xFF);
+        Assert.assertEquals(0b00001010, buffer.byteAt(2) & 0xFF);
+
+        buffer.clear();
+        HPackEncoder.encodeInt(buffer, 8, 42, 0x0);
+        Assert.assertEquals(1, buffer.length());
+        Assert.assertEquals(0b00101010, buffer.byteAt(0) & 0xFF);
+    }
+
+    static ByteBuffer wrap(final ByteArrayBuffer src) {
+
+        return ByteBuffer.wrap(src.buffer(), 0, src.length());
+    }
+
+    @Test
+    public void testIntegerCoding() throws Exception {
+
+        final ByteArrayBuffer buffer = new ByteArrayBuffer(16);
+
+        for (int n = 4; n <= 8; n++) {
+
+            buffer.clear();
+
+            HPackEncoder.encodeInt(buffer, n, 10, 0x0);
+            Assert.assertEquals(10, HPackDecoder.decodeInt(wrap(buffer), n));
+
+            buffer.clear();
+
+            HPackEncoder.encodeInt(buffer, n, 123456, 0x0);
+            Assert.assertEquals(123456, HPackDecoder.decodeInt(wrap(buffer), n));
+
+            buffer.clear();
+
+            HPackEncoder.encodeInt(buffer, n, Integer.MAX_VALUE, 0x0);
+            Assert.assertEquals(Integer.MAX_VALUE, HPackDecoder.decodeInt(wrap(buffer), n));
+        }
+
+    }
+
+    @Test
+    public void testIntegerCodingLimit() throws Exception {
+
+        final ByteBuffer src1 = createByteBuffer(0x7f, 0x80, 0xff, 0xff, 0xff, 0x07);
+        Assert.assertEquals(Integer.MAX_VALUE, HPackDecoder.decodeInt(src1, 7));
+
+        final ByteBuffer src2 = createByteBuffer(0x7f, 0x80, 0xff, 0xff, 0xff, 0x08);
+        try {
+            HPackDecoder.decodeInt(src2, 7);
+        } catch (HPackException expected) {
+        }
+        final ByteBuffer src3 = createByteBuffer(0x7f, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01);
+        try {
+            HPackDecoder.decodeInt(src3, 7);
+        } catch (HPackException expected) {
+        }
+    }
+
+    private static ByteBuffer createByteBuffer(final int... bytes) {
+
+        final ByteBuffer buffer = ByteBuffer.allocate(bytes.length);
+        for (int b : bytes) {
+            buffer.put((byte) b);
+        }
+        buffer.flip();
+        return buffer;
+    }
+
+    @Test
+    public void testPlainStringDecoding() throws Exception {
+
+        final ByteBuffer src = createByteBuffer(
+                0x0a, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x2d, 0x6b, 0x65, 0x79);
+
+        final ByteArrayBuffer buffer = new ByteArrayBuffer(16);
+        HPackDecoder.decodePlainString(buffer, src);
+        Assert.assertEquals("custom-key", new String(buffer.buffer(), 0, buffer.length(), StandardCharsets.US_ASCII));
+        Assert.assertFalse("Decoding completed", src.hasRemaining());
+    }
+
+    @Test(expected = HPackException.class)
+    public void testPlainStringDecodingTruncated() throws Exception {
+
+        final ByteBuffer src = createByteBuffer(
+                0x0a, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x2d, 0x6b, 0x65);
+
+        final ByteArrayBuffer buffer = new ByteArrayBuffer(16);
+        HPackDecoder.decodePlainString(buffer, src);
+    }
+
+    @Test
+    public void testHuffmanDecodingRFC7541Examples() throws Exception {
+        final ByteBuffer src = createByteBuffer(
+                0x8c, 0xf1, 0xe3, 0xc2, 0xe5, 0xf2, 0x3a, 0x6b, 0xa0, 0xab, 0x90, 0xf4, 0xff);
+
+        final ByteArrayBuffer buffer = new ByteArrayBuffer(16);
+        HPackDecoder.decodeHuffman(buffer, src);
+        Assert.assertEquals("www.example.com", new String(buffer.buffer(), 0, buffer.length(), StandardCharsets.US_ASCII));
+        Assert.assertFalse("Decoding completed", src.hasRemaining());
+    }
+
+    private static ByteBuffer createByteBuffer(final String s, final Charset charset) {
+
+        return ByteBuffer.wrap(s.getBytes(charset));
+    }
+
+    @Test
+    public void testHuffmanEncoding() throws Exception {
+        final ByteArrayBuffer buffer = new ByteArrayBuffer(16);
+        HPackEncoder.encodeHuffman(buffer, createByteBuffer("www.example.com", StandardCharsets.US_ASCII));
+        final ByteBuffer expected = createByteBuffer(
+                0xf1, 0xe3, 0xc2, 0xe5, 0xf2, 0x3a, 0x6b, 0xa0, 0xab, 0x90, 0xf4, 0xff);
+        Assert.assertEquals(expected, wrap(buffer));
+    }
+
+    @Test
+    public void testBasicStringCoding() throws Exception {
+
+        final HPackEncoder encoder = new HPackEncoder(StandardCharsets.US_ASCII);
+        final HPackDecoder decoder = new HPackDecoder(StandardCharsets.US_ASCII);
+
+        final ByteArrayBuffer buffer = new ByteArrayBuffer(16);
+        encoder.encodeString(buffer, "this and that", false);
+
+        final StringBuilder strBuf = new StringBuilder();
+        decoder.decodeString(ByteBuffer.wrap(buffer.buffer(), 0, buffer.length()), strBuf);
+        Assert.assertEquals("this and that", strBuf.toString());
+
+        buffer.clear();
+        strBuf.setLength(0);
+        encoder.encodeString(buffer, "this and that and Huffman", true);
+        decoder.decodeString(ByteBuffer.wrap(buffer.buffer(), 0, buffer.length()), strBuf);
+        Assert.assertEquals("this and that and Huffman", strBuf.toString());
+    }
+
+    static final int SWISS_GERMAN_HELLO[] = {
+            0x47, 0x72, 0xFC, 0x65, 0x7A, 0x69, 0x5F, 0x7A, 0xE4, 0x6D, 0xE4
+    };
+
+    static final int RUSSIAN_HELLO[] = {
+            0x412, 0x441, 0x435, 0x43C, 0x5F, 0x43F, 0x440, 0x438,
+            0x432, 0x435, 0x442
+    };
+
+    private static String constructHelloString(final int[] raw, final int n) {
+        final StringBuilder buffer = new StringBuilder();
+        for (int j = 0; j < n; j++) {
+            if (j > 0) {
+                buffer.append("; ");
+            }
+            for (int i = 0; i < raw.length; i++) {
+                buffer.append((char) raw[i]);
+            }
+        }
+        return buffer.toString();
+    }
+
+    @Test
+    public void testComplexStringCoding1() throws Exception {
+
+        for (Charset charset : new Charset[]{StandardCharsets.ISO_8859_1, StandardCharsets.UTF_8, StandardCharsets.UTF_16}) {
+
+            final ByteArrayBuffer buffer = new ByteArrayBuffer(16);
+            final StringBuilder strBuf = new StringBuilder();
+
+            final HPackEncoder encoder = new HPackEncoder(charset);
+            final HPackDecoder decoder = new HPackDecoder(charset);
+
+            for (int n = 0; n < 10; n++) {
+
+                final String hello = constructHelloString(SWISS_GERMAN_HELLO, 1 + 10 * n);
+
+                for (boolean b : new boolean[]{false, true}) {
+
+                    buffer.clear();
+                    encoder.encodeString(buffer, hello, b);
+                    strBuf.setLength(0);
+                    decoder.decodeString(ByteBuffer.wrap(buffer.buffer(), 0, buffer.length()), strBuf);
+                    final String helloBack = strBuf.toString();
+                    Assert.assertEquals("charset: " + charset + "; huffman: " + b, hello, helloBack);
+                }
+            }
+        }
+    }
+
+    @Test
+    public void testComplexStringCoding2() throws Exception {
+
+        for (Charset charset : new Charset[]{Charset.forName("KOI8-R"), StandardCharsets.UTF_8, StandardCharsets.UTF_16}) {
+
+            final ByteArrayBuffer buffer = new ByteArrayBuffer(16);
+            final StringBuilder strBuf = new StringBuilder();
+
+            final HPackEncoder encoder = new HPackEncoder(charset);
+            final HPackDecoder decoder = new HPackDecoder(charset);
+
+            for (int n = 0; n < 10; n++) {
+
+                final String hello = constructHelloString(RUSSIAN_HELLO, 1 + 10 * n);
+
+                for (boolean b : new boolean[]{false, true}) {
+
+                    buffer.clear();
+                    strBuf.setLength(0);
+                    encoder.encodeString(buffer, hello, b);
+                    decoder.decodeString(ByteBuffer.wrap(buffer.buffer(), 0, buffer.length()), strBuf);
+                    final String helloBack = strBuf.toString();
+                    Assert.assertEquals("charset: " + charset + "; huffman: " + b, hello, helloBack);
+                }
+            }
+        }
+    }
+
+    private static void assertHeaderEquals(final Header expected, final Header actual) {
+
+        Assert.assertNotNull(actual);
+        Assert.assertEquals("Header name", expected.getName(), actual.getName());
+        Assert.assertEquals("Header value", expected.getValue(), actual.getValue());
+        Assert.assertEquals("Header sensitive flag", expected.isSensitive(), actual.isSensitive());
+    }
+
+    @Test
+    public void testLiteralHeaderWithIndexingDecodingRFC7541Examples() throws Exception {
+
+        final ByteBuffer src = createByteBuffer(
+                0x40, 0x0a, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x2d, 0x6b, 0x65, 0x79, 0x0d, 0x63, 0x75, 0x73,
+                0x74, 0x6f, 0x6d, 0x2d, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72);
+
+        final InboundDynamicTable dynamicTable = new InboundDynamicTable();
+        final HPackDecoder decoder = new HPackDecoder(dynamicTable, StandardCharsets.US_ASCII);
+        final Header header = decoder.decodeLiteralHeader(src, HPackRepresentation.WITH_INDEXING);
+        assertHeaderEquals(new BasicHeader("custom-key", "custom-header"), header);
+        Assert.assertFalse("Decoding completed", src.hasRemaining());
+
+        Assert.assertEquals(1, dynamicTable.dynamicLength());
+        assertHeaderEquals(header, dynamicTable.getDynamicEntry(0));
+    }
+
+    @Test
+    public void testLiteralHeaderWithoutIndexingDecodingRFC7541Examples() throws Exception {
+
+        final ByteBuffer src = createByteBuffer(
+                0x04, 0x0c, 0x2f, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2f, 0x70, 0x61, 0x74, 0x68);
+
+        final InboundDynamicTable dynamicTable = new InboundDynamicTable();
+        final HPackDecoder decoder = new HPackDecoder(dynamicTable, StandardCharsets.US_ASCII);
+        final Header header = decoder.decodeLiteralHeader(src, HPackRepresentation.WITHOUT_INDEXING);
+        assertHeaderEquals(new BasicHeader(":path", "/sample/path"), header);
+        Assert.assertFalse("Decoding completed", src.hasRemaining());
+
+        Assert.assertEquals(0, dynamicTable.dynamicLength());
+    }
+
+    @Test
+    public void testLiteralHeaderNeverIndexedDecodingRFC7541Examples() throws Exception {
+
+        final ByteBuffer src = createByteBuffer(
+                0x10, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x06, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74);
+
+        final InboundDynamicTable dynamicTable = new InboundDynamicTable();
+        final HPackDecoder decoder = new HPackDecoder(dynamicTable, StandardCharsets.US_ASCII);
+        final Header header = decoder.decodeLiteralHeader(src, HPackRepresentation.NEVER_INDEXED);
+        assertHeaderEquals(new BasicHeader("password", "secret", true), header);
+        Assert.assertFalse("Decoding completed", src.hasRemaining());
+
+        Assert.assertEquals(0, dynamicTable.dynamicLength());
+    }
+
+    @Test
+    public void testIndexedHeaderDecodingRFC7541Examples() throws Exception {
+
+        final ByteBuffer src = createByteBuffer(0x82);
+
+        final InboundDynamicTable dynamicTable = new InboundDynamicTable();
+        final HPackDecoder decoder = new HPackDecoder(dynamicTable, StandardCharsets.US_ASCII);
+        final Header header = decoder.decodeIndexedHeader(src);
+        assertHeaderEquals(new BasicHeader(":method", "GET"), header);
+        Assert.assertFalse("Decoding completed", src.hasRemaining());
+
+        Assert.assertEquals(0, dynamicTable.dynamicLength());
+    }
+
+    @Test
+    public void testRequestDecodingWithoutHuffmanRFC7541Examples() throws Exception {
+
+        final ByteBuffer src1 = createByteBuffer(
+                0x82, 0x86, 0x84, 0x41, 0x0f, 0x77, 0x77, 0x77, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e,
+                0x63, 0x6f, 0x6d);
+
+        final InboundDynamicTable dynamicTable = new InboundDynamicTable();
+        final HPackDecoder decoder = new HPackDecoder(dynamicTable, StandardCharsets.US_ASCII);
+        final List<Header> headers1 = decoder.decodeHeaders(src1);
+
+        Assert.assertEquals(4, headers1.size());
+        assertHeaderEquals(new BasicHeader(":method", "GET"), headers1.get(0));
+        assertHeaderEquals(new BasicHeader(":scheme", "http"), headers1.get(1));
+        assertHeaderEquals(new BasicHeader(":path", "/"), headers1.get(2));
+        assertHeaderEquals(new BasicHeader(":authority", "www.example.com"), headers1.get(3));
+
+        Assert.assertEquals(1, dynamicTable.dynamicLength());
+        assertHeaderEquals(new BasicHeader(":authority", "www.example.com"), dynamicTable.getDynamicEntry(0));
+        Assert.assertEquals(57, dynamicTable.getCurrentSize());
+
+        final ByteBuffer src2 = createByteBuffer(
+                0x82, 0x86, 0x84, 0xbe, 0x58, 0x08, 0x6e, 0x6f, 0x2d, 0x63, 0x61, 0x63, 0x68, 0x65);
+
+        final List<Header> headers2 = decoder.decodeHeaders(src2);
+
+        Assert.assertEquals(5, headers2.size());
+        assertHeaderEquals(new BasicHeader(":method", "GET"), headers2.get(0));
+        assertHeaderEquals(new BasicHeader(":scheme", "http"), headers2.get(1));
+        assertHeaderEquals(new BasicHeader(":path", "/"), headers2.get(2));
+        assertHeaderEquals(new BasicHeader(":authority", "www.example.com"), headers2.get(3));
+        assertHeaderEquals(new BasicHeader("cache-control", "no-cache"), headers2.get(4));
+
+        Assert.assertEquals(2, dynamicTable.dynamicLength());
+        assertHeaderEquals(new BasicHeader("cache-control", "no-cache"), dynamicTable.getDynamicEntry(0));
+        assertHeaderEquals(new BasicHeader(":authority", "www.example.com"), dynamicTable.getDynamicEntry(1));
+        Assert.assertEquals(110, dynamicTable.getCurrentSize());
+
+        final ByteBuffer src3 = createByteBuffer(
+                0x82, 0x87, 0x85, 0xbf, 0x40, 0x0a, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x2d, 0x6b, 0x65, 0x79,
+                0x0c, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x2d, 0x76, 0x61, 0x6c, 0x75, 0x65);
+
+        final List<Header> headers3 = decoder.decodeHeaders(src3);
+
+        Assert.assertEquals(5, headers3.size());
+        assertHeaderEquals(new BasicHeader(":method", "GET"), headers3.get(0));
+        assertHeaderEquals(new BasicHeader(":scheme", "https"), headers3.get(1));
+        assertHeaderEquals(new BasicHeader(":path", "/index.html"), headers3.get(2));
+        assertHeaderEquals(new BasicHeader(":authority", "www.example.com"), headers3.get(3));
+        assertHeaderEquals(new BasicHeader("custom-key", "custom-value"), headers3.get(4));
+
+        Assert.assertEquals(3, dynamicTable.dynamicLength());
+        assertHeaderEquals(new BasicHeader("custom-key", "custom-value"), dynamicTable.getDynamicEntry(0));
+        assertHeaderEquals(new BasicHeader("cache-control", "no-cache"), dynamicTable.getDynamicEntry(1));
+        assertHeaderEquals(new BasicHeader(":authority", "www.example.com"), dynamicTable.getDynamicEntry(2));
+        Assert.assertEquals(164, dynamicTable.getCurrentSize());
+    }
+
+    @Test
+    public void testRequestDecodingWithHuffmanRFC7541Examples() throws Exception {
+
+        final ByteBuffer src1 = createByteBuffer(
+                0x82, 0x86, 0x84, 0x41, 0x8c, 0xf1, 0xe3, 0xc2, 0xe5, 0xf2, 0x3a, 0x6b, 0xa0, 0xab, 0x90, 0xf4, 0xff);
+
+        final InboundDynamicTable dynamicTable = new InboundDynamicTable();
+        final HPackDecoder decoder = new HPackDecoder(dynamicTable, StandardCharsets.US_ASCII);
+        final List<Header> headers1 = decoder.decodeHeaders(src1);
+
+        Assert.assertEquals(4, headers1.size());
+        assertHeaderEquals(new BasicHeader(":method", "GET"), headers1.get(0));
+        assertHeaderEquals(new BasicHeader(":scheme", "http"), headers1.get(1));
+        assertHeaderEquals(new BasicHeader(":path", "/"), headers1.get(2));
+        assertHeaderEquals(new BasicHeader(":authority", "www.example.com"), headers1.get(3));
+
+        Assert.assertEquals(1, dynamicTable.dynamicLength());
+        assertHeaderEquals(new BasicHeader(":authority", "www.example.com"), dynamicTable.getDynamicEntry(0));
+        Assert.assertEquals(57, dynamicTable.getCurrentSize());
+
+        final ByteBuffer src2 = createByteBuffer(
+                0x82, 0x86, 0x84, 0xbe, 0x58, 0x86, 0xa8, 0xeb, 0x10, 0x64, 0x9c, 0xbf);
+
+        final List<Header> headers2 = decoder.decodeHeaders(src2);
+
+        Assert.assertEquals(5, headers2.size());
+        assertHeaderEquals(new BasicHeader(":method", "GET"), headers2.get(0));
+        assertHeaderEquals(new BasicHeader(":scheme", "http"), headers2.get(1));
+        assertHeaderEquals(new BasicHeader(":path", "/"), headers2.get(2));
+        assertHeaderEquals(new BasicHeader(":authority", "www.example.com"), headers2.get(3));
+        assertHeaderEquals(new BasicHeader("cache-control", "no-cache"), headers2.get(4));
+
+        Assert.assertEquals(2, dynamicTable.dynamicLength());
+        assertHeaderEquals(new BasicHeader("cache-control", "no-cache"), dynamicTable.getDynamicEntry(0));
+        assertHeaderEquals(new BasicHeader(":authority", "www.example.com"), dynamicTable.getDynamicEntry(1));
+        Assert.assertEquals(110, dynamicTable.getCurrentSize());
+
+        final ByteBuffer src3 = createByteBuffer(
+                0x82, 0x87, 0x85, 0xbf, 0x40, 0x88, 0x25, 0xa8, 0x49, 0xe9, 0x5b, 0xa9, 0x7d, 0x7f, 0x89, 0x25,
+                0xa8, 0x49, 0xe9, 0x5b, 0xb8, 0xe8, 0xb4, 0xbf);
+
+        final List<Header> headers3 = decoder.decodeHeaders(src3);
+
+        Assert.assertEquals(5, headers3.size());
+        assertHeaderEquals(new BasicHeader(":method", "GET"), headers3.get(0));
+        assertHeaderEquals(new BasicHeader(":scheme", "https"), headers3.get(1));
+        assertHeaderEquals(new BasicHeader(":path", "/index.html"), headers3.get(2));
+        assertHeaderEquals(new BasicHeader(":authority", "www.example.com"), headers3.get(3));
+        assertHeaderEquals(new BasicHeader("custom-key", "custom-value"), headers3.get(4));
+
+        Assert.assertEquals(3, dynamicTable.dynamicLength());
+        assertHeaderEquals(new BasicHeader("custom-key", "custom-value"), dynamicTable.getDynamicEntry(0));
+        assertHeaderEquals(new BasicHeader("cache-control", "no-cache"), dynamicTable.getDynamicEntry(1));
+        assertHeaderEquals(new BasicHeader(":authority", "www.example.com"), dynamicTable.getDynamicEntry(2));
+        Assert.assertEquals(164, dynamicTable.getCurrentSize());
+    }
+
+    @Test
+    public void testResponseDecodingWithoutHuffmanRFC7541Examples() throws Exception {
+
+        final ByteBuffer src1 = createByteBuffer(
+                0x48, 0x03, 0x33, 0x30, 0x32, 0x58, 0x07, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x61, 0x1d, 0x4d,
+                0x6f, 0x6e, 0x2c, 0x20, 0x32, 0x31, 0x20, 0x4f, 0x63, 0x74, 0x20, 0x32, 0x30, 0x31, 0x33, 0x20, 0x32,
+                0x30, 0x3a, 0x31, 0x33, 0x3a, 0x32, 0x31, 0x20, 0x47, 0x4d, 0x54, 0x6e, 0x17, 0x68, 0x74, 0x74, 0x70,
+                0x73, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63,
+                0x6f, 0x6d);
+
+        final InboundDynamicTable dynamicTable = new InboundDynamicTable();
+        dynamicTable.setMaxSize(256);
+        final HPackDecoder decoder = new HPackDecoder(dynamicTable, StandardCharsets.US_ASCII);
+        final List<Header> headers1 = decoder.decodeHeaders(src1);
+
+        Assert.assertEquals(4, headers1.size());
+        assertHeaderEquals(new BasicHeader(":status", "302"), headers1.get(0));
+        assertHeaderEquals(new BasicHeader("cache-control", "private"), headers1.get(1));
+        assertHeaderEquals(new BasicHeader("date", "Mon, 21 Oct 2013 20:13:21 GMT"), headers1.get(2));
+        assertHeaderEquals(new BasicHeader("location", "https://www.example.com"), headers1.get(3));
+
+        Assert.assertEquals(4, dynamicTable.dynamicLength());
+        assertHeaderEquals(new BasicHeader("location", "https://www.example.com"), dynamicTable.getDynamicEntry(0));
+        assertHeaderEquals(new BasicHeader("date", "Mon, 21 Oct 2013 20:13:21 GMT"), dynamicTable.getDynamicEntry(1));
+        assertHeaderEquals(new BasicHeader("cache-control", "private"), dynamicTable.getDynamicEntry(2));
+        assertHeaderEquals(new BasicHeader(":status", "302"), dynamicTable.getDynamicEntry(3));
+        Assert.assertEquals(222, dynamicTable.getCurrentSize());
+
+        final ByteBuffer src2 = createByteBuffer(
+                0x48, 0x03, 0x33, 0x30, 0x37, 0xc1, 0xc0, 0xbf);
+
+        final List<Header> headers2 = decoder.decodeHeaders(src2);
+
+        Assert.assertEquals(4, headers2.size());
+        assertHeaderEquals(new BasicHeader(":status", "307"), headers2.get(0));
+        assertHeaderEquals(new BasicHeader("cache-control", "private"), headers2.get(1));
+        assertHeaderEquals(new BasicHeader("date", "Mon, 21 Oct 2013 20:13:21 GMT"), headers2.get(2));
+        assertHeaderEquals(new BasicHeader("location", "https://www.example.com"), headers2.get(3));
+
+        Assert.assertEquals(4, dynamicTable.dynamicLength());
+        assertHeaderEquals(new BasicHeader(":status", "307"), dynamicTable.getDynamicEntry(0));
+        assertHeaderEquals(new BasicHeader("location", "https://www.example.com"), dynamicTable.getDynamicEntry(1));
+        assertHeaderEquals(new BasicHeader("date", "Mon, 21 Oct 2013 20:13:21 GMT"), dynamicTable.getDynamicEntry(2));
+        assertHeaderEquals(new BasicHeader("cache-control", "private"), dynamicTable.getDynamicEntry(3));
+
+        Assert.assertEquals(222, dynamicTable.getCurrentSize());
+
+        final ByteBuffer src3 = createByteBuffer(
+                0x88, 0xc1, 0x61, 0x1d, 0x4d, 0x6f, 0x6e, 0x2c, 0x20, 0x32, 0x31, 0x20, 0x4f, 0x63, 0x74, 0x20, 0x32,
+                0x30, 0x31, 0x33, 0x20, 0x32, 0x30, 0x3a, 0x31, 0x33, 0x3a, 0x32, 0x32, 0x20, 0x47, 0x4d, 0x54, 0xc0,
+                0x5a, 0x04, 0x67, 0x7a, 0x69, 0x70, 0x77, 0x38, 0x66, 0x6f, 0x6f, 0x3d, 0x41, 0x53, 0x44, 0x4a, 0x4b,
+                0x48, 0x51, 0x4b, 0x42, 0x5a, 0x58, 0x4f, 0x51, 0x57, 0x45, 0x4f, 0x50, 0x49, 0x55, 0x41, 0x58, 0x51,
+                0x57, 0x45, 0x4f, 0x49, 0x55, 0x3b, 0x20, 0x6d, 0x61, 0x78, 0x2d, 0x61, 0x67, 0x65, 0x3d, 0x33, 0x36,
+                0x30, 0x30, 0x3b, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31);
+
+        final List<Header> headers3 = decoder.decodeHeaders(src3);
+
+        Assert.assertEquals(6, headers3.size());
+        assertHeaderEquals(new BasicHeader(":status", "200"), headers3.get(0));
+        assertHeaderEquals(new BasicHeader("cache-control", "private"), headers3.get(1));
+        assertHeaderEquals(new BasicHeader("date", "Mon, 21 Oct 2013 20:13:22 GMT"), headers3.get(2));
+        assertHeaderEquals(new BasicHeader("location", "https://www.example.com"), headers3.get(3));
+        assertHeaderEquals(new BasicHeader("content-encoding", "gzip"), headers3.get(4));
+        assertHeaderEquals(new BasicHeader("set-cookie", "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1"), headers3.get(5));
+
+        Assert.assertEquals(3, dynamicTable.dynamicLength());
+        assertHeaderEquals(new BasicHeader("set-cookie", "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1"), dynamicTable.getDynamicEntry(0));
+        assertHeaderEquals(new BasicHeader("content-encoding", "gzip"), dynamicTable.getDynamicEntry(1));
+        assertHeaderEquals(new BasicHeader("date", "Mon, 21 Oct 2013 20:13:22 GMT"), dynamicTable.getDynamicEntry(2));
+
+        Assert.assertEquals(215, dynamicTable.getCurrentSize());
+    }
+
+    @Test
+    public void testResponseDecodingWithHuffmanRFC7541Examples() throws Exception {
+
+        final ByteBuffer src1 = createByteBuffer(
+                0x48, 0x82, 0x64, 0x02, 0x58, 0x85, 0xae, 0xc3, 0x77, 0x1a, 0x4b, 0x61, 0x96, 0xd0, 0x7a, 0xbe, 0x94,
+                0x10, 0x54, 0xd4, 0x44, 0xa8, 0x20, 0x05, 0x95, 0x04, 0x0b, 0x81, 0x66, 0xe0, 0x82, 0xa6, 0x2d, 0x1b,
+                0xff, 0x6e, 0x91, 0x9d, 0x29, 0xad, 0x17, 0x18, 0x63, 0xc7, 0x8f, 0x0b, 0x97, 0xc8, 0xe9, 0xae, 0x82,
+                0xae, 0x43, 0xd3);
+
+        final InboundDynamicTable dynamicTable = new InboundDynamicTable();
+        dynamicTable.setMaxSize(256);
+        final HPackDecoder decoder = new HPackDecoder(dynamicTable, StandardCharsets.US_ASCII);
+        final List<Header> headers1 = decoder.decodeHeaders(src1);
+
+        Assert.assertEquals(4, headers1.size());
+        assertHeaderEquals(new BasicHeader(":status", "302"), headers1.get(0));
+        assertHeaderEquals(new BasicHeader("cache-control", "private"), headers1.get(1));
+        assertHeaderEquals(new BasicHeader("date", "Mon, 21 Oct 2013 20:13:21 GMT"), headers1.get(2));
+        assertHeaderEquals(new BasicHeader("location", "https://www.example.com"), headers1.get(3));
+
+        Assert.assertEquals(4, dynamicTable.dynamicLength());
+        assertHeaderEquals(new BasicHeader("location", "https://www.example.com"), dynamicTable.getDynamicEntry(0));
+        assertHeaderEquals(new BasicHeader("date", "Mon, 21 Oct 2013 20:13:21 GMT"), dynamicTable.getDynamicEntry(1));
+        assertHeaderEquals(new BasicHeader("cache-control", "private"), dynamicTable.getDynamicEntry(2));
+        assertHeaderEquals(new BasicHeader(":status", "302"), dynamicTable.getDynamicEntry(3));
+        Assert.assertEquals(222, dynamicTable.getCurrentSize());
+
+        final ByteBuffer src2 = createByteBuffer(
+                0x48, 0x83, 0x64, 0x0e, 0xff, 0xc1, 0xc0, 0xbf);
+
+        final List<Header> headers2 = decoder.decodeHeaders(src2);
+
+        Assert.assertEquals(4, headers2.size());
+        assertHeaderEquals(new BasicHeader(":status", "307"), headers2.get(0));
+        assertHeaderEquals(new BasicHeader("cache-control", "private"), headers2.get(1));
+        assertHeaderEquals(new BasicHeader("date", "Mon, 21 Oct 2013 20:13:21 GMT"), headers2.get(2));
+        assertHeaderEquals(new BasicHeader("location", "https://www.example.com"), headers2.get(3));
+
+        Assert.assertEquals(4, dynamicTable.dynamicLength());
+        assertHeaderEquals(new BasicHeader(":status", "307"), dynamicTable.getDynamicEntry(0));
+        assertHeaderEquals(new BasicHeader("location", "https://www.example.com"), dynamicTable.getDynamicEntry(1));
+        assertHeaderEquals(new BasicHeader("date", "Mon, 21 Oct 2013 20:13:21 GMT"), dynamicTable.getDynamicEntry(2));
+        assertHeaderEquals(new BasicHeader("cache-control", "private"), dynamicTable.getDynamicEntry(3));
+
+        Assert.assertEquals(222, dynamicTable.getCurrentSize());
+
+        final ByteBuffer src3 = createByteBuffer(
+                0x88, 0xc1, 0x61, 0x96, 0xd0, 0x7a, 0xbe, 0x94, 0x10, 0x54, 0xd4, 0x44, 0xa8, 0x20, 0x05, 0x95, 0x04,
+                0x0b, 0x81, 0x66, 0xe0, 0x84, 0xa6, 0x2d, 0x1b, 0xff, 0xc0, 0x5a, 0x83, 0x9b, 0xd9, 0xab, 0x77, 0xad,
+                0x94, 0xe7, 0x82, 0x1d, 0xd7, 0xf2, 0xe6, 0xc7, 0xb3, 0x35, 0xdf, 0xdf, 0xcd, 0x5b, 0x39, 0x60, 0xd5,
+                0xaf, 0x27, 0x08, 0x7f, 0x36, 0x72, 0xc1, 0xab, 0x27, 0x0f, 0xb5, 0x29, 0x1f, 0x95, 0x87, 0x31, 0x60,
+                0x65, 0xc0, 0x03, 0xed, 0x4e, 0xe5, 0xb1, 0x06, 0x3d, 0x50, 0x07);
+
+        final List<Header> headers3 = decoder.decodeHeaders(src3);
+
+        Assert.assertEquals(6, headers3.size());
+        assertHeaderEquals(new BasicHeader(":status", "200"), headers3.get(0));
+        assertHeaderEquals(new BasicHeader("cache-control", "private"), headers3.get(1));
+        assertHeaderEquals(new BasicHeader("date", "Mon, 21 Oct 2013 20:13:22 GMT"), headers3.get(2));
+        assertHeaderEquals(new BasicHeader("location", "https://www.example.com"), headers3.get(3));
+        assertHeaderEquals(new BasicHeader("content-encoding", "gzip"), headers3.get(4));
+        assertHeaderEquals(new BasicHeader("set-cookie", "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1"), headers3.get(5));
+
+        Assert.assertEquals(3, dynamicTable.dynamicLength());
+        assertHeaderEquals(new BasicHeader("set-cookie", "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1"), dynamicTable.getDynamicEntry(0));
+        assertHeaderEquals(new BasicHeader("content-encoding", "gzip"), dynamicTable.getDynamicEntry(1));
+        assertHeaderEquals(new BasicHeader("date", "Mon, 21 Oct 2013 20:13:22 GMT"), dynamicTable.getDynamicEntry(2));
+
+        Assert.assertEquals(215, dynamicTable.getCurrentSize());
+    }
+
+    private static byte[] createByteArray(final int... bytes) {
+        final byte[] buffer = new byte[bytes.length];
+        for (int i = 0; i < bytes.length; i++) {
+            buffer[i] = (byte) bytes[i];
+        }
+        return buffer;
+    }
+
+    @Test
+    public void testLiteralHeaderWithIndexingEncodingRFC7541Examples() throws Exception {
+
+        final OutboundDynamicTable dynamicTable = new OutboundDynamicTable();
+        final HPackEncoder encoder = new HPackEncoder(dynamicTable, StandardCharsets.US_ASCII);
+
+        final ByteArrayBuffer buf = new ByteArrayBuffer(128);
+
+        final Header header = new BasicHeader("custom-key", "custom-header");
+        encoder.encodeLiteralHeader(buf, null, header, HPackRepresentation.WITH_INDEXING, false);
+
+        final byte[] expected = createByteArray(
+                0x40, 0x0a, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x2d, 0x6b, 0x65, 0x79, 0x0d, 0x63, 0x75, 0x73,
+                0x74, 0x6f, 0x6d, 0x2d, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72);
+
+        Assert.assertArrayEquals(expected, buf.toByteArray());
+    }
+
+    @Test
+    public void testLiteralHeaderWithoutIndexingEncodingRFC7541Examples() throws Exception {
+
+        final OutboundDynamicTable dynamicTable = new OutboundDynamicTable();
+        final HPackEncoder encoder = new HPackEncoder(dynamicTable, StandardCharsets.US_ASCII);
+
+        final ByteArrayBuffer buf = new ByteArrayBuffer(128);
+
+        final Header header = new BasicHeader(":path", "/sample/path");
+        encoder.encodeLiteralHeader(buf, new HPackEntry() {
+            @Override
+            public int getIndex() {
+                return 4;
+            }
+
+            @Override
+            public HPackHeader getHeader() {
+                return new HPackHeader(header);
+            }
+        }, header, HPackRepresentation.WITHOUT_INDEXING, false);
+
+        final byte[] expected = createByteArray(
+                0x04, 0x0c, 0x2f, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2f, 0x70, 0x61, 0x74, 0x68);
+        Assert.assertArrayEquals(expected, buf.toByteArray());
+    }
+
+    @Test
+    public void testLiteralHeaderNeverIndexedEncodingRFC7541Examples() throws Exception {
+
+        final OutboundDynamicTable dynamicTable = new OutboundDynamicTable();
+        final HPackEncoder encoder = new HPackEncoder(dynamicTable, StandardCharsets.US_ASCII);
+
+        final ByteArrayBuffer buf = new ByteArrayBuffer(128);
+
+        final Header header = new BasicHeader("password", "secret", true);
+        encoder.encodeLiteralHeader(buf, null, header, HPackRepresentation.NEVER_INDEXED, false);
+
+        final byte[] expected = createByteArray(
+                0x10, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x06, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74);
+        Assert.assertArrayEquals(expected, buf.toByteArray());
+    }
+
+    @Test
+    public void testIndexedHeaderEncodingRFC7541Examples() throws Exception {
+
+        final OutboundDynamicTable dynamicTable = new OutboundDynamicTable();
+        final HPackEncoder encoder = new HPackEncoder(dynamicTable, StandardCharsets.US_ASCII);
+
+        final ByteArrayBuffer buf = new ByteArrayBuffer(128);
+        encoder.encodeIndex(buf, 2);
+
+        final byte[] expected = createByteArray(0x82);
+        Assert.assertArrayEquals(expected, buf.toByteArray());
+    }
+
+    @Test
+    public void testRequestEncodingWithoutHuffmanRFC7541Examples() throws Exception {
+
+        final OutboundDynamicTable dynamicTable = new OutboundDynamicTable();
+        final HPackEncoder encoder = new HPackEncoder(dynamicTable, StandardCharsets.US_ASCII);
+
+        final ByteArrayBuffer buf = new ByteArrayBuffer(256);
+        final List<Header> headers1 = Arrays.<Header>asList(
+                new BasicHeader(":method", "GET"),
+                new BasicHeader(":scheme", "http"),
+                new BasicHeader(":path", "/"),
+                new BasicHeader(":authority", "www.example.com"));
+
+        encoder.encodeHeaders(buf, headers1, false, false);
+
+        final byte[] expected1 = createByteArray(
+                0x82, 0x86, 0x84, 0x41, 0x0f, 0x77, 0x77, 0x77, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e,
+                0x63, 0x6f, 0x6d);
+        Assert.assertArrayEquals(expected1, buf.toByteArray());
+
+        Assert.assertEquals(1, dynamicTable.dynamicLength());
+        assertHeaderEquals(new BasicHeader(":authority", "www.example.com"), dynamicTable.getDynamicEntry(0));
+        Assert.assertEquals(57, dynamicTable.getCurrentSize());
+
+        final List<Header> headers2 = Arrays.<Header>asList(
+                new BasicHeader(":method", "GET"),
+                new BasicHeader(":scheme", "http"),
+                new BasicHeader(":path", "/"),
+                new BasicHeader(":authority", "www.example.com"),
+                new BasicHeader("cache-control", "no-cache"));
+
+        buf.clear();
+        encoder.encodeHeaders(buf, headers2, false, false);
+
+        final byte[] expected2 = createByteArray(
+                0x82, 0x86, 0x84, 0xbe, 0x58, 0x08, 0x6e, 0x6f, 0x2d, 0x63, 0x61, 0x63, 0x68, 0x65);
+        Assert.assertArrayEquals(expected2, buf.toByteArray());
+
+        Assert.assertEquals(2, dynamicTable.dynamicLength());
+        assertHeaderEquals(new BasicHeader("cache-control", "no-cache"), dynamicTable.getDynamicEntry(0));
+        assertHeaderEquals(new BasicHeader(":authority", "www.example.com"), dynamicTable.getDynamicEntry(1));
+        Assert.assertEquals(110, dynamicTable.getCurrentSize());
+
+        final List<Header> headers3 = Arrays.<Header>asList(
+                new BasicHeader(":method", "GET"),
+                new BasicHeader(":scheme", "https"),
+                new BasicHeader(":path", "/index.html"),
+                new BasicHeader(":authority", "www.example.com"),
+                new BasicHeader("custom-key", "custom-value"));
+
+        buf.clear();
+        encoder.encodeHeaders(buf, headers3, false, false);
+
+        final byte[] expected3 = createByteArray(
+                0x82, 0x87, 0x85, 0xbf, 0x40, 0x0a, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x2d, 0x6b, 0x65, 0x79,
+                0x0c, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x2d, 0x76, 0x61, 0x6c, 0x75, 0x65);
+        Assert.assertArrayEquals(expected3, buf.toByteArray());
+
+        Assert.assertEquals(3, dynamicTable.dynamicLength());
+        assertHeaderEquals(new BasicHeader("custom-key", "custom-value"), dynamicTable.getDynamicEntry(0));
+        assertHeaderEquals(new BasicHeader("cache-control", "no-cache"), dynamicTable.getDynamicEntry(1));
+        assertHeaderEquals(new BasicHeader(":authority", "www.example.com"), dynamicTable.getDynamicEntry(2));
+        Assert.assertEquals(164, dynamicTable.getCurrentSize());
+    }
+
+    @Test
+    public void testRequestEncodingWithHuffmanRFC7541Examples() throws Exception {
+
+        final OutboundDynamicTable dynamicTable = new OutboundDynamicTable();
+        final HPackEncoder encoder = new HPackEncoder(dynamicTable, StandardCharsets.US_ASCII);
+
+        final ByteArrayBuffer buf = new ByteArrayBuffer(256);
+        final List<Header> headers1 = Arrays.<Header>asList(
+                new BasicHeader(":method", "GET"),
+                new BasicHeader(":scheme", "http"),
+                new BasicHeader(":path", "/"),
+                new BasicHeader(":authority", "www.example.com"));
+
+        encoder.encodeHeaders(buf, headers1, false, true);
+
+        final byte[] expected1 = createByteArray(
+                0x82, 0x86, 0x84, 0x41, 0x8c, 0xf1, 0xe3, 0xc2, 0xe5, 0xf2, 0x3a, 0x6b, 0xa0, 0xab, 0x90, 0xf4, 0xff);
+        Assert.assertArrayEquals(expected1, buf.toByteArray());
+
+        Assert.assertEquals(1, dynamicTable.dynamicLength());
+        assertHeaderEquals(new BasicHeader(":authority", "www.example.com"), dynamicTable.getDynamicEntry(0));
+        Assert.assertEquals(57, dynamicTable.getCurrentSize());
+
+        final List<Header> headers2 = Arrays.<Header>asList(
+                new BasicHeader(":method", "GET"),
+                new BasicHeader(":scheme", "http"),
+                new BasicHeader(":path", "/"),
+                new BasicHeader(":authority", "www.example.com"),
+                new BasicHeader("cache-control", "no-cache"));
+
+        buf.clear();
+        encoder.encodeHeaders(buf, headers2, false, true);
+
+        final byte[] expected2 = createByteArray(
+                0x82, 0x86, 0x84, 0xbe, 0x58, 0x86, 0xa8, 0xeb, 0x10, 0x64, 0x9c, 0xbf);
+        Assert.assertArrayEquals(expected2, buf.toByteArray());
+
+        Assert.assertEquals(2, dynamicTable.dynamicLength());
+        assertHeaderEquals(new BasicHeader("cache-control", "no-cache"), dynamicTable.getDynamicEntry(0));
+        assertHeaderEquals(new BasicHeader(":authority", "www.example.com"), dynamicTable.getDynamicEntry(1));
+        Assert.assertEquals(110, dynamicTable.getCurrentSize());
+
+        final List<Header> headers3 = Arrays.<Header>asList(
+                new BasicHeader(":method", "GET"),
+                new BasicHeader(":scheme", "https"),
+                new BasicHeader(":path", "/index.html"),
+                new BasicHeader(":authority", "www.example.com"),
+                new BasicHeader("custom-key", "custom-value"));
+
+        buf.clear();
+        encoder.encodeHeaders(buf, headers3, false, true);
+
+        final byte[] expected3 = createByteArray(
+                0x82, 0x87, 0x85, 0xbf, 0x40, 0x88, 0x25, 0xa8, 0x49, 0xe9, 0x5b, 0xa9, 0x7d, 0x7f, 0x89, 0x25,
+                0xa8, 0x49, 0xe9, 0x5b, 0xb8, 0xe8, 0xb4, 0xbf);
+        Assert.assertArrayEquals(expected3, buf.toByteArray());
+
+        Assert.assertEquals(3, dynamicTable.dynamicLength());
+        assertHeaderEquals(new BasicHeader("custom-key", "custom-value"), dynamicTable.getDynamicEntry(0));
+        assertHeaderEquals(new BasicHeader("cache-control", "no-cache"), dynamicTable.getDynamicEntry(1));
+        assertHeaderEquals(new BasicHeader(":authority", "www.example.com"), dynamicTable.getDynamicEntry(2));
+        Assert.assertEquals(164, dynamicTable.getCurrentSize());
+    }
+
+    @Test
+    public void testResponseEncodingWithoutHuffmanRFC7541Examples() throws Exception {
+
+        final OutboundDynamicTable dynamicTable = new OutboundDynamicTable();
+        dynamicTable.setMaxSize(256);
+        final HPackEncoder encoder = new HPackEncoder(dynamicTable, StandardCharsets.US_ASCII);
+
+        final ByteArrayBuffer buf = new ByteArrayBuffer(256);
+        final List<Header> headers1 = Arrays.<Header>asList(
+                new BasicHeader(":status", "302"),
+                new BasicHeader("cache-control", "private"),
+                new BasicHeader("date", "Mon, 21 Oct 2013 20:13:21 GMT"),
+                new BasicHeader("location", "https://www.example.com"));
+
+        encoder.encodeHeaders(buf, headers1, false, false);
+
+        final byte[] expected1 = createByteArray(
+                0x48, 0x03, 0x33, 0x30, 0x32, 0x58, 0x07, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x61, 0x1d, 0x4d,
+                0x6f, 0x6e, 0x2c, 0x20, 0x32, 0x31, 0x20, 0x4f, 0x63, 0x74, 0x20, 0x32, 0x30, 0x31, 0x33, 0x20, 0x32,
+                0x30, 0x3a, 0x31, 0x33, 0x3a, 0x32, 0x31, 0x20, 0x47, 0x4d, 0x54, 0x6e, 0x17, 0x68, 0x74, 0x74, 0x70,
+                0x73, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63,
+                0x6f, 0x6d);
+        Assert.assertArrayEquals(expected1, buf.toByteArray());
+
+        Assert.assertEquals(4, dynamicTable.dynamicLength());
+        assertHeaderEquals(new BasicHeader("location", "https://www.example.com"), dynamicTable.getDynamicEntry(0));
+        assertHeaderEquals(new BasicHeader("date", "Mon, 21 Oct 2013 20:13:21 GMT"), dynamicTable.getDynamicEntry(1));
+        assertHeaderEquals(new BasicHeader("cache-control", "private"), dynamicTable.getDynamicEntry(2));
+        assertHeaderEquals(new BasicHeader(":status", "302"), dynamicTable.getDynamicEntry(3));
+        Assert.assertEquals(222, dynamicTable.getCurrentSize());
+
+        final List<Header> headers2 = Arrays.<Header>asList(
+                new BasicHeader(":status", "307"),
+                new BasicHeader("cache-control", "private"),
+                new BasicHeader("date", "Mon, 21 Oct 2013 20:13:21 GMT"),
+                new BasicHeader("location", "https://www.example.com"));
+
+        buf.clear();
+        encoder.encodeHeaders(buf, headers2, false, false);
+
+        final byte[] expected2 = createByteArray(
+                0x48, 0x03, 0x33, 0x30, 0x37, 0xc1, 0xc0, 0xbf);
+        Assert.assertArrayEquals(expected2, buf.toByteArray());
+
+        Assert.assertEquals(4, dynamicTable.dynamicLength());
+        assertHeaderEquals(new BasicHeader(":status", "307"), dynamicTable.getDynamicEntry(0));
+        assertHeaderEquals(new BasicHeader("location", "https://www.example.com"), dynamicTable.getDynamicEntry(1));
+        assertHeaderEquals(new BasicHeader("date", "Mon, 21 Oct 2013 20:13:21 GMT"), dynamicTable.getDynamicEntry(2));
+        assertHeaderEquals(new BasicHeader("cache-control", "private"), dynamicTable.getDynamicEntry(3));
+
+        Assert.assertEquals(222, dynamicTable.getCurrentSize());
+
+        final List<Header> headers3 = Arrays.<Header>asList(
+        new BasicHeader(":status", "200"),
+                new BasicHeader("cache-control", "private"),
+                new BasicHeader("date", "Mon, 21 Oct 2013 20:13:22 GMT"),
+                new BasicHeader("location", "https://www.example.com"),
+                new BasicHeader("content-encoding", "gzip"),
+                new BasicHeader("set-cookie", "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1"));
+
+        buf.clear();
+        encoder.encodeHeaders(buf, headers3, false, false);
+
+        final byte[] expected3 = createByteArray(
+                0x88, 0xc1, 0x61, 0x1d, 0x4d, 0x6f, 0x6e, 0x2c, 0x20, 0x32, 0x31, 0x20, 0x4f, 0x63, 0x74, 0x20, 0x32,
+                0x30, 0x31, 0x33, 0x20, 0x32, 0x30, 0x3a, 0x31, 0x33, 0x3a, 0x32, 0x32, 0x20, 0x47, 0x4d, 0x54, 0xc0,
+                0x5a, 0x04, 0x67, 0x7a, 0x69, 0x70, 0x77, 0x38, 0x66, 0x6f, 0x6f, 0x3d, 0x41, 0x53, 0x44, 0x4a, 0x4b,
+                0x48, 0x51, 0x4b, 0x42, 0x5a, 0x58, 0x4f, 0x51, 0x57, 0x45, 0x4f, 0x50, 0x49, 0x55, 0x41, 0x58, 0x51,
+                0x57, 0x45, 0x4f, 0x49, 0x55, 0x3b, 0x20, 0x6d, 0x61, 0x78, 0x2d, 0x61, 0x67, 0x65, 0x3d, 0x33, 0x36,
+                0x30, 0x30, 0x3b, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31);
+        Assert.assertArrayEquals(expected3, buf.toByteArray());
+
+        Assert.assertEquals(3, dynamicTable.dynamicLength());
+        assertHeaderEquals(new BasicHeader("set-cookie", "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1"), dynamicTable.getDynamicEntry(0));
+        assertHeaderEquals(new BasicHeader("content-encoding", "gzip"), dynamicTable.getDynamicEntry(1));
+        assertHeaderEquals(new BasicHeader("date", "Mon, 21 Oct 2013 20:13:22 GMT"), dynamicTable.getDynamicEntry(2));
+
+        Assert.assertEquals(215, dynamicTable.getCurrentSize());
+    }
+
+    @Test
+    public void testResponseEncodingWithHuffmanRFC7541Examples() throws Exception {
+
+        final OutboundDynamicTable dynamicTable = new OutboundDynamicTable();
+        dynamicTable.setMaxSize(256);
+        final HPackEncoder encoder = new HPackEncoder(dynamicTable, StandardCharsets.US_ASCII);
+
+        final ByteArrayBuffer buf = new ByteArrayBuffer(256);
+        final List<Header> headers1 = Arrays.<Header>asList(
+                new BasicHeader(":status", "302"),
+                new BasicHeader("cache-control", "private"),
+                new BasicHeader("date", "Mon, 21 Oct 2013 20:13:21 GMT"),
+                new BasicHeader("location", "https://www.example.com"));
+
+        encoder.encodeHeaders(buf, headers1, false, true);
+
+        final byte[] expected1 = createByteArray(
+                0x48, 0x82, 0x64, 0x02, 0x58, 0x85, 0xae, 0xc3, 0x77, 0x1a, 0x4b, 0x61, 0x96, 0xd0, 0x7a, 0xbe, 0x94,
+                0x10, 0x54, 0xd4, 0x44, 0xa8, 0x20, 0x05, 0x95, 0x04, 0x0b, 0x81, 0x66, 0xe0, 0x82, 0xa6, 0x2d, 0x1b,
+                0xff, 0x6e, 0x91, 0x9d, 0x29, 0xad, 0x17, 0x18, 0x63, 0xc7, 0x8f, 0x0b, 0x97, 0xc8, 0xe9, 0xae, 0x82,
+                0xae, 0x43, 0xd3);
+        Assert.assertArrayEquals(expected1, buf.toByteArray());
+
+        Assert.assertEquals(4, dynamicTable.dynamicLength());
+        assertHeaderEquals(new BasicHeader("location", "https://www.example.com"), dynamicTable.getDynamicEntry(0));
+        assertHeaderEquals(new BasicHeader("date", "Mon, 21 Oct 2013 20:13:21 GMT"), dynamicTable.getDynamicEntry(1));
+        assertHeaderEquals(new BasicHeader("cache-control", "private"), dynamicTable.getDynamicEntry(2));
+        assertHeaderEquals(new BasicHeader(":status", "302"), dynamicTable.getDynamicEntry(3));
+        Assert.assertEquals(222, dynamicTable.getCurrentSize());
+
+        final List<Header> headers2 = Arrays.<Header>asList(
+                new BasicHeader(":status", "307"),
+                new BasicHeader("cache-control", "private"),
+                new BasicHeader("date", "Mon, 21 Oct 2013 20:13:21 GMT"),
+                new BasicHeader("location", "https://www.example.com"));
+
+        buf.clear();
+        encoder.encodeHeaders(buf, headers2, false, true);
+
+        final byte[] expected2 = createByteArray(
+                0x48, 0x83, 0x64, 0x0e, 0xff, 0xc1, 0xc0, 0xbf);
+        Assert.assertArrayEquals(expected2, buf.toByteArray());
+
+        Assert.assertEquals(4, dynamicTable.dynamicLength());
+        assertHeaderEquals(new BasicHeader(":status", "307"), dynamicTable.getDynamicEntry(0));
+        assertHeaderEquals(new BasicHeader("location", "https://www.example.com"), dynamicTable.getDynamicEntry(1));
+        assertHeaderEquals(new BasicHeader("date", "Mon, 21 Oct 2013 20:13:21 GMT"), dynamicTable.getDynamicEntry(2));
+        assertHeaderEquals(new BasicHeader("cache-control", "private"), dynamicTable.getDynamicEntry(3));
+
+        Assert.assertEquals(222, dynamicTable.getCurrentSize());
+
+        final List<Header> headers3 = Arrays.<Header>asList(
+                new BasicHeader(":status", "200"),
+                new BasicHeader("cache-control", "private"),
+                new BasicHeader("date", "Mon, 21 Oct 2013 20:13:22 GMT"),
+                new BasicHeader("location", "https://www.example.com"),
+                new BasicHeader("content-encoding", "gzip"),
+                new BasicHeader("set-cookie", "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1"));
+
+        buf.clear();
+        encoder.encodeHeaders(buf, headers3, false, true);
+
+        final byte[] expected3 = createByteArray(
+                0x88, 0xc1, 0x61, 0x96, 0xd0, 0x7a, 0xbe, 0x94, 0x10, 0x54, 0xd4, 0x44, 0xa8, 0x20, 0x05, 0x95, 0x04,
+                0x0b, 0x81, 0x66, 0xe0, 0x84, 0xa6, 0x2d, 0x1b, 0xff, 0xc0, 0x5a, 0x83, 0x9b, 0xd9, 0xab, 0x77, 0xad,
+                0x94, 0xe7, 0x82, 0x1d, 0xd7, 0xf2, 0xe6, 0xc7, 0xb3, 0x35, 0xdf, 0xdf, 0xcd, 0x5b, 0x39, 0x60, 0xd5,
+                0xaf, 0x27, 0x08, 0x7f, 0x36, 0x72, 0xc1, 0xab, 0x27, 0x0f, 0xb5, 0x29, 0x1f, 0x95, 0x87, 0x31, 0x60,
+                0x65, 0xc0, 0x03, 0xed, 0x4e, 0xe5, 0xb1, 0x06, 0x3d, 0x50, 0x07);
+        Assert.assertArrayEquals(expected3, buf.toByteArray());
+
+        Assert.assertEquals(3, dynamicTable.dynamicLength());
+        assertHeaderEquals(new BasicHeader("set-cookie", "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1"), dynamicTable.getDynamicEntry(0));
+        assertHeaderEquals(new BasicHeader("content-encoding", "gzip"), dynamicTable.getDynamicEntry(1));
+        assertHeaderEquals(new BasicHeader("date", "Mon, 21 Oct 2013 20:13:22 GMT"), dynamicTable.getDynamicEntry(2));
+
+        Assert.assertEquals(215, dynamicTable.getCurrentSize());
+    }
+
+    @Test
+    public void testHeaderEntrySizeNonAscii() throws Exception {
+
+        final ByteArrayBuffer buffer = new ByteArrayBuffer(128);
+        final Header header = new BasicHeader("hello", constructHelloString(SWISS_GERMAN_HELLO, 1));
+
+        final OutboundDynamicTable outboundTable1 = new OutboundDynamicTable();
+        final HPackEncoder encoder1 = new HPackEncoder(outboundTable1, StandardCharsets.ISO_8859_1);
+        final InboundDynamicTable inboundTable1 = new InboundDynamicTable();
+        final HPackDecoder decoder1 = new HPackDecoder(inboundTable1, StandardCharsets.ISO_8859_1);
+
+        encoder1.setMaxTableSize(48);
+        decoder1.setMaxTableSize(48);
+
+        encoder1.encodeHeader(buffer, header);
+        assertHeaderEquals(header, decoder1.decodeHeader(ByteBuffer.wrap(buffer.buffer(), 0, buffer.length())));
+
+        Assert.assertEquals(1, outboundTable1.dynamicLength());
+        Assert.assertEquals(1, inboundTable1.dynamicLength());
+
+        assertHeaderEquals(header, outboundTable1.getDynamicEntry(0));
+        assertHeaderEquals(header, inboundTable1.getDynamicEntry(0));
+
+        buffer.clear();
+
+        final OutboundDynamicTable outboundTable2 = new OutboundDynamicTable();
+        final HPackEncoder encoder2 = new HPackEncoder(outboundTable2, StandardCharsets.UTF_8);
+        final InboundDynamicTable inboundTable2 = new InboundDynamicTable();
+        final HPackDecoder decoder2 = new HPackDecoder(inboundTable2, StandardCharsets.UTF_8);
+
+        encoder2.setMaxTableSize(48);
+        decoder2.setMaxTableSize(48);
+
+        encoder2.encodeHeader(buffer, header);
+        assertHeaderEquals(header, decoder2.decodeHeader(ByteBuffer.wrap(buffer.buffer(), 0, buffer.length())));
+
+        Assert.assertEquals(0, outboundTable2.dynamicLength());
+        Assert.assertEquals(0, inboundTable2.dynamicLength());
+    }
+
+}
+

Propchange: httpcomponents/httpcore/trunk/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/hpack/TestHPackCoding.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: httpcomponents/httpcore/trunk/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/hpack/TestHPackCoding.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision

Propchange: httpcomponents/httpcore/trunk/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/hpack/TestHPackCoding.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: httpcomponents/httpcore/trunk/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/hpack/TestInboundDynamicTable.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/hpack/TestInboundDynamicTable.java?rev=1734137&view=auto
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/hpack/TestInboundDynamicTable.java (added)
+++ httpcomponents/httpcore/trunk/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/hpack/TestInboundDynamicTable.java Tue Mar  8 20:04:26 2016
@@ -0,0 +1,70 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF 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.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.hc.core5.http2.hpack;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class TestInboundDynamicTable {
+
+    @Test
+    public void testBasics() throws Exception {
+
+        final InboundDynamicTable table = new InboundDynamicTable();
+        Assert.assertEquals(Integer.MAX_VALUE, table.getMaxSize());
+        Assert.assertEquals(0, table.getCurrentSize());
+
+        final HPackHeader header1 = new HPackHeader("h", "1");
+        table.add(header1);
+        Assert.assertEquals(1, table.dynamicLength());
+        Assert.assertEquals(61, table.staticLength());
+        Assert.assertEquals(62, table.length());
+        Assert.assertSame(header1, table.getHeader(62));
+        Assert.assertEquals(34, table.getCurrentSize());
+    }
+
+    @Test
+    public void testEviction() throws Exception {
+
+        final InboundDynamicTable table = new InboundDynamicTable();
+
+        table.add(new HPackHeader("h", "1"));
+        table.add(new HPackHeader("h", "2"));
+
+        Assert.assertEquals(68, table.getCurrentSize());
+
+        table.setMaxSize(256);
+        Assert.assertEquals(68, table.getCurrentSize());
+        table.setMaxSize(67);
+        Assert.assertEquals(34, table.getCurrentSize());
+        table.setMaxSize(10);
+        Assert.assertEquals(0, table.getCurrentSize());
+    }
+
+}
+

Propchange: httpcomponents/httpcore/trunk/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/hpack/TestInboundDynamicTable.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: httpcomponents/httpcore/trunk/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/hpack/TestInboundDynamicTable.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision

Propchange: httpcomponents/httpcore/trunk/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/hpack/TestInboundDynamicTable.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: httpcomponents/httpcore/trunk/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/hpack/TestOutboundDynamicTable.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/hpack/TestOutboundDynamicTable.java?rev=1734137&view=auto
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/hpack/TestOutboundDynamicTable.java (added)
+++ httpcomponents/httpcore/trunk/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/hpack/TestOutboundDynamicTable.java Tue Mar  8 20:04:26 2016
@@ -0,0 +1,70 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF 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.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.hc.core5.http2.hpack;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class TestOutboundDynamicTable {
+
+    @Test
+    public void testBasics() throws Exception {
+
+        final OutboundDynamicTable table = new OutboundDynamicTable();
+        Assert.assertEquals(Integer.MAX_VALUE, table.getMaxSize());
+        Assert.assertEquals(0, table.getCurrentSize());
+
+        final HPackHeader header1 = new HPackHeader("h", "1");
+        table.add(header1);
+        Assert.assertEquals(1, table.dynamicLength());
+        Assert.assertEquals(61, table.staticLength());
+        Assert.assertEquals(62, table.length());
+        Assert.assertSame(header1, table.getHeader(62));
+        Assert.assertEquals(34, table.getCurrentSize());
+    }
+
+    @Test
+    public void testEviction() throws Exception {
+
+        final OutboundDynamicTable table = new OutboundDynamicTable();
+
+        table.add(new HPackHeader("h", "1"));
+        table.add(new HPackHeader("h", "2"));
+
+        Assert.assertEquals(68, table.getCurrentSize());
+
+        table.setMaxSize(256);
+        Assert.assertEquals(68, table.getCurrentSize());
+        table.setMaxSize(67);
+        Assert.assertEquals(34, table.getCurrentSize());
+        table.setMaxSize(10);
+        Assert.assertEquals(0, table.getCurrentSize());
+    }
+
+}
+

Propchange: httpcomponents/httpcore/trunk/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/hpack/TestOutboundDynamicTable.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: httpcomponents/httpcore/trunk/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/hpack/TestOutboundDynamicTable.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision

Propchange: httpcomponents/httpcore/trunk/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/hpack/TestOutboundDynamicTable.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/Header.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/Header.java?rev=1734137&r1=1734136&r2=1734137&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/Header.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/Header.java Tue Mar  8 20:04:26 2016
@@ -48,4 +48,14 @@ public interface Header {
      */
     String getValue();
 
+    /**
+     * Returns {@code true} if the header should be considered sensitive.
+     * <p>
+     * Some encoding schemes such as HPACK impose restrictions on encoded
+     * representation of sensitive headers.
+     *
+     * @since 5.0
+     */
+    boolean isSensitive();
+
 }

Modified: httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/message/BasicHeader.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/message/BasicHeader.java?rev=1734137&r1=1734136&r2=1734137&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/message/BasicHeader.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/message/BasicHeader.java Tue Mar  8 20:04:26 2016
@@ -46,17 +46,32 @@ public class BasicHeader implements Head
 
     private final String name;
     private final String value;
+    private final boolean sensitive;
 
     /**
-     * Constructor with name and value
+     * Constructor with sensitivity flag
      *
      * @param name the header name
      * @param value the header value, taken as the value's {@link #toString()}.
+     * @param sensitive sensitive flag
+     *
+     * @since 5.0
      */
-    public BasicHeader(final String name, final Object value) {
+    public BasicHeader(final String name, final Object value, final boolean sensitive) {
         super();
         this.name = Args.notNull(name, "Name");
         this.value = Objects.toString(value, null);
+        this.sensitive = sensitive;
+    }
+
+    /**
+     * Default constructor
+     *
+     * @param name the header name
+     * @param value the header value, taken as the value's {@link #toString()}.
+     */
+    public BasicHeader(final String name, final Object value) {
+        this(name, value, false);
     }
 
     @Override
@@ -70,6 +85,11 @@ public class BasicHeader implements Head
     }
 
     @Override
+    public boolean isSensitive() {
+        return this.sensitive;
+    }
+
+    @Override
     public String toString() {
         final StringBuilder buf = new StringBuilder();
         buf.append(this.name).append(": ");

Modified: httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/message/BufferedHeader.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/message/BufferedHeader.java?rev=1734137&r1=1734136&r2=1734137&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/message/BufferedHeader.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/message/BufferedHeader.java Tue Mar  8 20:04:26 2016
@@ -115,6 +115,11 @@ public class BufferedHeader implements F
     }
 
     @Override
+    public boolean isSensitive() {
+        return false;
+    }
+
+    @Override
     public int getValuePos() {
         return this.valuePos;
     }