Wraps a :class:QuicClientConnection (whose handshake must
already be complete -- 1-RTT keys installed) and drives H3
request/response exchanges on it. Multiplexes any number of
concurrent requests over the single QUIC connection: each
:meth:request opens its own bidi stream and registers a
:class:_PendingRequest; :meth:poll_responses demuxes one
QUIC burst across every in-flight stream.
send_request
def send_request(mut self, method: String, scheme: String, authority: String, path: String, headers: List[HpackHeader], body: List[UInt8], early: Bool = False) -> UInt64
Open a fresh bidi stream, write the request HEADERS [+ DATA] with FIN, and return the stream id the response will arrive on. Opens the control/QPACK streams first if not already open. When early the control/QPACK streams and the request ride 0-RTT (EarlyData) packets.
request
def request(mut self, method: String, scheme: String, authority: String, path: String, headers: List[HpackHeader], body: List[UInt8], early: Bool = False) -> UInt64
Multiplexed request: open a bidi stream, write HEADERS [+ DATA] with FIN, register an owned reader, and return the stream id. Any number of requests can be in flight at once over the one QUIC connection; drive them with :meth:poll_responses and collect with :meth:take_if_complete. When early the request is emitted at 0-RTT (EarlyData).
send_request_open
def send_request_open(mut self, method: String, scheme: String, authority: String, path: String, headers: List[HpackHeader], timeout_ms: Int = Int(30000), protocol: String = "") -> UInt64
Send request headers without FIN and register its response reader; a non-empty protocol makes it an extended CONNECT.
send_request_body
def send_request_body(mut self, sid: UInt64, body: List[UInt8], fin: Bool, timeout_ms: Int = Int(30000))
Write bounded DATA frames, pumping peer flow-control updates as needed.
poll_body
def poll_body(mut self, stream_id: UInt64, timeout_ms: Int = Int(100)) -> Http3BodyChunk
Streaming body read: poll one QUIC burst (fanning chunks out across every in-flight request so none stall), then move out the body bytes that became available on stream_id without ever buffering the whole body. Returns the new bytes plus whether the stream has finished (FIN). After done is True the trailers / final response are still retrievable with :meth:take_if_complete. An unknown / already-taken stream id returns an empty, done=True chunk.
fetch
def fetch(mut self, method: String, scheme: String, authority: String, path: String, headers: List[HpackHeader], body: List[UInt8], timeout_ms: Int = Int(100), max_polls: Int = Int(100)) -> Http3Response
Blocking single-request round-trip for the real-network client: send the request, then poll until the response is complete or the poll budget is exhausted. Raises on a budget timeout (the caller falls back to h2/h1). A thin wrapper over :meth:request/:meth:poll_responses.
fetch_0rtt
def fetch_0rtt(mut self, method: String, scheme: String, authority: String, path: String, headers: List[HpackHeader], body: List[UInt8], timeout_ms: Int = Int(100), max_polls: Int = Int(100)) -> Http3ZeroRttOutcome
Idempotent-only 0-RTT request with transparent 1-RTT fallback.
Gates strictly: a request is 0-RTT-eligible only when its
method is idempotent (:func:is_idempotent_method -- a replay
is safe) AND the connection resumed a session with rustls
early keys installed
(:meth:flare.quic.client.QuicClientConnection.early_data_ready).
A non-idempotent method, or a fresh (unresumed) connection,
is carried normally at 1-RTT.
The request is emitted in the first 0-RTT flight (the
control/QPACK streams + the request ride EarlyData packets via
:meth:QuicClientConnection.send_stream_early). After the
handshake, if the server rejected early data
(:meth:QuicClientConnection.early_data_accepted is False),
:meth:QuicClientConnection.finish_early_data transparently
replays the identical flight at 1-RTT on the same stream, the
request still completes, and the result reports
replayed=True -- the caller never observes a
rejected-0-RTT failure. used_0rtt is True only when the
server accepted the early data.
0-RTT packets are not wired into loss recovery, so a
lost-but-accepted 0-RTT packet is not retransmitted (fine on
the lossless loopback this client targets; the upgrade path is
the shared-pn loss-recovery registration in
:class:QuicClientConnection).