diff --git a/common/client-core/Cargo.toml b/common/client-core/Cargo.toml index fd1e82d7ac..2f6d87dbc4 100644 --- a/common/client-core/Cargo.toml +++ b/common/client-core/Cargo.toml @@ -36,7 +36,7 @@ nym-bandwidth-controller = { path = "../bandwidth-controller" } nym-crypto = { path = "../crypto" } nym-gateway-client = { path = "../client-libs/gateway-client" } nym-gateway-requests = { path = "../gateway-requests" } -nym-http-api-client = { path = "../http-api-client" } +nym-http-api-client = { path = "../http-api-client", features = ["network-defaults"] } nym-nonexhaustive-delayqueue = { path = "../nonexhaustive-delayqueue" } nym-sphinx = { path = "../nymsphinx" } nym-statistics-common = { path = "../statistics" } diff --git a/common/client-core/src/client/base_client/mod.rs b/common/client-core/src/client/base_client/mod.rs index af065b3dec..a425aefd87 100644 --- a/common/client-core/src/client/base_client/mod.rs +++ b/common/client-core/src/client/base_client/mod.rs @@ -46,6 +46,7 @@ use nym_gateway_client::client::config::GatewayClientConfig; use nym_gateway_client::{ AcknowledgementReceiver, GatewayClient, GatewayConfig, MixnetMessageReceiver, PacketRouter, }; +use nym_network_defaults::NymNetworkDetails; use nym_sphinx::acknowledgements::AckKey; use nym_sphinx::addressing::clients::Recipient; use nym_sphinx::addressing::nodes::NodeIdentity; @@ -212,6 +213,9 @@ pub struct BaseClientBuilder { client_store: S, dkg_query_client: Option, + // Optional network details for domain fronting support + network_details: Option, + wait_for_gateway: bool, custom_topology_provider: Option>, custom_gateway_transceiver: Option>, @@ -241,6 +245,7 @@ where config: base_config, client_store, dkg_query_client, + network_details: None, wait_for_gateway: false, custom_topology_provider: None, custom_gateway_transceiver: None, @@ -263,6 +268,16 @@ where self } + /// Set network details for domain fronting support. + /// + /// When provided, the client will use network details (which include front_hosts) + /// to construct HTTP clients with domain fronting enabled. + #[must_use] + pub fn with_network_details(mut self, network_details: NymNetworkDetails) -> Self { + self.network_details = Some(network_details); + self + } + #[must_use] pub fn with_forget_me(mut self, forget_me: &ForgetMe) -> Self { self.config.debug.forget_me = *forget_me; @@ -863,9 +878,29 @@ where } fn construct_nym_api_client( + network_details: Option<&NymNetworkDetails>, config: &Config, user_agent: Option, ) -> Result { + // If network details are provided, use from_network() which handles domain fronting + if let Some(network_details) = network_details { + tracing::debug!( + "Building nym-api client from network details (with domain fronting support)" + ); + + let mut builder = nym_http_api_client::ClientBuilder::from_network(network_details) + .map_err(ClientCoreError::from)?; + + if let Some(user_agent) = user_agent { + builder = builder.with_user_agent(user_agent); + } + + return builder.build().map_err(ClientCoreError::from); + } + + // Fallback to basic client for backwards compatibility + tracing::debug!("Building basic nym-api HTTP client from config endpoints"); + let mut nym_api_urls = config.get_nym_api_endpoints(); nym_api_urls.shuffle(&mut thread_rng()); @@ -961,7 +996,11 @@ where .dkg_query_client .map(|client| BandwidthController::new(credential_store, client)); - let nym_api_client = Self::construct_nym_api_client(&self.config, self.user_agent.clone())?; + let nym_api_client = Self::construct_nym_api_client( + self.network_details.as_ref(), + &self.config, + self.user_agent.clone(), + )?; let key_rotation_config = Self::determine_key_rotation_state(&nym_api_client).await?; let topology_provider = Self::setup_topology_provider( diff --git a/sdk/rust/nym-sdk/src/mixnet/client.rs b/sdk/rust/nym-sdk/src/mixnet/client.rs index 258d2f3c37..f5a28b589a 100644 --- a/sdk/rust/nym-sdk/src/mixnet/client.rs +++ b/sdk/rust/nym-sdk/src/mixnet/client.rs @@ -708,6 +708,7 @@ where let mut base_builder: BaseClientBuilder<_, _> = BaseClientBuilder::new(base_config, self.storage, self.dkg_query_client) + .with_network_details(self.config.network_details.clone()) .with_wait_for_gateway(self.wait_for_gateway) .with_forget_me(&self.forget_me) .with_remember_me(&self.remember_me)