Skip to content

vshakitskiy/alpacki

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

34 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

alpacki

Package Version Hex Docs

alpacki is an HPACK (RFC 7541) implementation for Gleam. It handles header compression for HTTP/2 connections.

gleam add alpacki@2

Encoding and decoding

Each side of an HTTP/2 connection maintains its own dynamic table. Headers are encoded into compact header block fragments for transmission, and decoded back on the receiving side.

Encoding from a list of headers:

let table = alpacki.new_dynamic(4096)
let headers = [
  alpacki.HeaderField(":method", "GET", alpacki.WithIndexing),
  alpacki.HeaderField(":path", "/", alpacki.WithIndexing),
  alpacki.HeaderField(":scheme", "https", alpacki.WithIndexing),
]

let #(data, table) =
  alpacki.encode_header_block(headers, table, huffman: True)

Decoding headers from raw bits:

let table = alpacki.new_dynamic(4096)
let assert Ok(#(headers, table)) = alpacki.decode_header_block(data, table)

The Indexing type on each HeaderField controls the wire representation: WithIndexing adds the entry to the dynamic table for future reference, WithoutIndexing sends it without storing, and NeverIndexed signals that the value is sensitive and must never be compressed by intermediaries.

Resizing the dynamic table

When the remote peer sends a SETTINGS frame that changes SETTINGS_HEADER_TABLE_SIZE, call resize_dynamic on the encoder's table. The next encode_header_block call will automatically prepend the required size update instructions before the header fields.

// Remote peer reduced the table size to 2048 bytes.
let encoder_table = alpacki.resize_dynamic(encoder_table, 2048)

// The next encoded block will start with a size update instruction.
let #(data, encoder_table) =
  alpacki.encode_header_block(headers, encoder_table, huffman: True)

On the decoder side, expect_table_size_update can optionally be used to enforce the peer sends the size update, decode_header_block processes any size update instructions at the start of a block automatically.

Primitives

Beyond the high-level API, alpacki exposes the individual HPACK primitives. If you are building on primitives instead of encode_header_block / decode_header_block, you are responsible for emitting dynamic table size updates yourself with encode_table_size_update when the maximum table size changes.

Integer:

let encoded = alpacki.encode_integer(120, prefix: 5)
let assert Ok(#(120, <<>>)) = alpacki.decode_integer(encoded, prefix: 5)

String Literal:

let encoded = alpacki.encode_string_literal(<<"Wibble":utf8>>, huffman: False)
let assert Ok(#(decoded, <<>>)) = alpacki.decode_string_literal(encoded)

Huffman:

let encoded = alpacki.encode_huffman(<<"www.example.com":utf8>>)
let assert Ok(decoded) = alpacki.decode_huffman(encoded)

Further documentation can be found at https://hexdocs.pm/alpacki.

About

🦙 HPACK protocol (RFC 7541) in Gleam

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages