HTTP2::Client
A reusable, origin-bound HTTP/2 client.
Constants
Default connection configuration for clients: keepalive on, so an
active connection detects a silent peer without a socket-level read
timeout tearing down idle or quiet-but-healthy streams. Used only as
the constructor default for connection_configuration — a
caller-supplied configuration is used exactly as given, never merged
with or overridden by this default.
The minimum per-connection slice #graceful_close ever passes to
Connection#graceful_close, even for a connection reached after
the shared deadline (see #graceful_close's doc comment) has
already elapsed. Connection#graceful_close rejects a
non-positive timeout outright (ArgumentError), so SOME positive
floor is required; this is deliberately tiny — a guard against
that ArgumentError, not a fairness guarantee that a connection
reached this late gets a meaningful chance to drain. A connection
reached with essentially no budget left either has nothing active
to wait for (drains immediately) or does, and immediately raises
Connection::DrainTimeoutError — both fast, bounded outcomes,
rather than an exception from #graceful_close itself.
Constructors
Creates a client bound to one http or https origin. Owned
connections are dialed lazily and scale under pool_configuration.
A supplied connection is used as-is, is owned by this client, and
remains fixed: it is not reconnected or evicted for idleness.
Supplying both connection and pool_configuration is invalid.
tls_context, whether supplied or defaulted, is used for every
https dial this client makes (#dial's single Connection.connect_tls
call reuses the SAME @tls_context for the client's whole
lifetime) and is configured for ALPN "h2" in place, unconditionally,
on every dial — see Connection.start_tls's doc comment for the
full contract, including why this is self-healing against anything
else that changes it between dials. The symmetric caveat: do not
share one tls_context with a different consumer (another
Client configured differently, or anything outside this library)
that needs a different, stable ALPN protocol on it — every dial
through this Client overwrites alpn_protocol back to "h2".
Instance methods
Extra field names, beyond the library's own built-in four
(authorization, proxy-authorization, cookie, set-cookie),
that must never be promoted to HPACK's compressed, indexed
representation or inserted into this client's connections' dynamic
tables (see Task 9's HPACK incremental-indexing change). A caller
with its own credential or secret header — x-api-key,
x-csrf-token, a bearer token carried under a non-standard name —
adds it here so it keeps the same literal-never-indexed treatment
RFC 7541 §7.1.3 reserves for that wire marker precisely so
intermediaries cannot promote it. Comparison is case-insensitive:
names are downcased once, here, when this client is constructed.
Empty by default: this is purely additive and cannot narrow the
built-in four, which stay unconditional.
Treat the returned Set as fixed once this client starts sending
requests. #request reads it directly on every call (no defensive
copy, so a request-heavy connection is not paying a repeated
allocation for a value that rarely changes) — mutating it
concurrently with an in-flight request is a data race under
-Dpreview_mt, and any entry added after construction must already
be lowercase, since nothing downcases it a second time. Any
mutation must happen before this client's first request.
True once #close or #graceful_close has been called — both set
the closed flag immediately when invoked, even while a
#graceful_close drain is still in progress, not only once
teardown finishes. A request made after this returns true fails
immediately with ClosedError, without dialing or touching the
network.
Sends a DELETE request and waits for its final response fields.
Sends a GET request and waits for its final response fields.
Gracefully drains all connections currently owned by this client.
timeout is a SHARED deadline across every connection, not a
per-connection budget: it is applied once, up front, and each
connection receives only whatever of it remains (floored
at MIN_GRACEFUL_CLOSE_TIMEOUT), so N connections that each need
a full drain still take roughly timeout in total rather than
N times timeout — a client with several retired connections
behind the current one closes in bounded time instead of one that
grows with however many connections happen to be pending.
Sends a HEAD request and waits for its final response fields.
Sends a OPTIONS request and waits for its final response fields.
Sends a PATCH request. IO bodies stream from their
current position. An IO body paired with an explicit
content-length header must EOF exactly at that declared length —
see Request#initialize for what happens, and the risk, if it
does not.
Sends a POST request. IO bodies stream from their
current position. An IO body paired with an explicit
content-length header must EOF exactly at that declared length —
see Request#initialize for what happens, and the risk, if it
does not.
Sends a PUT request. IO bodies stream from their
current position. An IO body paired with an explicit
content-length header must EOF exactly at that declared length —
see Request#initialize for what happens, and the risk, if it
does not.
Builds and sends a request for any HTTP method. See Request#initialize
for the EOF requirement on a sized IO body.
Sends a prepared request. The returned response body remains streaming.