http_gun/config

Configures a client: destinations, protocol, TLS trust, timeouts, size limits, redaction and observations.

Start from default() and change only what you need:

let settings =
  config.default()
  |> config.allow_loopback
  |> config.with_protocol(config.PreferHttp2)
  |> config.with_request_timeout(config.After(duration.seconds(10)))
let assert Ok(client) = http_gun.start(settings)

Every timeout is a gleam/time/duration.Duration; a timeout that may be lifted takes a Timeout, where Infinity must be chosen explicitly. HTTP Gun keeps whole milliseconds, rounding a sub-millisecond remainder away from zero.

A Config is opaque, so a new option never breaks your code. validate checks it without starting processes; http_gun.start validates it too and returns the same ConfigError. A configured client identity contains private key material; never log arbitrary configuration values.

Defaults

SettingDefaultSetter
destinationspublic addresses onlyallow_loopback, with_destination
destination on every viewnot requiredrequire_view_destination
protocolHTTP/1.1with_protocol
TLS client identitynonewith_client_identity
TLS trustsystem CA store, peer and host name verifiedwith_trust
connect, including DNS and TLSduration.seconds(5)with_connect_timeout
waiting for a pooled connectionduration.seconds(5)with_pool_timeout
request, admission to last byteAfter(duration.seconds(30))with_request_timeout
idle read, no bytes while readingAfter(duration.seconds(30))with_idle_timeout
idle pooled connectionduration.seconds(60)with_connection_idle_timeout
draining on stopduration.seconds(5)with_shutdown_timeout
connections / per origin16 / 4with_max_connections, with_max_connections_per_origin
HTTP/2 streams per connection100with_max_streams_per_connection
open response bodies128with_max_open_bodies
queued requests128with_max_queued_requests
request body1 MiBwith_max_request_body_bytes
header bytes / count16 KiB / 100with_max_header_bytes, with_max_header_count
buffered response bytes128 KiBwith_max_buffered_bytes
collected response body (send)8 MiBwith_max_response_body_bytes
bytes retained by one batch64 MiBwith_max_batch_bytes
redactioncredential headerswith_redaction
observationssinal.emit, which follows the application’s routeswith_observations, without_observations
client label in eventsnonewith_label

Types

Client settings. Build with default() and the with_* functions.

pub type Config =
  @internal Settings

Why a configuration is invalid.

pub type ConfigError {
  OutOfRange(setting: Setting, value: Int)
  TimeoutOutOfRange(setting: Setting, value: duration.Duration)
  EmptyTrustAnchors
  InvalidTrustAnchor
  InvalidAllowedHost(entry: String)
}

Constructors

  • OutOfRange(setting: Setting, value: Int)

    A capacity is out of range: it must be positive; queued requests, request body and response body limits may also be zero.

  • TimeoutOutOfRange(setting: Setting, value: duration.Duration)

    A timeout is out of range, in HTTP Gun’s whole-millisecond precision: it must be positive; the shutdown timeout may also be zero.

  • EmptyTrustAnchors

    Anchors([]) trusts nothing.

  • InvalidTrustAnchor

    A trust anchor is empty or not whole bytes.

  • InvalidAllowedHost(entry: String)

    A destination.only_hosts entry is malformed.

The protocol a response used. Scripted and cassette responses report Offline.

pub type Negotiated {
  H1
  H2
  Offline
}

Constructors

  • H1
  • H2
  • Offline

Which HTTP versions a client negotiates.

pub type Protocol {
  Http1
  PreferHttp2
  RequireHttp2
}

Constructors

  • Http1

    HTTP/1.1 only.

  • PreferHttp2

    HTTP/2 over TLS when the server offers it through ALPN, else HTTP/1.1. Plain-text connections use HTTP/1.1.

  • RequireHttp2

    HTTP/2 only; a server that negotiates HTTP/1.1 fails the connection.

Resolves a host name for a new connection, replacing DNS, for example in tests. It receives the host and the time left in the connect timeout, runs in an isolated worker, and returns the complete A/AAAA answer. Every address is checked against the destination policy; an exception or an empty answer fails closed.

pub type Resolver =
  fn(String, duration.Duration) -> Result(
    List(destination.Address),
    Nil,
  )

A setting, as ConfigError names it.

