Avatars: a cached avatar or miss failed on every later request

The shared Redis client decodes replies as UTF-8 text, but the avatar cache
holds raw image bytes and a b"none" miss marker: an image could not be read
back at all, and a miss came back as str and crashed on .partition(b"\n").
Only a sender's first request worked; after that, a 500. The cache now goes
through a binary-safe client, get_redis_bytes().

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-09-28 08:09:09 +02:00
co-authored by Claude Opus 5.5
parent 37bb6ef78d
commit caed8543ea
3 changed files with 107 additions and 4 deletions
+3 -2
View File
@@ -17,7 +17,7 @@ from fastapi import APIRouter, Query, Response
from app.accounts.ssrf import SsrfError, guarded_request
from app.config import get_settings
from app.identity.deps import CurrentUser
from app.redis_client import get_redis
from app.redis_client import get_redis_bytes
router = APIRouter(prefix="/avatar", tags=["mail"])
@@ -66,7 +66,8 @@ async def sender_avatar(_user: CurrentUser, email: str = Query(...)) -> Response
if not get_settings().sender_avatars_enabled or "@" not in email:
return Response(status_code=404)
redis = get_redis()
# Binary-safe client: the cache holds raw image bytes (and a b"none" marker).
redis = get_redis_bytes()
md5 = _email_md5(email)
key = f"avatar:{md5}"
headers = {"Cache-Control": "private, max-age=86400"}