# 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.