Streams
The stream layer implements the HTTP/2 stream state machine per RFC 9113 §5. Each HTTP2Stream owns a state (StreamState), send and receive flow-control windows, and buffered request/response headers and data. The layer's functions move streams between states in response to received or sent HEADERS, DATA, and RST_STREAM frames.
Role signalling
The stream state machine itself is role-neutral: IDLE, OPEN, HALF_CLOSED_LOCAL, HALF_CLOSED_REMOTE, and CLOSED transitions work the same way from either side of the connection. The receive_* and send_* verbs describe direction from the caller's perspective, which reads naturally for either a server processing a request or a client processing a response.
The HTTP and gRPC semantic accessors (get_method, get_path, get_content_type, get_grpc_encoding, etc.) read request headers stored on the stream — in the current exercised code paths that means a server reading a request it received from a client. A client assembling request headers would set them directly on the stream and call send_headers!. Full client-role helpers land in Milestone 6.
State enum
PureHTTP2.StreamState — Module
StreamStateHTTP/2 stream states per RFC 7540 Section 5.1.
States
IDLE: Stream not yet usedRESERVED_LOCAL: Reserved by local PUSH_PROMISERESERVED_REMOTE: Reserved by remote PUSH_PROMISEOPEN: Active stream for both endpointsHALF_CLOSED_LOCAL: Local endpoint finished sendingHALF_CLOSED_REMOTE: Remote endpoint finished sendingCLOSED: Stream terminated
Error type
PureHTTP2.StreamError — Type
StreamError <: ExceptionError related to HTTP/2 stream processing.
Fields
stream_id::UInt32: Stream that caused the errorerror_code::UInt32: HTTP/2 error codemessage::String: Error description
Construction
PureHTTP2.HTTP2Stream — Type
HTTP2StreamRepresents an HTTP/2 stream with state machine and data buffers.
Fields
id::UInt32: Stream identifierstate::StreamState.T: Current statesend_window::Int: Send flow control windowrecv_window::Int: Receive flow control windowrequest_headers::Vector{Tuple{String, String}}: Request headersresponse_headers::Vector{Tuple{String, String}}: Response headerstrailers::Vector{Tuple{String, String}}: Trailing headersdata_buffer::IOBuffer: Accumulated dataheaders_complete::Bool: Whether header block is completeend_stream_received::Bool: Whether END_STREAM has been receivedend_stream_sent::Bool: Whether END_STREAM has been sentreset::Bool: Whether stream has been reset
Example
julia> using PureHTTP2
julia> stream = HTTP2Stream(UInt32(1));
julia> stream.state == StreamState.IDLE
true
julia> receive_headers!(stream, false);
julia> stream.state == StreamState.OPEN
true
julia> can_send(stream)
trueRole predicates
PureHTTP2.is_client_initiated — Function
is_client_initiated(stream_id::Integer) -> BoolCheck if a stream was initiated by the client (odd-numbered).
PureHTTP2.is_server_initiated — Function
is_server_initiated(stream_id::Integer) -> BoolCheck if a stream was initiated by the server (even-numbered).
Direction predicates
PureHTTP2.can_send — Function
can_send(stream::HTTP2Stream) -> BoolCheck if data can be sent on this stream.
can_send(controller::FlowController, stream_id::UInt32, size::Int) -> BoolCheck if data of the given size can be sent on the stream.
PureHTTP2.can_receive — Function
can_receive(stream::HTTP2Stream) -> BoolCheck if data can be received on this stream.
PureHTTP2.is_closed — Function
is_closed(stream::HTTP2Stream) -> BoolCheck if the stream is closed.
is_closed(conn::HTTP2Connection) -> BoolCheck if the connection is closed.
State transitions
PureHTTP2.receive_headers! — Function
receive_headers!(stream::HTTP2Stream, end_stream::Bool) -> NothingHandle receiving HEADERS frame.
PureHTTP2.send_headers! — Function
send_headers!(stream::HTTP2Stream, end_stream::Bool) -> NothingHandle sending HEADERS frame.
PureHTTP2.receive_data! — Function
receive_data!(stream::HTTP2Stream, data::Vector{UInt8}, end_stream::Bool) -> NothingHandle receiving DATA frame.
receive_data!(receiver::DataReceiver, stream_id::UInt32, frame::Frame) -> Vector{UInt8}Process a received DATA frame and return the payload. Generates WINDOWUPDATE frames if needed (call generatewindow_updates after).
PureHTTP2.send_data! — Function
send_data!(stream::HTTP2Stream, length::Int, end_stream::Bool) -> NothingHandle sending DATA frame (updates state only, doesn't store data).
PureHTTP2.receive_rst_stream! — Function
receive_rst_stream!(stream::HTTP2Stream, error_code::UInt32) -> NothingHandle receiving RST_STREAM frame.
PureHTTP2.send_rst_stream! — Function
send_rst_stream!(stream::HTTP2Stream, error_code::UInt32) -> NothingHandle sending RST_STREAM frame.
Window updates
PureHTTP2.update_send_window! — Function
update_send_window!(stream::HTTP2Stream, increment::Int) -> NothingUpdate the send window for flow control.
PureHTTP2.update_recv_window! — Function
update_recv_window!(stream::HTTP2Stream, increment::Int) -> NothingUpdate the receive window for flow control.
Data buffer
PureHTTP2.get_data — Function
get_data(stream::HTTP2Stream) -> Vector{UInt8}Get accumulated data from the stream buffer.
PureHTTP2.peek_data — Function
peek_data(stream::HTTP2Stream) -> Vector{UInt8}Peek at accumulated data without consuming it.
HTTP semantic accessors
These helpers read well-known HTTP/2 pseudo-headers and common headers from a stream's request_headers list.
PureHTTP2.get_header — Function
get_header(stream::HTTP2Stream, name::String) -> Union{String, Nothing}Get a request header value by name (case-insensitive).
PureHTTP2.get_headers — Function
get_headers(stream::HTTP2Stream, name::String) -> Vector{String}Get all request header values for a name (case-insensitive).
PureHTTP2.get_method — Function
get_method(stream::HTTP2Stream) -> Union{String, Nothing}Get the :method pseudo-header.
PureHTTP2.get_path — Function
get_path(stream::HTTP2Stream) -> Union{String, Nothing}Get the :path pseudo-header.
PureHTTP2.get_authority — Function
get_authority(stream::HTTP2Stream) -> Union{String, Nothing}Get the :authority pseudo-header.
PureHTTP2.get_content_type — Function
get_content_type(stream::HTTP2Stream) -> Union{String, Nothing}Get the content-type header.
gRPC convenience helpers
These are gRPC-specific shortcuts for reading headers that gRPC adds on top of HTTP/2. They exist in PureHTTP2.jl for historical reasons inherited from the original extraction from gRPCServer.jl (see upstream-bugs.md for the layering concern). A cleaner split would put them in a gRPC adapter rather than in PureHTTP2.jl itself; that refactor is deferred to a future milestone.
PureHTTP2.get_grpc_encoding — Function
get_grpc_encoding(stream::HTTP2Stream) -> Union{String, Nothing}Get the grpc-encoding header (request compression).
PureHTTP2.get_grpc_accept_encoding — Function
get_grpc_accept_encoding(stream::HTTP2Stream) -> Union{String, Nothing}Get the grpc-accept-encoding header (supported compression codecs).
PureHTTP2.get_grpc_timeout — Function
get_grpc_timeout(stream::HTTP2Stream) -> Union{String, Nothing}Get the grpc-timeout header.
PureHTTP2.get_metadata — Function
get_metadata(stream::HTTP2Stream) -> Vector{Tuple{String, String}}Get all custom metadata headers (non-pseudo, non-reserved).