nhttp_h2_frame (nhttp_lib v1.0.0)
View SourceHTTP/2 binary frame encoding and decoding.
This module implements RFC 9113 Section 4-6 binary framing layer. It provides zero-copy parsing using binary pattern matching and efficient encoding using iolists.
Decoding
case nhttp_h2_frame:decode(Data) of
{ok, Frame, Rest} -> handle_frame(Frame), decode(Rest);
{more, MinBytes} -> wait_for_data(MinBytes);
{error, Error} -> handle_error(Error)
end.Encoding
{ok, Frame} = nhttp_h2_frame:headers(StreamId, fin, fin, HeaderBlock),
ok = ssl:send(Socket, Frame).
Summary
Functions
Encode a CONTINUATION frame.
Encode a DATA frame.
Decode a single frame from binary data. Returns {ok, Frame, BytesConsumed} where BytesConsumed is the number of bytes consumed from the input. Use split_at/2 to get the remaining buffer. Uses default max frame size (16384 bytes).
Decode a single frame with custom max frame size. The max frame size should come from peer's SETTINGS_MAX_FRAME_SIZE.
Decode all complete frames from binary data. Returns {ok, Frames, BytesConsumed} with list of decoded frames.
Decode settings payload (for use in connection layer).
Encode a GOAWAY frame.
Encode a HEADERS frame without priority.
Encode a HEADERS frame with priority.
Split header block into HEADERS + CONTINUATION frames if needed.
Encode a PING frame.
Encode a PING acknowledgment.
HTTP/2 connection preface magic string.
Encode a PRIORITY frame.
Encode a PUSH_PROMISE frame.
Encode a RST_STREAM frame.
Encode a SETTINGS frame.
Encode a SETTINGS acknowledgment.
Split buffer at position, returning the remainder. This is the intentional single allocation point for callers.
Encode a connection-level WINDOW_UPDATE frame.
Encode a stream-level WINDOW_UPDATE frame.
Types
-type decode_all_result() :: {ok, [t()], BytesConsumed :: non_neg_integer()} | {error, decode_error()}.
-type decode_error() :: {connection_error, nhttp_h2:error_code(), Reason :: binary()} | {stream_error, nhttp_lib:stream_id(), nhttp_h2:error_code(), Reason :: binary()}.
-type decode_result() :: {ok, t(), BytesConsumed :: pos_integer()} | {more, MinBytes :: pos_integer()} | {error, decode_error()}.
-type t() :: {data, nhttp_lib:stream_id(), nhttp_h2:fin(), Payload :: binary()} | {headers, nhttp_lib:stream_id(), nhttp_h2:fin(), nhttp_h2:fin(), HeaderBlock :: binary()} | {headers, nhttp_lib:stream_id(), nhttp_h2:fin(), nhttp_h2:fin(), nhttp_h2:priority(), HeaderBlock :: binary()} | {priority, nhttp_lib:stream_id(), nhttp_h2:priority()} | {rst_stream, nhttp_lib:stream_id(), nhttp_h2:error_code()} | {settings, nhttp_h2:settings()} | settings_ack | {push_promise, nhttp_lib:stream_id(), nhttp_h2:fin(), PromisedStreamId :: nhttp_lib:stream_id(), HeaderBlock :: binary()} | {ping, OpaqueData :: binary()} | {ping_ack, OpaqueData :: binary()} | {goaway, LastStreamId :: nhttp_lib:stream_id(), nhttp_h2:error_code(), DebugData :: binary()} | {window_update, Increment :: pos_integer()} | {window_update, nhttp_lib:stream_id(), Increment :: pos_integer()} | {continuation, nhttp_lib:stream_id(), nhttp_h2:fin(), HeaderBlock :: binary()} | {unknown, Type :: non_neg_integer()} | preface.
Functions
-spec continuation(StreamId, EndHeaders, HeaderBlock) -> {ok, iodata()} when StreamId :: nhttp_lib:stream_id(), EndHeaders :: nhttp_h2:fin(), HeaderBlock :: iodata().
Encode a CONTINUATION frame.
-spec data(StreamId, EndStream, Payload) -> {ok, iodata()} when StreamId :: nhttp_lib:stream_id(), EndStream :: nhttp_h2:fin(), Payload :: iodata().
Encode a DATA frame.
-spec decode(Data :: binary()) -> decode_result().
Decode a single frame from binary data. Returns {ok, Frame, BytesConsumed} where BytesConsumed is the number of bytes consumed from the input. Use split_at/2 to get the remaining buffer. Uses default max frame size (16384 bytes).
-spec decode(Data :: binary(), MaxFrameSize :: pos_integer()) -> decode_result().
Decode a single frame with custom max frame size. The max frame size should come from peer's SETTINGS_MAX_FRAME_SIZE.
-spec decode_all(binary()) -> decode_all_result().
Decode all complete frames from binary data. Returns {ok, Frames, BytesConsumed} with list of decoded frames.
-spec decode_settings_payload(binary()) -> {ok, nhttp_h2:settings()} | {error, decode_error()}.
Decode settings payload (for use in connection layer).
-spec goaway(LastStreamId, ErrorCode, DebugData) -> {ok, iodata()} when LastStreamId :: nhttp_lib:stream_id(), ErrorCode :: nhttp_h2:error_code(), DebugData :: iodata().
Encode a GOAWAY frame.
-spec headers(StreamId, EndStream, EndHeaders, HeaderBlock) -> {ok, iodata()} when StreamId :: nhttp_lib:stream_id(), EndStream :: nhttp_h2:fin(), EndHeaders :: nhttp_h2:fin(), HeaderBlock :: iodata().
Encode a HEADERS frame without priority.
-spec headers(StreamId, EndStream, EndHeaders, Priority, HeaderBlock) -> {ok, iodata()} when StreamId :: nhttp_lib:stream_id(), EndStream :: nhttp_h2:fin(), EndHeaders :: nhttp_h2:fin(), Priority :: nhttp_h2:priority(), HeaderBlock :: iodata().
Encode a HEADERS frame with priority.
-spec headers_with_continuation(StreamId, EndStream, HeaderBlock, MaxFrameSize) -> {ok, iodata()} when StreamId :: nhttp_lib:stream_id(), EndStream :: nhttp_h2:fin(), HeaderBlock :: iodata(), MaxFrameSize :: pos_integer().
Split header block into HEADERS + CONTINUATION frames if needed.
Encode a PING frame.
Encode a PING acknowledgment.
-spec preface() -> {ok, binary()}.
HTTP/2 connection preface magic string.
-spec priority(StreamId, Priority) -> {ok, iodata()} when StreamId :: nhttp_lib:stream_id(), Priority :: nhttp_h2:priority().
Encode a PRIORITY frame.
-spec push_promise(StreamId, PromisedStreamId, EndHeaders, HeaderBlock) -> {ok, iodata()} when StreamId :: nhttp_lib:stream_id(), PromisedStreamId :: nhttp_lib:stream_id(), EndHeaders :: nhttp_h2:fin(), HeaderBlock :: iodata().
Encode a PUSH_PROMISE frame.
-spec rst_stream(StreamId, ErrorCode) -> {ok, binary()} when StreamId :: nhttp_lib:stream_id(), ErrorCode :: nhttp_h2:error_code().
Encode a RST_STREAM frame.
-spec settings(Settings :: nhttp_h2:settings()) -> {ok, iodata()}.
Encode a SETTINGS frame.
-spec settings_ack() -> {ok, binary()}.
Encode a SETTINGS acknowledgment.
-spec split_at(binary(), non_neg_integer()) -> binary().
Split buffer at position, returning the remainder. This is the intentional single allocation point for callers.
-spec window_update(Increment :: pos_integer()) -> {ok, binary()}.
Encode a connection-level WINDOW_UPDATE frame.
-spec window_update(StreamId, Increment) -> {ok, binary()} when StreamId :: nhttp_lib:stream_id(), Increment :: pos_integer().
Encode a stream-level WINDOW_UPDATE frame.