How to Configure the HTTP Client and Custom TLS Settings in Forge
Forge employs a three-layer architecture built on reqwest that separates HTTP configuration into domain models, configuration files, and infrastructure builders, enabling granular TLS control via code, TOML, or environment variables.
Forge is an AI-powered coding assistant developed in the antinomyhq/forgecode repository. Its HTTP client configuration architecture allows developers to customize connection behavior, timeouts, and TLS settings through a type-safe domain model that bridges user configuration with the underlying reqwest client.
HTTP Client Architecture Overview
Forge organizes HTTP client configuration into three distinct layers that separate data definitions from implementation details. This architecture ensures that TLS settings, timeouts, and connection pooling can be specified declaratively while the actual reqwest::Client instantiation remains encapsulated in the infrastructure layer.
Domain Layer: HttpConfig
The foundational data structures reside in forge_domain::HttpConfig, which defines every tunable HTTP option including timeouts, connection pools, redirects, DNS settings, and TLS parameters. This pure data model contains fields for TLS backend selection, version constraints, and certificate validation.
Located in crates/forge_domain/src/http_config.rs, this struct includes TlsVersion and TlsBackend enums that map directly to reqwest types through conversion functions. The domain layer contains no networking logic, serving only as the canonical schema for HTTP behavior.
Configuration Layer: ForgeConfig
The configuration crate aggregates user preferences through forge_config::ForgeConfig, which holds an optional http: Option<HttpConfig> field. This layer handles deserialization from TOML/YAML files and environment variables using the FORGE_HTTP_* prefix pattern.
In crates/forge_config/src/config.rs, the configuration parser merges file-based settings with environment overrides, producing a resolved HttpConfig that propagates to the infrastructure layer. This separation allows operators to configure TLS settings without modifying application code.
Infrastructure Layer: ForgeHttpInfra
The concrete HTTP client materializes in crates/forge_infra/src/http.rs within ForgeHttpInfra::new. This function accepts a ForgeConfig, extracts the HttpConfig (falling back to defaults if absent), and constructs a reqwest::Client through the builder pattern.
Key translation steps include:
- Mapping
TlsVersiontoreqwest::tls::Versionviato_reqwest_tls - Selecting the TLS backend through
client.use_rustls_tls()whentls_backend == TlsBackend::Rustls - Loading custom root certificates from
root_cert_pathsusingCertificate::from_pemorfrom_der - Enabling
danger_accept_invalid_certs(true)when theaccept_invalid_certsflag is set
Configuring Custom TLS Settings
Forge exposes comprehensive TLS customization through the HttpConfig struct, configurable via three interfaces: programmatic Rust construction, TOML configuration files, or environment variables.
Available TLS Options
| Field | Type | Description | Environment Variable |
|---|---|---|---|
tls_backend |
TlsBackend |
Selects the TLS implementation (Default for platform native, Rustls for pure Rust) |
FORGE_HTTP_TLS_BACKEND |
min_tls_version |
Option<TlsVersion> |
Minimum allowed protocol version (e.g., 1.2) |
FORGE_HTTP_MIN_TLS_VERSION |
max_tls_version |
Option<TlsVersion> |
Maximum allowed protocol version (e.g., 1.3) |
FORGE_HTTP_MAX_TLS_VERSION |
accept_invalid_certs |
bool |
Dangerous - bypasses certificate validation (testing only) | FORGE_HTTP_ACCEPT_INVALID_CERTS |
root_cert_paths |
Option<Vec<PathBuf>> |
Additional PEM/DER files to trust beyond system store | FORGE_HTTP_ROOT_CERT_PATHS (comma-separated) |
When ForgeHttpInfra instantiates the client, these values translate directly to reqwest::ClientBuilder method calls:
if let Some(v) = http.min_tls_version {
client = client.min_tls_version(to_reqwest_tls(v));
}
if let Some(v) = http.max_tls_version {
client = client.max_tls_version(to_reqwest_tls(v));
}
match http.tls_backend {
TlsBackend::Rustls => client = client.use_rustls_tls(),
TlsBackend::Default => {} // platform default
}
if http.accept_invalid_certs {
client = client.danger_accept_invalid_certs(true);
}
if let Some(paths) = http.root_cert_paths {
for p in paths { /* read PEM/DER and add_root_certificate */ }
}
Method 1: Programmatic Configuration
Construct HttpConfig directly in Rust for compile-time safety:
use forge_domain::{HttpConfig, TlsVersion, TlsBackend};
let http_cfg = HttpConfig {
// Timeouts (seconds)
connect_timeout: 20,
read_timeout: 300,
// TLS customization
tls_backend: TlsBackend::Rustls,
min_tls_version: Some(TlsVersion::V1_2),
max_tls_version: Some(TlsVersion::V1_3),
accept_invalid_certs: false,
root_cert_paths: Some(vec![
"/etc/ssl/custom-ca.pem".into(),
"/home/user/mycert.der".into(),
]),
..HttpConfig::default()
};
Method 2: TOML Configuration File
Define settings in a configuration file that forge_config loads at runtime:
# config.toml
[http]
connectTimeout = 20
readTimeout = 300
tlsBackend = "rustls"
minTlsVersion = "1.2"
maxTlsVersion = "1.3"
acceptInvalidCerts = false
rootCertPaths = "/etc/ssl/custom-ca.pem,/home/user/mycert.der"
Load the configuration using forge_config::ForgeConfig::from_path("config.toml"). The http section maps directly onto the HttpConfig struct fields.
Method 3: Environment Variables
Override or define settings without touching configuration files:
export FORGE_HTTP_TLS_BACKEND=rustls
export FORGE_HTTP_MIN_TLS_VERSION=1.2
export FORGE_HTTP_MAX_TLS_VERSION=1.3
export FORGE_HTTP_ROOT_CERT_PATHS="/etc/ssl/custom-ca.pem,/home/user/mycert.der"
export FORGE_HTTP_ACCEPT_INVALID_CERTS=false
Complete Application Example
Integrate the configuration into a running application:
use forge_infra::http::ForgeHttpInfra;
use forge_app::FileWriterInfra;
use std::sync::Arc;
async fn run(http_cfg: HttpConfig) -> anyhow::Result<()> {
// Wrap the config in the top-level ForgeConfig
let forge_cfg = forge_config::ForgeConfig {
http: Some(http_cfg),
..Default::default()
};
// Provide a concrete FileWriterInfra implementation
let file_writer: Arc<dyn FileWriterInfra> = Arc::new(forge_infra::fs_write::FsWriteInfra::default());
// Build the HTTP infra with custom TLS settings
let http = ForgeHttpInfra::new(forge_cfg, file_writer);
// Execute request using configured client
let url = reqwest::Url::parse("https://api.example.com/health")?;
let resp = http.http_get(&url, None).await?;
println!("Status: {}", resp.status());
Ok(())
}
Summary
- Three-layer architecture: Forge separates HTTP concerns into
HttpConfig(domain),ForgeConfig(serialization), andForgeHttpInfra(implementation) to maintain clean boundaries between data and networking logic. - Source locations: Domain models live in
crates/forge_domain/src/http_config.rs, configuration aggregation incrates/forge_config/src/config.rs, and thereqwest::Clientbuilder incrates/forge_infra/src/http.rs. - TLS flexibility: Choose between Rustls and native TLS backends, constrain protocol versions to TLS 1.2 or 1.3, mount custom certificate authorities, and control certificate validation.
- Configuration interfaces: Set TLS parameters via Rust code, TOML files, or
FORGE_HTTP_*environment variables, with the infrastructure layer automatically applying them to the underlyingreqwestclient.
Frequently Asked Questions
What TLS backends does Forge support?
Forge supports two TLS backends configured through the tls_backend field in HttpConfig. Setting TlsBackend::Rustls forces the pure Rust Rustls implementation via client.use_rustls_tls(), while TlsBackend::Default uses the platform's native TLS library (typically OpenSSL on Linux, Secure Transport on macOS, or Schannel on Windows).
How do I bypass certificate validation for local testing?
Set accept_invalid_certs: true in your HttpConfig or export FORGE_HTTP_ACCEPT_INVALID_CERTS=true. This calls reqwest::ClientBuilder::danger_accept_invalid_certs(true), which disables all certificate validation. Only use this in development environments, as it exposes connections to man-in-the-middle attacks.
Can I configure all HTTP settings through environment variables?
Yes. The forge_config crate automatically maps environment variables with the FORGE_HTTP_* prefix to HttpConfig fields. For example, FORGE_HTTP_TLS_BACKEND=rustls sets the backend, while FORGE_HTTP_ROOT_CERT_PATHS accepts comma-separated paths to PEM or DER certificate files that augment the system's trust store.
Where does Forge actually create the HTTP client?
The concrete reqwest::Client instantiation occurs in crates/forge_infra/src/http.rs within the ForgeHttpInfra::new function. This method extracts HttpConfig from the provided ForgeConfig and translates the domain model into reqwest::ClientBuilder calls, handling TLS version mapping, backend selection, and certificate loading before producing the final client instance.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →