#[non_exhaustive]pub struct Capabilities {Show 19 fields
pub streaming_request_body: bool,
pub full_duplex: bool,
pub request_trailers: bool,
pub response_trailers: bool,
pub redirects: RedirectSupport,
pub cancel_on_drop: CancelSupport,
pub connection_reuse: ReuseSupport,
pub response_decompression: DecompressionSupport,
pub early_data: EarlyDataSupport,
pub tls_config: TlsSupport,
pub client_certs: bool,
pub proxy: bool,
pub owns_cookie_jar: bool,
pub owns_cache: bool,
pub version_select: bool,
pub version_reported: bool,
pub timeouts: TimeoutSupport,
pub informational_1xx: bool,
pub forbidden_request_headers: &'static [HeaderName],
}Expand description
What the transport can do in this process, right now.
A runtime fact, not a cfg!: one wasm binary runs in both Chrome
(streaming request body available since 131) and Safari (not available).
§Two kinds of field
Every field here is one of two things, and reading them as one kind is
what makes a field like proxy look dead when it is
not.
- A gate. The field guards a setting a caller made on the
Client, andClientBuilder::buildrefuses when the transport cannot honour it — the model this whole type exists for, taken fromwasi:http’s own setters returningresult<_, request-options-error::not-supported>. A gate with no branch is the silently ignored setting defect, and this project has closed four of them:redirects,owns_cookie_jar,owns_cacheand thetimeoutstriple each earned a branch the day the setting arrived. - A report. The field states a fact about the transport, and
nothing at the client level could refuse it, because the setting it
describes is configured on the transport.
proxy,client_certs,tls_config,early_data,connection_reuse,cancel_on_drop,full_duplex,streaming_request_body, the two trailer flags andversion_reportedare all this kind. Its reader is the caller.
A report is not a dead field. upgrade was deleted for having no
reader, and the difference is that its four variants encoded a
distinction with one reachable side — where a report has both values
reachable and answers a question only it can answer.
The classification is enforced rather than described:
every_capability_is_a_gate_or_a_report in this module destructures
the struct with no .., so a field added later is a compile error
until somebody decides which kind it is.
Fields (Non-exhaustive)§
This struct is marked as non-exhaustive
Struct { .. } syntax; cannot be matched against without a wildcard ..; and struct update syntax will not work.streaming_request_body: boolWhether a request body may be written as it is produced.
Reported. Client does not gate on it — see this type’s doc for
why some fields do and some do not — which is why
hclient-urlsession refuses a Streaming body with a typed error
of its own rather than relying on a check that does not happen.
full_duplex: boolWhether the response may begin arriving before the request body has finished. Reported.
request_trailers: boolReported.
response_trailers: boolReported.
redirects: RedirectSupportWho follows a redirect — see RedirectSupport.
A gate: RedirectPolicy and a redirect predicate are Client
settings, and RedirectSupport::Internal means the transport has
already followed the chain by the time anything is handed back, so
either setting would silently not apply.
cancel_on_drop: CancelSupportWhat dropping an in-flight execute future does — see
CancelSupport and the contract on
Transport::execute.
connection_reuse: ReuseSupportWhether a connection is reused across requests — see
ReuseSupport.
response_decompression: DecompressionSupportWhether the transport already decoded the response body’s
Content-Encoding — see DecompressionSupport.
early_data: EarlyDataSupportWhether the transport can put a marked request into TLS 1.3 early
data — see EarlyDataSupport, which says less than its name
suggests and says so at length.
tls_config: TlsSupportWhat TLS configuration this transport accepts — see TlsSupport.
Reported, not a gate. A Client has no TLS setting to refuse:
the trust store, the client certificate and the ALPN list are all
configured on the TlsConnect a transport was built with. See this
type’s own doc for the two kinds of field.
client_certs: boolWhether the TLS configuration this transport holds presents a client certificate.
Reported, for tls_config’s reason. Read off
TlsIdentity::presents_client_certs by the backends rather than
from a constant, which is what stopped one connector giving two
answers depending on which stack held it.
proxy: boolWhether this transport sends through a proxy.
Reported, and it will never be a gate. The
setting it would guard is Native::proxy, which is on the
transport that would answer the question, so there is nothing at
the client level to refuse. That makes it unlike
owns_cookie_jar, where the client owns
the setting and the transport owns the conflict.
It is not upgrade’s case either,
the four-variant enum deleted for having no reader: both values
here are reachable, and the reader is the caller — will my
requests go through a proxy is a question a diagnostic asks and
only this field answers.
Whether the transport keeps its own cookie jar: attaching Cookie
to outgoing requests and processing Set-Cookie on incoming ones,
without being asked.
true for hclient-fetch — the browser does both, and Cookie is
on that backend’s forbidden_request_headers, so a client-side jar
there would not merely be redundant, it would send every cookie
twice and store every Set-Cookie twice. false for
hclient-native and hclient-wasi.
§Why a bool and not an enum
The same question CancelSupport and ReuseSupport were made
to answer: a variant exists only if a caller decision turns on it.
This field answers exactly one decision — “do I run a jar of my own
for this transport?” — and it is binary. The two axes an enum would
add do not carry decisions:
- Who owns it (the browser, an ambient host) is the split
CancelSupportalready rejected once, for the same reason. - Attaching versus storing could in principle come apart, and in practice never has: a backend that attaches cookies it did not store, or stores cookies it will not attach, is not a shape any of the three backends here or any ambient HTTP API takes.
What it does not answer — deliberately, and this is where a third
state would arrive if it ever arrives — is whether a jar-owning
backend can be asked to stop, or its jar inspected. There is no
portable setting for either, so there is nothing to refuse. When a
client-level cookie setting exists, it earns its refusal here the
way RedirectSupport::Internal earned its variant: the setting,
the variant and the check_supported arm arrive together.
owns_cache: boolWhether the transport keeps its own HTTP response cache: serving a stored response instead of sending, and storing what it fetches, without being asked.
true for hclient-fetch — the browser has an HTTP cache and
applies it inside fetch(). false for hclient-native,
hclient-h3 and hclient-wasi, none of which stores a response
anywhere. wasi:http’s host may well have a cache; the guest
cannot see it, and a capability is a claim about what this code
does rather than about what is downstream of it — the same line
owns_cookie_jar holds for the same backend.
§This field had no reader for four verticals
It shipped in v0.1 as false everywhere but one backend, branched
on nowhere, and was on the same list version_select was rescued
from — a variant exists only if a caller decision turns on it. The
decision that arrived is ClientBuilder::cache, and a client-side
cache against a transport reporting true is an
UnsupportedCapability at build(), the same arm
owns_cookie_jar takes for a jar and RedirectSupport::Internal
takes for a redirect policy.
§Why a bool and not an enum
Self::owns_cookie_jar’s answer, one field up, applies verbatim:
this field settles exactly one decision — do I run a cache of my
own for this transport? — and it is binary. Who owns it is the
split CancelSupport rejected; storing versus serving could in
principle come apart and in practice never has.
What it deliberately does not answer is whether a cache-owning
backend can be asked to bypass, revalidate or clear. There is no
portable setting for any of the three — fetch()’s cache option
is a browser API a Transport seam has no counterpart for — so
there is nothing to refuse. That is where a third state would
arrive if it ever arrives.
version_select: boolWhether the transport honours a per-request RequireVersion
demand: reads it, and either serves the request over that version
or fails it with VersionNotAvailable before the head is
written.
§It says “honours”, not “chooses”
A transport that only ever speaks one version reports true if it
answers demands — hclient-h3 does, by proceeding on
RequireVersion(HTTP_3) and refusing everything else. Reporting
false there would make Client refuse the one demand it
trivially satisfies, which is the opposite of honest.
false is for a transport that cannot answer at all:
hclient-fetch and hclient-wasi neither select the version nor
learn it (both also report version_reported: false), so a demand
against either becomes an UnsupportedCapability from Client —
the same arm a RedirectPolicy against
RedirectSupport::Internal takes.
§Why this field exists
The rule is that a capability exists only if a caller decision
turns on it — RedirectSupport lost two variants to it.
RequireVersion is the decision this one answers, and it is the
reason the demand and this
field’s first true land in one change.
version_reported: boolWhether Response::version() is something the transport observed.
false says the value on the response is http’s builder default
standing in for a fact the backend never learned — the browser will
not tell a page which protocol it spoke, and wasi:http@0.3.0 has
no version concept at all.
The observability seam asks the same question one field over and
answers it in the event rather than here, because a
Hooks impl is handed an
Event and no capabilities:
Head::version is Some
exactly when this field is true. Two spellings of one fact, in
the two places that can each be read on their own.
timeouts: TimeoutSupport§informational_1xx: bool§forbidden_request_headers: &'static [HeaderName]Trait Implementations§
Source§impl Clone for Capabilities
impl Clone for Capabilities
Source§fn clone(&self) -> Capabilities
fn clone(&self) -> Capabilities
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more