- 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.
69 lines
1.9 KiB
Python
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,
|
|
)
|