silk.http.exchange_native.
Native TCP, Unix socket, and TLS connections for HTTP clients.
When to use#
Most code uses silk.http.client_native or silk.http.fetch_native, which call this module.
Use it directly to control the connection:
withConnectionopens a connection to one origin and lends it to a handler. The handler sends its exchanges withsilk.http.exchange.withUnixConnectiondoes the same through a Unix socket, for example to a local daemon.withProxyRouteconnects through a route fromsilk.http.proxy.acquireOwnedandacquireUnixOwnedreturn the connection, for a pool. The caller closes it.
Details#
A connection does these steps:
It resolves the host, and tries the addresses until one connects.
For an
httpsorigin, it does TLS. The certificate is checked against the original origin, not aHostfield and not a Unix path.
The deadline in Options is absolute, and each step gets it unchanged. When the handler
returns or fails, the connection is closed. Closing does not flush and does not send a TLS close
message.
withConnection and withUnixConnection load trust from the TrustSource service for an
https origin. The acquire functions and withProxyRoute take a trust snapshot that you
prepare.
Errors#
NativeExchangeErrorfor options that are not valid, a deadline that cannot be honored, missing trust, or a failed ALPN negotiation.ResolverError,NativeSocketError,ConnectionError, andIdentityErrorfrom resolution, the socket, TLS, and the certificate check.ExchangeErrorand the error of the handler.
Gotchas#
Resolution of a host name cannot stop at a deadline. A host name with a deadline fails with
UnsupportedDeadlinebefore any contact. An IP address with a deadline is accepted.Only Darwin on aarch64, and Linux with GNU libc on x86_64 or aarch64, are supported. On other targets, a call that is used fails to compile. Unused imports and
Optionsstill compile.
Examples#
Check a deadline before contact#
import silk.http.exchange_native { NativeExchangeError, Options, preflight }
import silk.http.origin { Origin, OriginError }
import silk.core.option { Option }
import silk.core.result { Result }
import silk.system.system_clock { Instant, SystemClock }
import silk.uri.uri { Uri }
import silk.uri.reference { ParseError }
fn origin(text: string<'static>) -> Option<Origin> {
let uri = match Uri.parse(text) {
Result<Uri, ParseError>.Success { value } => value
Result<Uri, ParseError>.Failure { error: _ } => {
return Option<Origin>.none()
}
}
return match Origin.fromUri(&uri) {
Result<Origin, OriginError>.Success { value } => Option<Origin>.some(value)
Result<Origin, OriginError>.Failure { error: _ } => Option<Origin>.none()
}
}
fn passes(checked: Result<(), NativeExchangeError>) -> bool {
return match move checked {
Result.Success { value: _ } => true
Result.Failure { error: _ } => false
}
}
pub fn main() -> i32 {
let named = match origin("https://example.com/") {
Option.Some { value } => value
Option.None => {
return 1
}
}
let numeric = match origin("http://127.0.0.1:8080/") {
Option.Some { value } => value
Option.None => {
return 1
}
}
let mut options = Options.defaults()
// With no deadline, both origins pass.
if !passes(preflight(&named, &options)) {
return 1
}
// The resolver cannot stop at a deadline, so a host name with a deadline fails.
options.deadline = Option<Instant>.some(SystemClock.make(5, 0))
let rejected = match move preflight(&named, &options) {
Result.Success { value: _ } => false
Result.Failure { error } => match move error {
NativeExchangeError.UnsupportedDeadline => true
_ => false
}
}
if !rejected {
return 1
}
// An IP address needs no resolver, so the deadline is accepted.
if !passes(preflight(&numeric, &options)) {
return 1
}
return 0
}Import as HttpExchangeNative with import silk.http.exchange_native as HttpExchangeNative.
Public declarations: 16.
NativeRoute#
pub struct NativeRouteHow a native connection reaches its peer: direct TCP, or a Unix socket path.
Implementation Copy for NativeRoute#
impl Copy for NativeRouteImplementation NativeRoute#
impl NativeRouteMethod isUnix#
pub fn isUnix(self: &Self) -> boolReturns whether the route uses a Unix socket.
Method path#
pub fn path<'a>(self: &'a Self) -> &'a [u8]Returns the Unix socket path, or an empty slice for direct TCP.
NativeExchangeError#
pub union NativeExchangeErrorThe error of a native HTTP connection, before or during TLS.
InvalidConnectOptions#
InvalidConnectOptionsThe poll interval or the attempt count of Options is out of range. See
silk.net.socket_native.
UnsupportedDeadline#
UnsupportedDeadlineA host name must be resolved, and there is a deadline. Resolution cannot stop at a deadline.
TrustRequired#
TrustRequiredThe origin uses https, and no trust snapshot was given.
AlpnMismatch#
AlpnMismatchThe policy is RequiredHttp11, and the server did not select http/1.1.
Field error#
pub error: ConnectionErrorThe TLS error.
Implementation Debug for NativeExchangeError#
impl Debug for NativeExchangeErrorOperation debug#
effect fn debug(self: &Self, formatter: &mut Formatter) -> () ! WriterError ? &mut WriterWrites the name of the variant and its fields, such as InvalidConnectOptions.
AlpnPolicy#
pub enum AlpnPolicyHow TLS negotiates the HTTP version (ALPN).
OptionalHttp11#
OptionalHttp11Offers http/1.1. The server can select it or select nothing.
RequiredHttp11#
RequiredHttp11Offers http/1.1. If the server does not select it, the connection fails with AlpnMismatch.
Http10#
Http10Sends no ALPN extension. Use it for a server that supports only HTTP/1.0.
Options#
pub struct OptionsThe settings of a native connection. Start from Options.defaults.
Details#
The deadline is absolute, and each step of a connection gets it unchanged: the check, the name resolution, the connect, and TLS.
Gotchas#
A host name with a deadline fails with UnsupportedDeadline before any contact, because
resolution cannot stop at a deadline. An IP address with a deadline is accepted.
Field maximumAddresses#
pub maximumAddresses: usizeThe maximum number of addresses to keep from resolution.
Field family#
pub family: FamilySelectionThe address families to use: IPv4, IPv6, or both.
Field noDelay#
pub noDelay: boolWhether to disable Nagle's algorithm on the socket.
Field pollIntervalNanoseconds#
pub pollIntervalNanoseconds: u64The time between checks while a socket connects. It is 1 nanosecond through 1 second.
Field maximumAttempts#
pub maximumAttempts: usizeThe maximum number of connection attempts. It is 1 through 1024.
Field deadline#
pub deadline: Option<Instant>The absolute deadline for the whole operation, on the monotonic clock. It must be None when
the host of the origin is a name, because the name lookup cannot stop at a deadline. Then the
operation fails with UnsupportedDeadline before any I/O.
Field handshakeNanoseconds#
pub handshakeNanoseconds: u64The maximum duration of the TLS handshake.
Field tls#
pub tls: ClientLimitsThe storage limits of the TLS client.
Field trust#
pub trust: TrustLoadLimitsThe limits for loading trust anchors.
Field alpn#
pub alpn: AlpnPolicyHow TLS negotiates the HTTP version.
Implementation Options#
impl OptionsAssociated function defaults#
pub fn defaults() -> OptionsReturns the default settings.
They are: 16 addresses, any family, Nagle on, a 1 ms poll interval, 64 attempts, no deadline,
30 seconds for the handshake, and OptionalHttp11.
NativeTransport#
pub struct NativeTransportThe transport of a native HTTP connection. It owns its socket or TLS connection.
NativeRouteProvider#
pub struct NativeRouteProviderThe plain socket of a connection through withProxyRoute.
Details#
It is connected to the peer that the route selects: the origin or the proxy. After a CONNECT
tunnel, TLS uses the same socket. The HTTP side and the byte side share one closed state, so the
socket is never used by two owners.
Implementation NativeRouteProvider#
impl NativeRouteProviderImplementation HttpTransport for NativeRouteProvider#
impl HttpTransport for NativeRouteProviderOperation readSomeRaw#
readSomeRaw: NativeRouteProvider.readHttpOperation writeSomeRaw#
writeSomeRaw: NativeRouteProvider.writeHttpOperation flush#
flush: NativeRouteProvider.flushHttpOperation close#
close: NativeRouteProvider.closeHttpImplementation ByteDuplex for NativeRouteProvider#
impl ByteDuplex for NativeRouteProviderOperation readSomeRaw#
readSomeRaw: NativeRouteProvider.readBytesOperation writeSomeRaw#
writeSomeRaw: NativeRouteProvider.writeBytesOperation writeSomeVectoredRaw#
writeSomeVectoredRaw: NativeRouteProvider.writeBytesVectoredOperation flushRaw#
flushRaw: NativeRouteProvider.flushBytesOperation shutdownWriteRaw#
shutdownWriteRaw: NativeRouteProvider.shutdownBytesOperation closeRaw#
closeRaw: NativeRouteProvider.closeBytesacquireOwned#
pub effect fn acquireOwned(
origin: Origin,
options: Options,
limits: Limits,
preparedTrust: Option<TrustSnapshot>,
acquisitionDeadline: Option<Instant>,
) -> Connection<NativeTransport>
! NativeExchangeError | ExchangeError | ResolverError | NativeSocketError | ConnectionError | IdentityError | OutOfMemoryError
? &mut Allocator | &mut MonotonicClock | &mut SystemClock | &mut RandomOpens a direct TCP or HTTPS connection to origin, and returns it.
Details#
The opening deadline is the earlier of options.deadline and acquisitionDeadline. For
https, it uses preparedTrust and checks the certificate against origin. The returned
connection keeps no deadline. Close it, or give it to another owner such as a pool.
Errors#
NativeExchangeError.TrustRequirediforiginuseshttpsandpreparedTrustis none.NativeSocketError.Timeoutif the deadline has passed.UnsupportedDeadlineif the host oforiginis a name and a deadline is set.ResolverError,NativeSocketError,ConnectionError, andIdentityErrorfrom resolution, the socket, TLS, and the certificate check.
Gotchas#
Only Darwin on aarch64, and Linux with GNU libc on x86_64 or aarch64, are supported. On other targets, a call fails to compile.
admitUnixRoute#
pub effect fn admitUnixRoute(path: &[u8]) -> NativeRoute ! NativeSocketErrorReturns a route for the Unix socket at path. It copies path and does not connect.
Errors#
NativeSocketError if path is too long for a socket address on the target.
acquireUnixOwned#
pub effect fn acquireUnixOwned(
path: &[u8],
origin: Origin,
options: Options,
limits: Limits,
preparedTrust: Option<TrustSnapshot>,
acquisitionDeadline: Option<Instant>,
) -> Connection<NativeTransport>
! NativeExchangeError | ExchangeError | NativeSocketError | ConnectionError | IdentityError | OutOfMemoryError
? &mut Allocator | &mut MonotonicClock | &mut SystemClock | &mut RandomOpens an HTTP or HTTPS connection to origin through the Unix socket at path, and returns it.
Details#
path selects only the socket. For https, it uses preparedTrust, and TLS checks the
certificate against origin. The opening deadline is the earlier of options.deadline and
acquisitionDeadline. The returned connection keeps no deadline. Close it, or give it to
another owner such as a pool.
Gotchas#
Only Darwin on aarch64, and Linux with GNU libc on x86_64 or aarch64, are supported. On other targets, a call fails to compile.
withConnection#
pub effect<'env> fn withConnection<
A,
E,
?R,
H: ConnectionHandler<NativeTransport, A, E ? R> + 'env,
'env,
>(origin: Origin, options: Options, limits: Limits, handler: H) -> A
! E | ExchangeError | NativeExchangeError | ResolverError | NativeSocketError | ConnectionError | IdentityError | TrustSourceError | OutOfMemoryError
? R | &mut Allocator | &mut MonotonicClock | &mut SystemClock | &mut Random | &mut TrustSource
where R in Without<R, HttpTransport>Opens a connection to origin, lends it to handler, and closes it after.
Details#
For https, it loads trust from the TrustSource service before it connects, and checks the
certificate against origin. A Host field never changes the identity that is checked. The
deadline in options is absolute, and each step gets it unchanged. When the handler returns or
fails, the connection is closed. Closing does not flush and does not send a TLS close message.
Errors#
UnsupportedDeadlineif the host oforiginis a name andoptions.deadlineis set.NativeExchangeErrorfor options that are not valid, a deadline that cannot be honored, missing trust, or a failed ALPN negotiation.ResolverError,NativeSocketError,ConnectionError, andIdentityErrorfrom resolution, the socket, TLS, and the certificate check.ExchangeErrorfrom the HTTP connection.TrustSourceErrorif trust cannot be loaded.The error of the handler.
Gotchas#
Only Darwin on aarch64, and Linux with GNU libc on x86_64 or aarch64, are supported. On other targets, a call fails to compile.
withUnixConnection#
pub effect<'env> fn withUnixConnection<
A,
E,
?R,
H: ConnectionHandler<NativeTransport, A, E ? R> + 'env,
'env,
>(path: &[u8], origin: Origin, options: Options, limits: Limits, handler: H) -> A
! E | ExchangeError | NativeExchangeError | NativeSocketError | ConnectionError | IdentityError | TrustSourceError | OutOfMemoryError
? R | &mut Allocator | &mut MonotonicClock | &mut SystemClock | &mut Random | &mut TrustSource
where R in Without<R, HttpTransport>Opens a connection to origin through the Unix socket at path, lends it to handler, and
closes it after.
Details#
path selects only the socket. For https, it loads trust from the TrustSource service and
checks the certificate against origin. The deadline in options is absolute, and each step
gets it unchanged. When the handler returns or fails, the connection is closed. Closing does not
flush and does not send a TLS close message.
Errors#
NativeExchangeErrorfor options that are not valid, a deadline that cannot be honored, missing trust, or a failed ALPN negotiation.ResolverError,NativeSocketError,ConnectionError, andIdentityErrorfrom resolution, the socket, TLS, and the certificate check.TrustSourceErrorif trust cannot be loaded.ExchangeErrorand the error of the handler.
Gotchas#
Only Darwin on aarch64, and Linux with GNU libc on x86_64 or aarch64, are supported. On other targets, a call fails to compile.
withProxyRoute#
pub effect<'env> fn withProxyRoute<
'configuration,
A,
E,
?R,
H: RouteHandler<'configuration, NativeRouteProvider, A, E ? R> + 'env,
'env,
>(
route: Route<'configuration>,
options: Options,
limits: Limits,
preparedTrust: Option<TrustSnapshot>,
handler: H,
) -> A
! E | ProxyError | ExchangeError | NativeExchangeError | ResolverError | NativeSocketError | ConnectionError | IdentityError | OutOfMemoryError
? R | &mut Allocator | &mut MonotonicClock | &mut SystemClock | &mut Random
where R in Without<R, ByteDuplex>, R in Without<R, HttpTransport>Connects through route, lends the connection to handler, and closes it after.
Details#
It connects only to the peer that the route selects: the origin for Direct, or the proxy for
Forward and Tunnel. For Tunnel, it sends CONNECT, then does TLS with the origin through
the tunnel. options.deadline is used unchanged for all steps. limits applies to the HTTP
connection and to the CONNECT exchange.
Errors#
ProxyErrorif the proxy rejectsCONNECT, or the route is not valid.NativeExchangeError.TrustRequiredif the origin useshttpsandpreparedTrustis none.The errors of resolution, the socket, TLS, and the handler.
Implementation NativeTransport#
impl NativeTransportMethod route#
pub fn route(self: &Self) -> NativeRouteReturns the route of the transport.
Implementation HttpTransport for NativeTransport#
impl HttpTransport for NativeTransportOperation readSomeRaw#
readSomeRaw: NativeTransport.readOperation writeSomeRaw#
writeSomeRaw: NativeTransport.writeOperation flush#
flush: NativeTransport.flushOutputOperation close#
close: NativeTransport.closeLeasepreflight#
pub fn preflight(origin: &Origin, options: &Options) -> Result<(), NativeExchangeError>Checks if a connection to origin with options can start. It does no I/O.
Errors#
UnsupportedDeadline if the host of origin is a name and options.deadline is set.
preflightProxyRoute#
pub fn preflightProxyRoute<'configuration>(route: &Route<'configuration>, options: &Options) -> Result<
Origin,
ProxyError | NativeExchangeError,
>Returns the peer that route connects to, and checks that a connection to it with options can
start. It does no I/O.
The peer is the origin for Direct, and the proxy for Forward and Tunnel.
Errors#
ProxyErrorifrouteis not valid.UnsupportedDeadlineif the host of the peer is a name andoptions.deadlineis set.
NativeRedirectClient#
pub struct NativeRedirectClient<'configuration, 'policy, A, HandlerError, ?HandlerRequirements>Opens a new native connection for each attempt of a redirect operation.
Details#
silk.http.fetch_native uses it with silk.http.redirect. For each attempt, it selects the
route for the current URI again, checks the request and the route before contact, and uses the
deadline of the operation. Each https attempt loads fresh trust. A tunnel still checks the
certificate of the original origin.
Implementation NativeRedirectClient<'configuration, 'policy, A, HandlerError, HandlerRequirements>#
impl<'configuration, 'policy, A, HandlerError, ?HandlerRequirements> NativeRedirectClient<
'configuration,
'policy,
A,
HandlerError,
HandlerRequirements,
>Associated function make#
pub fn make(route: Route<'configuration>, options: Options, limits: Limits) -> NativeRedirectClient<
'configuration,
'policy,
A,
HandlerError,
HandlerRequirements,
>Returns a client that starts from route, with options and limits for each attempt.
Implementation NativeRedirectClient<'configuration, 'policy, A, HandlerError, HandlerRequirements>#
impl<'configuration, 'policy, A, HandlerError, ?HandlerRequirements> NativeRedirectClient<
'configuration,
'policy,
A,
HandlerError,
HandlerRequirements,
>Implementation AttemptClient<'policy, NativeRouteProvider, A, HandlerError, ProxyError | RequestError | ValueError | OriginError | ExchangeError | NativeExchangeError | ResolverError | NativeSocketError | ConnectionError | IdentityError | TrustSourceError | OutOfMemoryError, &mut Allocator | &mut MonotonicClock | &mut SystemClock | &mut Random | &mut TrustSource, HandlerRequirements> for NativeRedirectClient<'configuration, 'policy, A, HandlerError, HandlerRequirements>#
impl<'configuration, 'policy, A, HandlerError, ?HandlerRequirements> AttemptClient<
'policy,
NativeRouteProvider,
A,
HandlerError,
ProxyError | RequestError | ValueError | OriginError | ExchangeError | NativeExchangeError | ResolverError | NativeSocketError | ConnectionError | IdentityError | TrustSourceError | OutOfMemoryError,
&mut Allocator | &mut MonotonicClock | &mut SystemClock | &mut Random | &mut TrustSource,
HandlerRequirements,
> for NativeRedirectClient<'configuration, 'policy, A, HandlerError, HandlerRequirements>Operation withAttempt#
withAttempt: NativeRedirectClient.withAttemptroute#
pub fn route(connection: &Connection<NativeTransport>) -> NativeRouteReturns the route of a native connection.
Category: HTTP.
Profiles: aarch64-apple-darwin, aarch64-unknown-linux-gnu, aarch64-unknown-linux-gnu-no-libc, x86_64-unknown-linux-gnu, x86_64-unknown-linux-gnu-no-libc, wasm32-unknown-unknown, wasm32-wasip1, wasm32-wasip2.