diff --git a/src/clients.rs b/src/clients.rs index 8f626422..546f498a 100644 --- a/src/clients.rs +++ b/src/clients.rs @@ -212,6 +212,14 @@ pub async fn create_http_client( .set_port(Some(port)) .unwrap_or_else(|_| panic!("error setting port: {port}")); + // Apply path prefix if configured + if let Some(prefix) = &service_config.path_prefix { + let trimmed = prefix.trim_matches('/'); + if !trimmed.is_empty() { + base_url.set_path(&format!("/{}", trimmed)); + } + } + let connect_timeout = Duration::from_secs(DEFAULT_CONNECT_TIMEOUT_SEC); let request_timeout = Duration::from_secs( service_config diff --git a/src/clients/http.rs b/src/clients/http.rs index e962c578..5f8d64cc 100644 --- a/src/clients/http.rs +++ b/src/clients/http.rs @@ -125,6 +125,11 @@ pub struct HttpClient { impl HttpClient { pub fn new(base_url: Url, api_token: Option, inner: HttpClientInner) -> Self { + // Ensure base_url has trailing slash for proper path joining + let mut base_url = base_url; + if !base_url.path().ends_with('/') { + base_url.set_path(&format!("{}/", base_url.path())); + } let health_url = base_url.join("health").unwrap(); Self { base_url, @@ -139,6 +144,7 @@ impl HttpClient { } pub fn endpoint(&self, path: &str) -> Url { + let path = path.trim_start_matches('/'); self.base_url.join(path).unwrap() } diff --git a/src/config.rs b/src/config.rs index 956c5d8d..fbc9c7b4 100644 --- a/src/config.rs +++ b/src/config.rs @@ -73,6 +73,8 @@ pub struct ServiceConfig { pub hostname: String, /// Port for service pub port: Option, + /// Path prefix for service endpoints (e.g., "/namespace/service-name") + pub path_prefix: Option, /// Timeout in seconds for request to be handled pub request_timeout: Option, /// TLS provider info @@ -99,6 +101,7 @@ impl ServiceConfig { Self { hostname, port: Some(port), + path_prefix: None, request_timeout: None, tls: None, grpc_dns_probe_interval: None,