Use presigned S3 URLs for serving images instead of proxying bytes

Browser <img> tags can't attach JWT headers, causing 401s. The image
endpoint now returns a time-limited presigned S3 URL via authenticated
API call, which the frontend fetches and uses directly.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-04 08:45:35 -04:00
parent cfa77a1779
commit b62a8b6b3f
4 changed files with 33 additions and 11 deletions

View File

@@ -47,6 +47,16 @@ async def get_image(key: str) -> tuple[bytes, str]:
return body, content_type
async def generate_presigned_url(key: str, expires_in: int = 3600) -> str:
async with _get_client() as client:
url = await client.generate_presigned_url(
"get_object",
Params={"Bucket": S3_BUCKET_NAME, "Key": key},
ExpiresIn=expires_in,
)
return url
async def delete_image(key: str) -> None:
async with _get_client() as client:
await client.delete_object(Bucket=S3_BUCKET_NAME, Key=key)