Files
photoanalyzer/photo_pipeline/api/routes/thumbnails.py

38 lines
1.4 KiB
Python

"""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",
# private: the URL is versioned and immutable, but these bytes are the user's
# photos and must never sit in a shared cache (US07-02).
headers={"Cache-Control": "private, max-age=31536000, immutable"},
)