fix: share URL respects scheme in OXICLOUD_SERVER_HOST (#103)

When OXICLOUD_SERVER_HOST contains a full URL with scheme (e.g.
https://oxi.example.com), the share link no longer prepends
http:// or appends :port, avoiding malformed URLs like
http://https://host:8085/s/token.

- Add AppConfig::base_url() helper with smart URL construction
- Replace all 6 inline format!() calls in share_service.rs
- Replace inline construction in di.rs (admin settings base URL)
- Priority: OXICLOUD_BASE_URL > full-URL host > http://host:port
This commit is contained in:
Dionisio
2026-02-14 00:18:59 +01:00
parent 82dd7a5c56
commit 099d1d1c55
3 changed files with 29 additions and 9 deletions
+6 -6
View File
@@ -158,7 +158,7 @@ impl ShareUseCase for ShareService {
.map_err(|e| ShareServiceError::Repository(e.to_string()))?;
// Convert the entity to DTO for the response
Ok(ShareDto::from_entity(&saved_share, &format!("http://{}:{}", self.config.server_host, self.config.server_port)))
Ok(ShareDto::from_entity(&saved_share, &self.config.base_url()))
}
async fn get_shared_link(&self, id: &str) -> Result<ShareDto, DomainError> {
@@ -175,7 +175,7 @@ impl ShareUseCase for ShareService {
}
// Convert the entity to DTO for the response
Ok(ShareDto::from_entity(&share, &format!("http://{}:{}", self.config.server_host, self.config.server_port)))
Ok(ShareDto::from_entity(&share, &self.config.base_url()))
}
async fn get_shared_link_by_token(&self, token: &str) -> Result<ShareDto, DomainError> {
@@ -192,7 +192,7 @@ impl ShareUseCase for ShareService {
}
// Convert the entity to DTO for the response
Ok(ShareDto::from_entity(&share, &format!("http://{}:{}", self.config.server_host, self.config.server_port)))
Ok(ShareDto::from_entity(&share, &self.config.base_url()))
}
async fn get_shared_links_for_item(
@@ -213,7 +213,7 @@ impl ShareUseCase for ShareService {
// Convert the entities to DTOs for the response
let share_dtos = active_shares
.iter()
.map(|s| ShareDto::from_entity(s, &format!("http://{}:{}", self.config.server_host, self.config.server_port)))
.map(|s| ShareDto::from_entity(s, &self.config.base_url()))
.collect();
Ok(share_dtos)
@@ -264,7 +264,7 @@ impl ShareUseCase for ShareService {
.map_err(|e| ShareServiceError::Repository(e.to_string()))?;
// Convert the entity to DTO for the response
Ok(ShareDto::from_entity(&updated_share, &format!("http://{}:{}", self.config.server_host, self.config.server_port)))
Ok(ShareDto::from_entity(&updated_share, &self.config.base_url()))
}
async fn delete_shared_link(&self, id: &str) -> Result<(), DomainError> {
@@ -296,7 +296,7 @@ impl ShareUseCase for ShareService {
// Convert the entities to DTOs
let share_dtos: Vec<ShareDto> = shares
.iter()
.map(|s| ShareDto::from_entity(s, &format!("http://{}:{}", self.config.server_host, self.config.server_port)))
.map(|s| ShareDto::from_entity(s, &self.config.base_url()))
.collect();
// Create the paginated result
+22
View File
@@ -580,6 +580,28 @@ impl AppConfig {
pub fn auth_enabled(&self) -> bool {
self.features.enable_auth
}
/// Build the public base URL for generating share links and other external URLs.
///
/// Priority:
/// 1. `OXICLOUD_BASE_URL` env var (used as-is)
/// 2. If `server_host` already contains a scheme (`http://` or `https://`),
/// treat it as a full origin and do **not** prepend a scheme or append a port.
/// 3. Otherwise, fall back to `http://{server_host}:{server_port}`.
pub fn base_url(&self) -> String {
if let Ok(explicit) = std::env::var("OXICLOUD_BASE_URL") {
return explicit.trim_end_matches('/').to_string();
}
let host = self.server_host.trim_end_matches('/');
if host.starts_with("http://") || host.starts_with("https://") {
// The user already provided a full origin — use it directly.
host.to_string()
} else {
format!("http://{}:{}", host, self.server_port)
}
}
}
/// Gets a default global configuration
+1 -3
View File
@@ -594,9 +594,7 @@ impl AppServiceFactory {
let settings_repo = Arc::new(
crate::infrastructure::repositories::pg::SettingsPgRepository::new(pool.clone())
);
let server_base_url = std::env::var("OXICLOUD_BASE_URL").unwrap_or_else(|_| {
format!("http://{}:{}", self.config.server_host, self.config.server_port)
});
let server_base_url = self.config.base_url();
// Load OIDC config from env vars (the snapshot from startup)
let env_oidc = crate::common::config::OidcConfig::from_env();