pub type Setting {
  ConnectTimeout
  PoolTimeout
  RequestTimeout
  IdleTimeout
  ConnectionIdleTimeout
  ShutdownTimeout
  MaxConnections
  MaxConnectionsPerOrigin
  MaxStreamsPerConnection
  MaxOpenBodies
  MaxQueuedRequests
  MaxRequestBodyBytes
  MaxHeaderBytes
  MaxHeaderCount
  MaxBufferedBytes
  MaxResponseBodyBytes
  MaxBatchBytes
}

Constructors

  • ConnectTimeout
  • PoolTimeout
  • RequestTimeout
  • IdleTimeout
  • ConnectionIdleTimeout
  • ShutdownTimeout
  • MaxConnections
  • MaxConnectionsPerOrigin
  • MaxStreamsPerConnection
  • MaxOpenBodies
  • MaxQueuedRequests
  • MaxRequestBodyBytes
  • MaxHeaderBytes
  • MaxHeaderCount
  • MaxBufferedBytes
  • MaxResponseBodyBytes
  • MaxBatchBytes

A time bound that may be lifted. Infinity lifts it and must be chosen explicitly.

pub type Timeout {
  After(duration.Duration)
  Infinity
}

Constructors

Which certificate authorities verify a TLS server. Every choice verifies the peer and its host name.

pub type Trust {
  SystemTrust
  CustomCa(path: String)
  Anchors(certificates: List(BitArray))
}

Constructors

  • SystemTrust
  • CustomCa(path: String)

    A PEM file of CA certificates, replacing system trust.

  • Anchors(certificates: List(BitArray))

    DER-encoded CA certificates, replacing system trust without file IO.

Values

pub fn allow_loopback(config: Config) -> Config

Also admit loopback destinations (127.0.0.0/8 and ::1), for a local server in tests or development. Every other destination setting is kept.

pub fn default() -> Config

Public destinations only, HTTP/1.1, verified TLS with system trust, and the bounds in the module’s defaults table. Starts nothing.

pub fn describe_error(error: ConfigError) -> String

Describe a configuration error for logs.

pub fn require_view_destination(config: Config) -> Config

Refuse every request whose client view has not chosen a destination with http_gun.with_destination, failing it with ViewDestinationRequired and NotSent before it is validated, resolved or matched. The client’s own policy then only bounds what views may narrow to: a view still narrows and never widens it.

A view chooses a destination when one of its policies sets destination.only_hosts or refuses an address class this client admits. A plaintext rule never counts: a library that only tightens destination.with_plaintext on a caller’s view leaves the requirement in force.

A multi-tenant client must admit the union of its tenants’ destinations, for example public addresses and loopback. Without this setting, a call that skips the tenant’s view reaches that union; with it, the call fails closed. The check applies to live, recording and playback clients alike, so a cassette test catches a call that skips the view.

let assert Ok(client) =
  config.default()
  |> config.allow_loopback
  |> config.require_view_destination
  |> http_gun.start
let public = client |> http_gun.with_destination(destination.default())
pub fn validate(config: Config) -> Result(Config, ConfigError)

Check every setting without starting processes.

pub fn with_client_identity(
  config: Config,
  identity: client_identity.Identity,
) -> Config

Present this immutable identity when a TLS server requests client authentication. Trust and hostname verification remain independent. Every connection in this client uses the same snapshot, including reconnects. Views cannot replace it. Rotate by starting a new client and draining/stopping the old client; in-flight old-client exchanges retain their old identity. The setter is pure. Plaintext connections send no identity material.

pub fn with_connect_timeout(
  config: Config,
  timeout: duration.Duration,
) -> Config

Bound resolving, connecting and the TLS handshake of each new connection, together. Default 5 s.

pub fn with_connection_idle_timeout(
  config: Config,
  timeout: duration.Duration,
) -> Config

Close a pooled connection that has carried no request for this long. Default 60 s.

pub fn with_destination(
  config: Config,
  policy: destination.Policy,
) -> Config

Replace the destination policy.

pub fn with_idle_timeout(
  config: Config,
  timeout: Timeout,
) -> Config

Fail a response when no bytes arrive for this long while its owner waits for the head or reads the body. A reader that pauses is not idle. Also bounds a stalled socket write. Default 30 s; http_gun.with_idle_timeout replaces it for one client view.

