Usage Guide
View SourceOverview
erlang_qpack provides QPACK header compression for HTTP/3 as specified in RFC 9204. It supports both stateless encoding (static table only) and stateful encoding with dynamic table management.
Stateless API
The simplest way to use qpack is with the stateless API, which only uses the static table:
%% Encode headers
Headers = [
{<<":method">>, <<"GET">>},
{<<":path">>, <<"/">>},
{<<":scheme">>, <<"https">>},
{<<":authority">>, <<"example.com">>}
],
Encoded = qpack:encode(Headers).
%% Decode headers
{ok, Decoded} = qpack:decode(Encoded).Stateful API
For better compression, use the stateful API with a dynamic table:
%% Create state with 4KB dynamic table
State0 = qpack:new(#{max_dynamic_size => 4096}),
%% Encode headers - entries may be added to dynamic table
{Encoded, State1} = qpack:encode(Headers, State0),
%% Decode headers
{{ok, Decoded}, State2} = qpack:decode(Encoded, State1).Stream Tracking
For HTTP/3 integration with section acknowledgment:
%% Encode with stream ID tracking
{Encoded, State1} = qpack:encode(Headers, StreamId, State0),
%% Get the Required Insert Count for this encoding
RIC = qpack:get_last_ric(State1).Encoder Stream
The encoder generates instructions for the decoder's dynamic table:
%% Get pending encoder instructions to send to peer
Instructions = qpack:get_encoder_instructions(State),
%% Clear instructions after sending
State1 = qpack:clear_encoder_instructions(State).Decoder Stream
Process instructions from the peer:
%% Process encoder instructions from peer (updates dynamic table)
{ok, State1} = qpack:process_encoder_instructions(Data, State0),
%% Handle incomplete data (streaming)
case qpack:process_encoder_instructions(Data, State0) of
{ok, State1} ->
%% All instructions processed
State1;
{incomplete, Remaining, State1} ->
%% Buffer Remaining, wait for more data
{Remaining, State1};
{error, Reason} ->
%% Protocol error
error(Reason)
end.Sending Acknowledgments
%% Acknowledge a decoded header section
Ack = qpack:encode_section_ack(StreamId),
%% Increment known received count
Increment = qpack:encode_insert_count_increment(Count).Processing Acknowledgments
%% Process decoder instructions from peer
{ok, State1} = qpack:process_decoder_instructions(Data, State0).Blocked Decoding
When a header block references dynamic table entries the decoder hasn't received yet:
case qpack:decode(Data, State) of
{{ok, Headers}, State1} ->
%% Successfully decoded
{Headers, State1};
{{blocked, RIC}, State1} ->
%% Need to wait for encoder instructions up to RIC
%% Buffer the header block and retry after processing more instructions
{blocked, RIC, Data, State1};
{{error, Reason}, State1} ->
%% Decoding error
error(Reason)
end.Dynamic Table Management
%% Get current capacity
Capacity = qpack:get_dynamic_capacity(State),
%% Set new capacity (generates encoder instruction)
State1 = qpack:set_dynamic_capacity(NewCapacity, State),
%% Get insert count
InsertCount = qpack:get_insert_count(State),
%% Get known received count (acknowledged by peer)
KRC = qpack:get_known_received_count(State).Huffman Encoding
The Huffman module can be used directly:
%% Encode
Encoded = qpack_huffman:encode(<<"www.example.com">>),
%% Decode
Decoded = qpack_huffman:decode(Encoded),
%% Decode with validation (RFC 7541 Section 5.2)
{ok, Decoded} = qpack_huffman:decode_safe(Encoded),
%% Check encoded size
Size = qpack_huffman:encoded_size(Data).Error Handling
QPACK operations can return errors:
%% Decoding errors
{{error, incomplete}, State} %% Truncated input
{{error, {invalid_static_index, N}}, State}
{{error, {invalid_dynamic_index, N}}, State}
%% Instruction processing errors
{error, {invalid_increment, N, InsertCount}}
{error, invalid_encoder_instruction}
{error, invalid_decoder_instruction}Best Practices
- Reuse state - Create one state per connection and reuse it for all requests/responses
- Process instructions promptly - Process encoder/decoder stream data as it arrives
- Handle blocked decoding - Buffer blocked header blocks and retry after receiving more encoder instructions
- Size the dynamic table appropriately - 4KB-16KB is typical for most applications
- Send acknowledgments - Send section acknowledgments to allow the encoder to reference new entries