hpack

tape
import hpack from "hpack";
import str from "str";

var d: hpack.Decoder = hpack.decoder(4096);
defer d.free();
var fields: hpack.Vec_Header = hpack.vec_Header_new();
defer fields.free();
d.decode(block, 65536, &fields) or { return 1; };     // block: a HEADERS frame's header block
for (i in 0..fields.len()) { io.println("{fields.get_ref(i).name}: {fields.get_ref(i).value}"); }

var out: str.Builder = str.builder();
defer out.free();
hpack.encode_table_reset(&out);                         // first block of a connection
hpack.encode(&out, ":status", "200", false);
hpack.encode(&out, "set-cookie", "id=42", true);        // never indexed

hpack reads and writes the header blocks of HTTP/2 (RFC 7541). You don’t need it to make requests: http’s Client uses it through h2. It is here for code that handles HTTP/2 frames itself, a test server for instance.

FunctionDoes
decoder(limit) -> DecoderA decoder whose dynamic table may grow to limit octets (what your SETTINGS_HEADER_TABLE_SIZE says; 4096 is the default)
d.decode(block, max_list, out)Decodes one whole block (HEADERS and its CONTINUATIONs), appending its fields to out in order
d.entries(), d.table_size()The dynamic table’s entries and size in octets
d.free()Releases the table
encode(out, name, value, sensitive)One field: a static table index when there is one for both, else a literal (never indexed when sensitive)
encode_table_reset(out)A table size update to 0: put it first in a connection’s first block
huffman_encode, huffman_decode, huffman_lenThe Huffman code of Appendix B
write_int, write_stringHPACK’s integers and string literals
tape
pub struct Header { name: string; value: string; }
pub enum HpackError : u8 { Truncated = 1; BadIndex = 2; BadInteger = 3; BadHuffman = 4; BadTableSize = 5; TooLarge = 6; }

A decoder belongs to one connection: blocks must be decoded in the order they came, every one of them, since each may change the table the next ones refer to. max_list limits the list as SETTINGS_MAX_HEADER_LIST_SIZE counts it (each field’s name and value plus 32): past it, the rest of the block is still decoded (the table stays right) but its fields are not kept, and decode returns TooLarge. Any other error means the table can no longer be trusted: end the connection.

The encoder keeps no table of its own, so it needs no state: each field is encoded on its own, and a string is Huffman coded when that makes it shorter. Names must be lowercase, as HTTP/2 requires.

Last modified: