Browse the docs

silk.http.proxy.

Proxy settings for HTTP clients, and the choice of a route for each origin.

When to use#

Make a ProxyConfig with ProxyConfig.fromUri or ProxyConfig.make. Then call selectRoute for each origin. silk.http.request and silk.http.exchange use the Route to prepare and send the request.

Details#

selectRoute does not allocate or use the network. It returns:

  • Direct for an origin in the BypassPolicy.

  • Tunnel for an HTTPS origin. The client sends CONNECT to the proxy, then does TLS with the origin through the tunnel.

  • Forward for a plain HTTP origin. The client sends the request to the proxy with the full URI as target.

The configuration owns its Basic token. A route writes the Proxy-Authorization value only into a buffer that you give. classifyConnect reads the response of the proxy to CONNECT.

Errors#

Gotchas#

Only plain http proxies are supported. An https proxy URI fails with UnsupportedProxyTransport. This module reads no environment variables; NativeHttp.fromEnvironment in silk.http.client_native reads HTTPS_PROXY and the others.

Examples#

Select routes#

silk
import silk.mem.allocator { Allocator, OutOfMemoryError }
import silk.core.effect { Effect }
import silk.http.origin { Origin, OriginError }
import silk.http.proxy {
  BypassPolicy,
  ProxyAuth,
  ProxyAuthContextId,
  ProxyConfig,
  ProxyConfigId,
  ProxyError,
  Route,
  RouteMode,
  selectRoute
}
import silk.core.option { Option }
import silk.core.result { Result }
import silk.uri.uri { Uri }
import silk.uri.reference { ParseError }

fn origin(text: string<'static>) -> Origin {
  let uri = match Uri.parse(text) {
    Result<Uri, ParseError>.Success { value } => value
    Result<Uri, ParseError>.Failure { error: _ } => {
      Intrinsic.trap("unexpected failure")
      return origin(text)
    }
  }
  return match Origin.fromUri(&uri) {
    Result<Origin, OriginError>.Success { value } => value
    Result<Origin, OriginError>.Failure { error: _ } => {
      Intrinsic.trap("unexpected failure")
      return origin(text)
    }
  }
}

effect fn program() -> i32
  ! OutOfMemoryError
  ? &mut Allocator {
  // The token is the Base64 of "user:pass".
  let auth = match run ProxyAuth.preparedBasic(ProxyAuthContextId.make(1), b"dXNlcjpwYXNz") {
    Result<ProxyAuth, ProxyError>.Success { value } => move value
    Result<ProxyAuth, ProxyError>.Failure { error: _ } => {
      return 1
    }
  }
  let local = [origin("http://localhost:8080")]
  let bypass = match run BypassPolicy.copy(&local) {
    Result<BypassPolicy, ProxyError>.Success { value } => move value
    Result<BypassPolicy, ProxyError>.Failure { error: _ } => {
      return 1
    }
  }
  let config = match ProxyConfig.fromUri(
    ProxyConfigId.make(1),
    "http://proxy.example:3128",
    move auth,
    move bypass,
    4096,
  ) {
    Result<ProxyConfig, ProxyError>.Success { value } => move value
    Result<ProxyConfig, ProxyError>.Failure { error: _ } => {
      return 1
    }
  }

  // HTTPS goes through a CONNECT tunnel, plain HTTP is forwarded, and the bypass origin is direct.
  let secure = selectRoute(&config, origin("https://example.com/"))
  let plain = selectRoute(&config, origin("http://example.com/"))
  let direct = selectRoute(&config, origin("http://localhost:8080/"))
  if Route.mode(&secure) != RouteMode.Tunnel || Route.mode(&plain) != RouteMode.Forward
    || Route.mode(&direct) != RouteMode.Direct {
    return 1
  }
  let mut header: [u8; 64] = [0; 64]
  let length = match Route.writeProxyAuthorizationInto(&plain, &mut header) {
    Option<usize>.Some { value } => value
    Option<usize>.None => 0
  }

  // "Basic dXNlcjpwYXNz"
  if length != 18 || header[0] != 66 {
    return 1
  }
  return 0
}

effect fn failed<E>(error: E) -> i32 {
  drop error
  return 1
}

pub fn main() -> i32 {
  let mut allocator = Allocator.systemAllocatorProvider()
  return run Effect.catchAll(program(), failed) |> Effect.provideMut<Allocator>(&mut allocator)
}

Import as ProxyConfig with import silk.http.proxy { ProxyConfig }.

Public declarations: 15.

ProxyComponent#

silk
pub enum ProxyComponent

The setting that is not valid.

ProxyUri#

silk
ProxyUri

The proxy URI.

ProxyEndpoint#

silk
ProxyEndpoint

The proxy host and port.

Authentication#

silk
Authentication

The Basic token.

Bypass#

silk
Bypass

The bypass list.

Configuration#

silk
Configuration

The configuration as a whole.

Route#

silk
Route

A route that was used for the wrong operation, or for another origin.

Implementation Debug for ProxyComponent#

silk
impl Debug for ProxyComponent

Operation debug#

silk
effect fn debug(self: &Self, formatter: &mut Formatter) -> () ! WriterError ? &mut Writer

Writes the name of the variant, such as ProxyUri.

ProxyLimit#

silk
pub enum ProxyLimit

A limit of a proxy configuration.

AuthenticationBytes#

silk
AuthenticationBytes

The maximum length of the Basic token.

BypassOrigins#

silk
BypassOrigins

The maximum number of bypass origins, 64.

OwnedConfigurationBytes#

silk
OwnedConfigurationBytes

The maxOwnedConfigBytes of the configuration.

Implementation Debug for ProxyLimit#

silk
impl Debug for ProxyLimit

Operation debug#

silk
effect fn debug(self: &Self, formatter: &mut Formatter) -> () ! WriterError ? &mut Writer

Writes the name of the variant, such as AuthenticationBytes.

ProxyReason#

silk
pub union ProxyReason

The rule that failed.

InvalidProxyUri#

silk
InvalidProxyUri

The proxy URI is not valid, or has a part that is not allowed, such as a path or user information.

InvalidProxyPort#

silk
InvalidProxyPort

The proxy port is 0.

InvalidAuthentication#

silk
InvalidAuthentication

The Basic token is empty, or is not canonical Base64.

SizeOverflow#

silk
SizeOverflow

A size does not fit in usize.

LimitExceeded#

silk
LimitExceeded

A value exceeded a limit.

Field limit#

silk
pub limit: ProxyLimit

The limit.

Field allowed#

silk
pub allowed: usize

The value of the limit.

Field attempted#

silk
pub attempted: usize

The value that was found.

UnsupportedProxyTransport#

silk
UnsupportedProxyTransport

The proxy URI uses https, which is not supported.

InvalidRoute#

silk
InvalidRoute

The route mode or its origin does not fit the operation.

Implementation Debug for ProxyReason#

silk
impl Debug for ProxyReason

Operation debug#

silk
effect fn debug(self: &Self, formatter: &mut Formatter) -> () ! WriterError ? &mut Writer

Writes the name of the variant and its fields, such as InvalidProxyUri.

ProxyAdmissionError#

silk
pub struct ProxyAdmissionError

The error for a setting that is not valid. It holds no credentials.

Field component#

silk
pub component: ProxyComponent

The setting.

Field reason#

silk
pub reason: ProxyReason

The rule that failed.

Implementation Debug for ProxyAdmissionError#

silk
impl Debug for ProxyAdmissionError

Operation debug#

silk
effect fn debug(self: &Self, formatter: &mut Formatter) -> () ! WriterError ? &mut Writer

Writes the fields, as ProxyAdmissionError { component: ..., reason: ... }.

ProxyError#

silk
pub union ProxyError

The error from proxy settings or from a CONNECT response. For a setting that is not valid, it has a ProxyAdmissionError and holds no credentials. If the proxy rejects CONNECT, it has the response head.

Admission#

silk
Admission

A setting or a route is not valid.

Field error#

silk
pub error: ProxyAdmissionError

The error.

ProxyMetadataLimit#

silk
ProxyMetadataLimit

The CONNECT response head is too large to copy.

ProxyAuthenticationRequired#

silk
ProxyAuthenticationRequired

The proxy answered 407. The copy keeps only the status, the reason, and the Proxy-Authenticate fields.

Field response#

silk
pub response: OwnedResponseHead

The copy of the response head.

ProxyRejected#

silk
ProxyRejected

The proxy answered with another status that is not 2xx. The copy keeps all fields.

Field response#

silk
pub response: OwnedResponseHead

The copy of the response head.

InvalidConnectResponse#

silk
InvalidConnectResponse

classifyConnect was called before a final response.

Implementation Debug for ProxyError#

silk
impl Debug for ProxyError

Operation debug#

silk
effect fn debug(self: &Self, formatter: &mut Formatter) -> () ! WriterError ? &mut Writer

Writes the name of the variant and its fields, such as Admission { ... }.

ProxyConfigId#

silk
pub struct ProxyConfigId

A number that you choose to identify a configuration, for example in a pool key. It is not secret.

ProxyAuthContextId#

silk
pub struct ProxyAuthContextId

A number that you choose to identify a set of credentials, for example in a pool key. It is not secret.

ProxyAuth#

silk
pub union ProxyAuth

The credentials for the proxy.

None#

silk
None

No credentials.

Basic#

silk
Basic

A Basic token.

BypassPolicy#

silk
pub struct BypassPolicy

The origins that do not use the proxy. An origin matches only with the same scheme, host, and port.

ProxyConfig#

silk
pub struct ProxyConfig

The settings of a proxy: its host and port, its credentials, and the bypass list.

When to use#

Make one with ProxyConfig.fromUri or ProxyConfig.make. Then call selectRoute for each origin.

Details#

The configuration owns its Basic token. A route writes the Proxy-Authorization value only into a buffer that you give.

Gotchas#

Only plain http proxies are supported. An https proxy URI fails with UnsupportedProxyTransport. This module reads no environment variables; NativeHttp.fromEnvironment in silk.http.client_native reads HTTPS_PROXY and the others.

RouteMode#

silk
pub enum RouteMode

How a request goes to an origin.

Direct#

silk
Direct

Directly to the origin.

Forward#

silk
Forward

To the proxy, with the full URI as target.

Tunnel#

silk
Tunnel

Through a CONNECT tunnel at the proxy, then TLS with the origin.

Route#

silk
pub union Route<'configuration>

The route for one origin, from selectRoute.

Details#

Direct connects to the origin. Tunnel is for an HTTPS origin: the client sends CONNECT to the proxy, then does TLS with the origin through the tunnel. Forward is for a plain HTTP origin: the client sends the request to the proxy with the full URI as target.

Direct#

silk
Direct

Go directly to an origin in the bypass list.

Field origin#

silk
pub origin: Origin

The origin.

Forward#

silk
Forward

Send plain HTTP through the proxy.

Field origin#

silk
pub origin: Origin

The plain HTTP origin.

Tunnel#

silk
Tunnel

Open a tunnel through the proxy for TLS with the origin.

Field origin#

silk
pub origin: Origin

The HTTPS origin. TLS checks its certificate.

RouteKey#

silk
pub struct RouteKey

A key that identifies a route, for example for a connection pool. It has no credentials.

Implementation Copy for ProxyReason#

silk
impl Copy for ProxyReason

Implementation Copy for ProxyAdmissionError#

silk
impl Copy for ProxyAdmissionError

Implementation Copy for ProxyConfigId#

silk
impl Copy for ProxyConfigId

Implementation Copy for ProxyAuthContextId#

silk
impl Copy for ProxyAuthContextId

Implementation Copy for Route<'configuration>#

silk
impl<'configuration> Copy for Route<'configuration>

Implementation Copy for RouteKey#

silk
impl Copy for RouteKey

Implementation ProxyError#

silk
impl ProxyError

Associated function invalidRoute#

silk
pub fn invalidRoute() -> ProxyError

Returns the InvalidRoute error.

Implementation ProxyConfigId#

silk
impl ProxyConfigId

Associated function make#

silk
pub fn make(value: u64) -> ProxyConfigId

Returns the identity for value.

Method equals#

silk
pub fn equals(self: &Self, other: &Self) -> bool

Returns true if the two identities have the same value.

Implementation ProxyAuthContextId#

silk
impl ProxyAuthContextId

Associated function make#

silk
pub fn make(value: u64) -> ProxyAuthContextId

Returns the identity for value.

Method equals#

silk
pub fn equals(self: &Self, other: &Self) -> bool

Returns true if the two identities have the same value.

Implementation ProxyAuth#

silk
impl ProxyAuth

Associated function none#

silk
pub fn none(contextId: ProxyAuthContextId) -> ProxyAuth

Returns credentials with no token.

Associated function preparedBasic#

silk
pub effect fn preparedBasic(
    contextId: ProxyAuthContextId,
    token: &[u8],
  ) -> Result<ProxyAuth, ProxyError> ! OutOfMemoryError ? &mut Allocator

Checks and copies token, the Base64 of user:password. It must be canonical Base64, and at most 4096 bytes.

Method contextId#

silk
pub fn contextId(self: &Self) -> ProxyAuthContextId

Returns the identity of the credentials.

Method ownedBytes#

silk
pub fn ownedBytes(self: &Self) -> usize

Returns the length of the token, or 0.

Implementation BypassPolicy#

silk
impl BypassPolicy

Associated function copy#

silk
pub effect fn copy(origins: &[Origin]) -> Result<BypassPolicy, ProxyError>
  ! OutOfMemoryError
  ? &mut Allocator

Copies up to 64 origins into a bypass list.

Method contains#

silk
pub fn contains(self: &Self, origin: &Origin) -> bool

Returns true if origin has the same scheme, host, and port as an origin in the list.

Method ownedBytes#

silk
pub fn ownedBytes(self: &Self) -> usize

Returns the memory of the list, in bytes.

Implementation ProxyConfig#

silk
impl ProxyConfig

Associated function make#

silk
pub fn make(
    id: ProxyConfigId,
    proxyHost: Host,
    proxyPort: Port,
    authentication: ProxyAuth,
    bypass: BypassPolicy,
    maxOwnedConfigBytes: usize,
  ) -> Result<ProxyConfig, ProxyError>

Returns a configuration for a proxy at proxyHost and proxyPort. The port cannot be 0. maxOwnedConfigBytes limits the memory of the host, the token, and the bypass list.

Associated function fromUri#

silk
pub fn fromUri<'text>(
    id: ProxyConfigId,
    text: string<'text>,
    authentication: ProxyAuth,
    bypass: BypassPolicy,
    maxOwnedConfigBytes: usize,
  ) -> Result<ProxyConfig, ProxyError>

Returns a configuration for the proxy in text, such as http://proxy:3128. The URI can have only the http scheme, a host, and a port.

Method id#

silk
pub fn id(self: &Self) -> ProxyConfigId

Returns the identity of the configuration.

Method authContextId#

silk
pub fn authContextId(self: &Self) -> ProxyAuthContextId

Returns the identity of the credentials.

Method proxyHost#

silk
pub fn proxyHost(self: &Self) -> Host

Returns the proxy host.

Method proxyPort#

silk
pub fn proxyPort(self: &Self) -> Port

Returns the proxy port.

Method ownedBytes#

silk
pub fn ownedBytes(self: &Self) -> usize

Returns the memory of the configuration, in bytes.

selectRoute#

silk
pub fn selectRoute<'configuration>(
  configuration: &'configuration ProxyConfig,
  origin: Origin,
) -> Route<'configuration>

Returns the route for origin: Direct for a bypass origin, Tunnel for HTTPS, and Forward for plain HTTP. It does not allocate or use the network.

classifyConnect#

silk
pub effect fn classifyConnect(
  head: &ResponseHead,
) -> () ! ProxyError | OutOfMemoryError ? &mut Allocator

Reads the final response of the proxy to CONNECT.

Details#

A 2xx status succeeds. A 407 fails with ProxyAuthenticationRequired, and other statuses with ProxyRejected, with a copy of the head. If the head is too large to copy, it fails with ProxyMetadataLimit. Call it only after a final response head.

Implementation Route<'configuration>#

silk
impl<'configuration> Route<'configuration>

Method mode#

silk
pub fn mode(self: &Self) -> RouteMode

Returns the mode of the route.

Method originalOrigin#

silk
pub fn originalOrigin(self: &Self) -> Origin

Returns the origin that the route is for.

Method proxyHost#

silk
pub fn proxyHost(self: &Self) -> Host

Returns the proxy host.

Method proxyPort#

silk
pub fn proxyPort(self: &Self) -> Port

Returns the proxy port.

Method physicalPeer#

silk
pub fn physicalPeer(self: &Self) -> Result<Origin, OriginError>

Returns the proxy as a plain HTTP origin, the server to connect to.

Method proxyAuthorizationLength#

silk
pub fn proxyAuthorizationLength(self: &Self) -> usize

Returns the length of the Proxy-Authorization value, or 0 if there are no credentials.

Method writeProxyAuthorizationInto#

silk
pub fn writeProxyAuthorizationInto(self: &Self, output: &mut [u8]) -> Option<usize>

Writes the Proxy-Authorization value, such as Basic dXNlcjpwYXNz, to the start of output, and returns its length. Returns None and writes nothing if output is too small.

Method configId#

silk
pub fn configId(self: &Self) -> ProxyConfigId

Returns the identity of the configuration.

Method authContextId#

silk
pub fn authContextId(self: &Self) -> ProxyAuthContextId

Returns the identity of the credentials.

Method key#

silk
pub fn key(self: &Self) -> RouteKey

Returns the key of the route. It does not read the credentials.

Method recompute#

silk
pub fn recompute(self: &Self, origin: Origin) -> Route<'configuration>

Returns the route for another origin, with the same configuration, for example after a redirect.

Implementation RouteKey#

silk
impl RouteKey

Method originalOrigin#

silk
pub fn originalOrigin(self: &Self) -> Origin

Returns the origin of the route.

Method mode#

silk
pub fn mode(self: &Self) -> RouteMode

Returns the mode of the route.

Method equals#

silk
pub fn equals(self: &Self, other: &Self) -> bool

Returns true if the mode, the origin, the proxy, and the two identities are equal.

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.

View the source of this page