示例#1
0
    def test_request_examples_with_huffman(self):
        """
        This section shows the same examples as the previous section, but
        using Huffman encoding for the literal values.
        """
        d = Decoder()

        # Patch the decoder to use the Request Huffman tables, not the Response
        # ones.
        d.huffman_coder = HuffmanDecoder(REQUEST_CODES, REQUEST_CODES_LENGTH)
        first_header_set = [(":method", "GET"), (":scheme", "http"), (":path", "/"), (":authority", "www.example.com")]
        first_header_table = first_header_set[::-1]
        first_data = b"\x82\x87\x86\x04\x8b\xdb\x6d\x88\x3e\x68\xd1\xcb\x12\x25\xba\x7f"

        assert d.decode(first_data) == set(first_header_set)
        assert list(d.header_table) == [(n.encode("utf-8"), v.encode("utf-8")) for n, v in first_header_table]

        # This request takes advantage of the differential encoding of header
        # sets.
        second_header_set = [
            (":method", "GET"),
            (":scheme", "http"),
            (":path", "/"),
            (":authority", "www.example.com"),
            ("cache-control", "no-cache"),
        ]
        second_header_table = second_header_set[::-1]
        second_data = b"\x1b\x86\x63\x65\x4a\x13\x98\xff"

        assert d.decode(second_data) == set(second_header_set)
        assert list(d.header_table) == [(n.encode("utf-8"), v.encode("utf-8")) for n, v in second_header_table]

        # This request has not enough headers in common with the previous
        # request to take advantage of the differential encoding.  Therefore,
        # the reference set is emptied before encoding the header fields.
        third_header_set = [
            (":method", "GET"),
            (":scheme", "https"),
            (":path", "/index.html"),
            (":authority", "www.example.com"),
            ("custom-key", "custom-value"),
        ]
        third_data = (
            b"\x80\x85\x8c\x8b\x84\x00\x88\x4e\xb0\x8b\x74\x97\x90\xfa\x7f\x89" b"\x4e\xb0\x8b\x74\x97\x9a\x17\xa8\xff"
        )

        assert d.decode(third_data) == set(third_header_set)
        # Don't check the header table here, it's just too complex to be
        # reliable. Check its length though.
        assert len(d.header_table) == 8
示例#2
0
    def test_can_decode_a_story(self, story):
        d = Decoder()

        # We support draft 5 of the HPACK spec.
        assert story['draft'] == 5

        if story['context'] == 'request':
            d.huffman_coder = HuffmanDecoder(REQUEST_CODES, REQUEST_CODES_LENGTH)

        for case in story['cases']:
            d.header_table_size = case['header_table_size']
            decoded_headers = d.decode(unhexlify(case['wire']))

            # The correct headers are a list of dicts, which is annoying.
            correct_headers = {(item[0], item[1]) for header in case['headers'] for item in header.items()}
            assert correct_headers == decoded_headers
示例#3
0
    def test_can_encode_a_story_with_huffman(self, raw_story):
        d = Decoder()
        e = Encoder()

        if raw_story['context'] == 'request':
            d.huffman_coder = HuffmanDecoder(REQUEST_CODES, REQUEST_CODES_LENGTH)
        else:
            e.huffman_coder = HuffmanEncoder(RESPONSE_CODES, RESPONSE_CODES_LENGTH)

        for case in raw_story['cases']:
            # The input headers are a list of dicts, which is annoying.
            input_headers = {(item[0], item[1]) for header in case['headers'] for item in header.items()}

            encoded = e.encode(input_headers, huffman=True)
            decoded_headers = d.decode(encoded)

            assert input_headers == decoded_headers
示例#4
0
    def test_can_decode_a_story(self, story):
        d = Decoder()

        # We support draft 5 of the HPACK spec.
        assert story['draft'] == 5

        if story['context'] == 'request':
            d.huffman_coder = HuffmanDecoder(REQUEST_CODES,
                                             REQUEST_CODES_LENGTH)

        for case in story['cases']:
            d.header_table_size = case['header_table_size']
            decoded_headers = d.decode(unhexlify(case['wire']))

            # The correct headers are a list of dicts, which is annoying.
            correct_headers = {(item[0], item[1])
                               for header in case['headers']
                               for item in header.items()}
            assert correct_headers == decoded_headers
示例#5
0
    def test_can_encode_a_story_with_huffman(self, raw_story):
        d = Decoder()
        e = Encoder()

        if raw_story['context'] == 'request':
            d.huffman_coder = HuffmanDecoder(REQUEST_CODES,
                                             REQUEST_CODES_LENGTH)
        else:
            e.huffman_coder = HuffmanEncoder(RESPONSE_CODES,
                                             RESPONSE_CODES_LENGTH)

        for case in raw_story['cases']:
            # The input headers are a list of dicts, which is annoying.
            input_headers = {(item[0], item[1])
                             for header in case['headers']
                             for item in header.items()}

            encoded = e.encode(input_headers, huffman=True)
            decoded_headers = d.decode(encoded)

            assert input_headers == decoded_headers
示例#6
0
    def test_request_examples_with_huffman(self):
        """
        This section shows the same examples as the previous section, but
        using Huffman encoding for the literal values.
        """
        d = Decoder()

        # Patch the decoder to use the Request Huffman tables, not the Response
        # ones.
        d.huffman_coder = HuffmanDecoder(REQUEST_CODES, REQUEST_CODES_LENGTH)
        first_header_set = [
            (
                ':method',
                'GET',
            ),
            (
                ':scheme',
                'http',
            ),
            (
                ':path',
                '/',
            ),
            (':authority', 'www.example.com'),
        ]
        first_header_table = first_header_set[::-1]
        first_data = (
            b'\x82\x87\x86\x04\x8b\xdb\x6d\x88\x3e\x68\xd1\xcb\x12\x25\xba\x7f'
        )

        assert d.decode(first_data) == set(first_header_set)
        assert list(d.header_table) == [(n.encode('utf-8'), v.encode('utf-8'))
                                        for n, v in first_header_table]

        # This request takes advantage of the differential encoding of header
        # sets.
        second_header_set = [
            (
                ':method',
                'GET',
            ),
            (
                ':scheme',
                'http',
            ),
            (
                ':path',
                '/',
            ),
            (
                ':authority',
                'www.example.com',
            ),
            ('cache-control', 'no-cache'),
        ]
        second_header_table = second_header_set[::-1]
        second_data = b'\x1b\x86\x63\x65\x4a\x13\x98\xff'

        assert d.decode(second_data) == set(second_header_set)
        assert list(d.header_table) == [(n.encode('utf-8'), v.encode('utf-8'))
                                        for n, v in second_header_table]

        # This request has not enough headers in common with the previous
        # request to take advantage of the differential encoding.  Therefore,
        # the reference set is emptied before encoding the header fields.
        third_header_set = [
            (
                ':method',
                'GET',
            ),
            (
                ':scheme',
                'https',
            ),
            (
                ':path',
                '/index.html',
            ),
            (
                ':authority',
                'www.example.com',
            ),
            ('custom-key', 'custom-value'),
        ]
        third_data = (
            b'\x80\x85\x8c\x8b\x84\x00\x88\x4e\xb0\x8b\x74\x97\x90\xfa\x7f\x89'
            b'\x4e\xb0\x8b\x74\x97\x9a\x17\xa8\xff')

        assert d.decode(third_data) == set(third_header_set)
        # Don't check the header table here, it's just too complex to be
        # reliable. Check its length though.
        assert len(d.header_table) == 8