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.StreamStateModule
StreamState

HTTP/2 stream states per RFC 7540 Section 5.1.

States

  • IDLE: Stream not yet used
  • RESERVED_LOCAL: Reserved by local PUSH_PROMISE
  • RESERVED_REMOTE: Reserved by remote PUSH_PROMISE
  • OPEN: Active stream for both endpoints
  • HALF_CLOSED_LOCAL: Local endpoint finished sending
  • HALF_CLOSED_REMOTE: Remote endpoint finished sending
  • CLOSED: Stream terminated
source

Error type

PureHTTP2.StreamErrorType
StreamError <: Exception

Error related to HTTP/2 stream processing.

Fields

  • stream_id::UInt32: Stream that caused the error
  • error_code::UInt32: HTTP/2 error code
  • message::String: Error description
source

Construction

PureHTTP2.HTTP2StreamType
HTTP2Stream

Represents an HTTP/2 stream with state machine and data buffers.

Fields

  • id::UInt32: Stream identifier
  • state::StreamState.T: Current state
  • send_window::Int: Send flow control window
  • recv_window::Int: Receive flow control window
  • request_headers::Vector{Tuple{String, String}}: Request headers
  • response_headers::Vector{Tuple{String, String}}: Response headers
  • trailers::Vector{Tuple{String, String}}: Trailing headers
  • data_buffer::IOBuffer: Accumulated data
  • headers_complete::Bool: Whether header block is complete
  • end_stream_received::Bool: Whether END_STREAM has been received
  • end_stream_sent::Bool: Whether END_STREAM has been sent
  • reset::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)
true
source

Role predicates

Direction predicates

PureHTTP2.can_sendFunction
can_send(stream::HTTP2Stream) -> Bool

Check if data can be sent on this stream.

source
can_send(controller::FlowController, stream_id::UInt32, size::Int) -> Bool

Check if data of the given size can be sent on the stream.

source
PureHTTP2.is_closedFunction
is_closed(stream::HTTP2Stream) -> Bool

Check if the stream is closed.

source
is_closed(conn::HTTP2Connection) -> Bool

Check if the connection is closed.

source

State transitions

PureHTTP2.receive_data!Function
receive_data!(stream::HTTP2Stream, data::Vector{UInt8}, end_stream::Bool) -> Nothing

Handle receiving DATA frame.

source
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).

source
PureHTTP2.send_data!Function
send_data!(stream::HTTP2Stream, length::Int, end_stream::Bool) -> Nothing

Handle sending DATA frame (updates state only, doesn't store data).

source

Window updates

Data buffer

PureHTTP2.get_dataFunction
get_data(stream::HTTP2Stream) -> Vector{UInt8}

Get accumulated data from the stream buffer.

source
PureHTTP2.peek_dataFunction
peek_data(stream::HTTP2Stream) -> Vector{UInt8}

Peek at accumulated data without consuming it.

source

HTTP semantic accessors

These helpers read well-known HTTP/2 pseudo-headers and common headers from a stream's request_headers list.

PureHTTP2.get_headerFunction
get_header(stream::HTTP2Stream, name::String) -> Union{String, Nothing}

Get a request header value by name (case-insensitive).

source
PureHTTP2.get_headersFunction
get_headers(stream::HTTP2Stream, name::String) -> Vector{String}

Get all request header values for a name (case-insensitive).

source
PureHTTP2.get_pathFunction
get_path(stream::HTTP2Stream) -> Union{String, Nothing}

Get the :path pseudo-header.

source

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_metadataFunction
get_metadata(stream::HTTP2Stream) -> Vector{Tuple{String, String}}

Get all custom metadata headers (non-pseudo, non-reserved).

source