US01-05: Generate and Serve Managed Thumbnails (#50)

This commit was merged in pull request #50.
This commit is contained in:
2026-07-15 21:27:40 +02:00
parent 691d5a5651
commit 98e9cb2988
9 changed files with 697 additions and 6 deletions

View File

@@ -0,0 +1,35 @@
"""Thumbnail endpoint: previews addressed only by asset ID and bounded size.
The browser never supplies a filesystem path. Errors return a consistent JSON
envelope with the service's typed code and status; successful responses carry the
image with an immutable cache header (the URL's identity comes from the versioned,
content-keyed cache).
"""
from __future__ import annotations
from fastapi import APIRouter, Query, Request
from fastapi.responses import FileResponse, JSONResponse
from photo_pipeline.services.thumbnails import ThumbnailError, ThumbnailService
router = APIRouter(tags=["thumbnails"])
@router.get("/assets/{asset_id}/thumbnail")
def get_thumbnail(asset_id: str, request: Request, size: int = Query(512)):
service = ThumbnailService(
request.app.state.session_factory, request.app.state.config
)
try:
path = service.generate(asset_id, size)
except ThumbnailError as error:
return JSONResponse(
status_code=error.http_status,
content={"error": {"code": error.code, "message": str(error)}},
)
return FileResponse(
path,
media_type="image/webp",
headers={"Cache-Control": "public, max-age=31536000, immutable"},
)