pub fn with_label(config: Config, label: String) -> Config

Name this client in every lifecycle event, as the metadata’s client field, so a handler that sees every client’s events can tell them apart. Unlabelled clients report None. The label is any text; it is not a credential and is not stored in cassettes.

A library that starts its own private client should label it with the library’s name, for example "hellhound".

pub fn with_max_batch_bytes(config: Config, bytes: Int) -> Config

Body bytes that one batch call retains across its results. Once reached, the response being collected fails and requests not yet sent fail with LimitExceeded(BatchBytes, ..). Default 64 MiB.

pub fn with_max_buffered_bytes(
  config: Config,
  bytes: Int,
) -> Config

Response bytes buffered between the network and a slow reader, which also bounds one chunk. Default 128 KiB.

pub fn with_max_connections(config: Config, count: Int) -> Config

Connections across all origins. Default 16.

pub fn with_max_connections_per_origin(
  config: Config,
  count: Int,
) -> Config

Connections to one scheme, host and port. Default 4.

pub fn with_max_header_bytes(
  config: Config,
  bytes: Int,
) -> Config

Header bytes (names plus values) of a request, a response head or its trailers. Default 16 KiB.

pub fn with_max_header_count(
  config: Config,
  count: Int,
) -> Config

Headers in a request, a response head or its trailers. Default 100.

pub fn with_max_open_bodies(config: Config, count: Int) -> Config

Response bodies open at once; further requests queue. Default 128.

pub fn with_max_queued_requests(
  config: Config,
  count: Int,
) -> Config

Requests waiting for capacity; beyond this a request fails with AdmissionFull. Default 128.

pub fn with_max_request_body_bytes(
  config: Config,
  bytes: Int,
) -> Config

Request body bytes. Default 1 MiB.

pub fn with_max_response_body_bytes(
  config: Config,
  bytes: Int,
) -> Config

Body bytes that send and batch collect per response; a larger body fails with LimitExceeded(ResponseBodyBytes, ..) and the response status. http_gun.with_body_limit replaces it per view. Streaming reads are not bounded by it. Default 8 MiB.

pub fn with_max_streams_per_connection(
  config: Config,
  count: Int,
) -> Config

Concurrent HTTP/2 streams per connection, below the server’s own limit. Default 100.

pub fn with_observations(
  config: Config,
  target: forwarder.Forwarder,
) -> Config

Hand lifecycle events to this forwarder instead of emitting them with sinal.emit. By default HTTP Gun calls sinal.emit, so the events follow the application’s forwarder.route for ["http_gun"]; without a route, handlers run in HTTP Gun’s pool and body processes.

pub fn with_pool_timeout(
  config: Config,
  timeout: duration.Duration,
) -> Config

Bound the wait for a connection or stream from the pool, including an HTTP/1.1 readiness check. A request that triggers a new connection is bounded by the connect timeout instead. Default 5 s.

pub fn with_protocol(
  config: Config,
  protocol: Protocol,
) -> Config
pub fn with_redaction(
  config: Config,
  redaction: redaction.Redaction,
) -> Config

Choose what cassettes never store. See http_gun/redaction.

pub fn with_request_timeout(
  config: Config,
  timeout: Timeout,
) -> Config

Bound each request from admission to the last body byte. Default 30 s. http_gun.with_timeout and http_gun.with_deadline replace it for one client view, shorter or longer. Infinity lifts it; the connect, pool and idle timeouts still apply.

pub fn with_resolver(
  config: Config,
  resolver: fn(String, duration.Duration) -> Result(
    List(destination.Address),
    Nil,
  ),
) -> Config

Resolve host names with resolver instead of DNS.

pub fn with_shutdown_timeout(
  config: Config,
  timeout: duration.Duration,
) -> Config

How long http_gun.stop lets open responses finish before cancelling them. Zero cancels at once. Default 5 s.

pub fn with_trust(config: Config, trust: Trust) -> Config
pub fn without_observations(config: Config) -> Config

Emit no lifecycle events from this client. A later with_observations turns them back on.

A library that owns a private client may choose this so that its HTTP stays out of the application’s handlers. Prefer with_label: a labelled client lets the application decide whether to watch or skip it.

✨ Search Document