HPACK (RFC 7541)

- Header Compression for HTTP/2

http/1.1

Request

GET /path HTTP/1.1
Host: www.example.com
Accept-Encoding: gzip, deflate,br

http/1.1

Response

HTTP/1.1 200 OK
Accept-Ranges: bytes
Content-Length: 438
Content-Type: text/html; charset=UTF-8
Content-Encoding: gzip

PROS

  • Easy to support, works both ways

CONS

  • Different algorithms have different implementations
  • Does not support header compression
  • Multiple security issues, via chosen-plaintext attacks.

Unrelated: There's also TLS compression (don't use it)

hpack

core ideas

  1. most web requests will have fairly similar headers.
  2. should be fast.
  3. reduce complexity or implementation issues.
  4. ignore encoding, focus on a correct decoding.
  5. "streaming"

important-to-note

  1. Headers can be repeated
  2. Headers are an Ordered List

Static Table

Generated by frequency of header fields on popular websites.

+-------+-----------------------------+---------------+
| Index | Header Name                 | Header Value  |
+-------+-----------------------------+---------------+
| 1     | :authority                  |               |
| 2     | :method                     | GET           |
| 3     | :method                     | POST          |
| 4     | :path                       | /             |
| 5     | :path                       | /index.html   |
| 6     | :scheme                     | http          |
| 7     | :scheme                     | https         |
| 8     | :status                     | 200           |
| 9     | :status                     | 204           |
| 10    | :status                     | 206           |
| 11    | :status                     | 304           |

Index Address Space

   <----------  Index Address Space ---------->
   <-- Static  Table -->  <-- Dynamic Table -->
   +---+-----------+---+  +---+-----------+---+
   | 1 |    ...    | s |  |s+1|    ...    |s+k|
   +---+-----------+---+  +---+-----------+---+
                          ^                   |
                          |                   V
                   Insertion Point      Dropping Point

Representation

A header field(=name+value) can be represented as:

an index

is a reference to either:

  • the static table
  • the dynamic table

or a literal (1)

the header field name can be represented

  • literally
  • a reference to either tables

or a literal (2)

the header value is represented literally and

  1. ADD it to the dynamic table
  2. DON'T ADD it to the dynamic table
  3. NEVER ADD it to the dynamic table

a literal

can be presented in two forms:

  1. directly
  2. using a Huffman code

decisions while parsing

  • do a table lookup
    • static table
    • dynamic table
  • read it literally
    • directly
    • using the huffman code

Almost is encoded as a integer or as a string

literal representation

   0   1   2   3   4   5   6   7
 +---+---+---+---+---+---+---+---+
 | H |    String Length (7+)     |
 +---+---------------------------+
 |  String Data (Length octets)  |
 +-------------------------------+

H=1 -> Huffman Encoded
H=0 -> Encoded as a "string"

index representation

This is simple table lookup

   0   1   2   3   4   5   6   7
 +---+---+---+---+---+---+---+---+
 | 1 |        Index (7+)         |
 +---+---------------------------+

Static Huffman Code

                                                code
                  code as bits                 as hex   len
sym              aligned to MSB                aligned   in
                                               to LSB   bits
(  0)  |11111111|11000                             1ff8  [13]
(  1)  |11111111|11111111|1011000                7fffd8  [23]
(  2)  |11111111|11111111|11111110|0010         fffffe2  [28]
(  3)  |11111111|11111111|11111110|0011         fffffe3  [28]

dynamic table updates

  • You can add entries to the table
  • You can set the table size dynamically

This mechanism can be used to completely clear entries from the
dynamic table by setting a maximum size of 0, which can subsequently
be restored.