From 8256d4c362581a16bbc6db857790f321a56c1992 Mon Sep 17 00:00:00 2001 From: Hermes Agent Date: Tue, 23 Jun 2026 12:53:29 -0400 Subject: [PATCH] =?UTF-8?q?fix:=20affichage=20des=20images=20via=20URLs=20?= =?UTF-8?q?sign=C3=A9es=20Imago?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - ImagoClient::get_thumbnail() utilise maintenant /thumbnail-url (URL signée) - ImagoClient::get_file() utilise maintenant /download-url (URL signée) - Fallback automatique thumbnail → fichier original si thumbnail indisponible - Les images s'affichent dans la gallery même sans thumbnail généré --- src/imago_client.rs | 49 +++++++++++++++++++++++++++++++++++++------- src/server/routes.rs | 9 +++++++- 2 files changed, 50 insertions(+), 8 deletions(-) diff --git a/src/imago_client.rs b/src/imago_client.rs index 4dbef79..85f1fa0 100644 --- a/src/imago_client.rs +++ b/src/imago_client.rs @@ -237,13 +237,33 @@ impl ImagoClient { Ok(detail) } - /// Récupère le thumbnail d'une image (raw bytes) + /// Récupère le thumbnail d'une image via URL signée pub async fn get_thumbnail(&self, id: i64) -> Result<(Vec, String)> { - let response = self.client - .get(format!("{}/{}/thumbnail", self.images_base(), id)) + // Étape 1 : obtenir l'URL signée + let sign_response: serde_json::Value = self.client + .get(format!("{}/{}/thumbnail-url", self.images_base(), id)) .header("X-API-Key", &self.api_key) .send() .await? + .error_for_status()? + .json() + .await?; + + let signed_url = sign_response["url"] + .as_str() + .ok_or_else(|| anyhow::anyhow!("URL signée manquante dans la réponse"))?; + + // Si c'est un placeholder (pas de thumbnail), retourner une erreur propre + if signed_url.contains("placeholder") { + return Err(anyhow::anyhow!("Thumbnail non disponible (placeholder)")); + } + + // Étape 2 : télécharger depuis l'URL signée + let full_url = format!("{}{}", self.base_url.trim_end_matches('/'), signed_url); + let response = self.client + .get(&full_url) + .send() + .await? .error_for_status()?; let content_type = response @@ -257,20 +277,35 @@ impl ImagoClient { Ok((data, content_type)) } - /// Récupère le fichier original (raw bytes) + /// Récupère le fichier original via URL signée pub async fn get_file(&self, id: i64) -> Result<(Vec, String)> { - let response = self.client - .get(format!("{}/{}/file", self.images_base(), id)) + // Étape 1 : obtenir l'URL signée + let sign_response: serde_json::Value = self.client + .get(format!("{}/{}/download-url", self.images_base(), id)) .header("X-API-Key", &self.api_key) .send() .await? + .error_for_status()? + .json() + .await?; + + let signed_url = sign_response["url"] + .as_str() + .ok_or_else(|| anyhow::anyhow!("URL signée manquante dans la réponse"))?; + + // Étape 2 : télécharger depuis l'URL signée + let full_url = format!("{}{}", self.base_url.trim_end_matches('/'), signed_url); + let response = self.client + .get(&full_url) + .send() + .await? .error_for_status()?; let content_type = response .headers() .get("content-type") .and_then(|v| v.to_str().ok()) - .unwrap_or("image/png") + .unwrap_or("application/octet-stream") .to_string(); let data = response.bytes().await?.to_vec(); diff --git a/src/server/routes.rs b/src/server/routes.rs index 0b5a9d7..20b91dd 100644 --- a/src/server/routes.rs +++ b/src/server/routes.rs @@ -420,7 +420,14 @@ async fn get_thumbnail( let result = if full { client.get_file(img_id).await } else { - client.get_thumbnail(img_id).await + // Essayer le thumbnail d'abord, fallback vers le fichier original + match client.get_thumbnail(img_id).await { + Ok(t) => Ok(t), + Err(_) => { + tracing::info!("Thumbnail fallback -> fichier original pour id={}", id); + client.get_file(img_id).await + } + } }; match result {