Imago/app/routers/files.py
Bruno Charest cc99fea20a
Some checks failed
CI / Lint & Format (push) Has been cancelled
CI / Tests (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
CI / Docker Build (push) Has been cancelled
Add comprehensive test suite for image processing and related services
- Implement tests for database generator to ensure proper session handling.
- Create tests for EXIF extraction and conversion functions.
- Add tests for image-related endpoints, ensuring proper data retrieval and isolation between clients.
- Develop tests for OCR functionality, including language detection and text extraction.
- Introduce tests for the image processing pipeline, covering success and failure scenarios.
- Validate rate limiting functionality and ensure independent counters for different clients.
- Implement scraper tests to verify HTML content fetching and error handling.
- Add unit tests for various services, including storage and filename generation.
- Establish worker entry point for ARQ to handle background image processing tasks.
2026-02-24 11:22:10 -05:00

69 lines
1.9 KiB
Python

"""
Router — Files : sert les fichiers locaux via URLs signées HMAC.
Monté uniquement quand STORAGE_BACKEND == "local".
"""
import logging
from pathlib import Path
from fastapi import APIRouter, HTTPException, status
from fastapi.responses import FileResponse
from app.config import settings
from app.services.storage_backend import get_storage_backend, LocalStorage
logger = logging.getLogger(__name__)
router = APIRouter(prefix="/files", tags=["Fichiers"])
@router.get(
"/signed/{token}",
summary="Télécharger un fichier via URL signée",
description="Valide le token HMAC et retourne le fichier correspondant.",
)
async def serve_signed_file(token: str):
"""Sert un fichier local via un token HMAC signé."""
backend = get_storage_backend()
if not isinstance(backend, LocalStorage):
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Endpoint non disponible avec le backend de stockage actuel",
)
# Valider le token
path = backend.validate_token(token)
if path is None:
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail="Token invalide ou expiré",
)
# Vérifier que le fichier existe
abs_path = backend.get_absolute_path(path)
if not abs_path.exists():
raise HTTPException(
status_code=status.HTTP_410_GONE,
detail="Le fichier n'existe plus",
)
# Détecter le content type
suffix = abs_path.suffix.lower()
mime_map = {
".jpg": "image/jpeg",
".jpeg": "image/jpeg",
".png": "image/png",
".gif": "image/gif",
".webp": "image/webp",
".bmp": "image/bmp",
".tiff": "image/tiff",
}
media_type = mime_map.get(suffix, "application/octet-stream")
return FileResponse(
path=str(abs_path),
media_type=media_type,
filename=abs_path.name,
)