audio streaming app plyr.fm
38
fork

Configure Feed

Select the types of activity you want to include in your feed.

fix: add cache headers to sensitive-images endpoint (#784)

the frontend SSR fetches /moderation/sensitive-images on every page
load. during traffic spikes this exceeded the 120/minute rate limit
(1,179 hits over 7 days).

add Cache-Control header: public, s-maxage=300, max-age=60
- edge (cloudflare) caches for 5 minutes
- browser caches for 1 minute

this data changes rarely (only when admins flag images), so caching
is safe and massively reduces backend load.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>

authored by

nate nowack
Claude Opus 4.5
and committed by
GitHub
df4e09e2 4172014e

+20 -1
+8
STATUS.md
··· 55 55 56 56 --- 57 57 58 + #### sensitive-images cache headers (PR #784, Jan 24) 59 + 60 + **added edge caching for /moderation/sensitive-images** - the frontend SSR (`+layout.server.ts`) fetches sensitive images on every page load to filter NSFW content. during traffic spikes, this exceeded the 120/minute rate limit (1,179 rate limit hits over 7 days, mostly Jan 22 spike). 61 + 62 + **fix**: added `Cache-Control: public, s-maxage=300, max-age=60` header to the endpoint. cloudflare edge caches for 5 minutes, browsers cache for 1 minute. sensitive images list changes rarely (only when admins flag new images), so this is safe and massively reduces backend load. 63 + 64 + --- 65 + 58 66 #### listen receipts (PR #773, Jan 22) 59 67 60 68 **share links now track who clicked and played** - when you share a track, you get a URL with a `?ref=` code that records visitors and listeners:
+12 -1
backend/src/backend/api/moderation.py
··· 2 2 3 3 import logging 4 4 5 - from fastapi import APIRouter, Request 5 + from fastapi import APIRouter, Request, Response 6 6 from pydantic import BaseModel 7 7 8 8 from backend._internal.moderation_client import get_moderation_client ··· 22 22 urls: list[str] 23 23 24 24 25 + # cache TTLs for sensitive images endpoint 26 + # edge (CDN) caches for 5 minutes, browser caches for 1 minute 27 + # this data changes rarely (only when admins flag new images) 28 + SENSITIVE_IMAGES_CACHE_CONTROL = "public, s-maxage=300, max-age=60" 29 + 30 + 25 31 @router.get("/sensitive-images") 26 32 @limiter.limit("120/minute") 27 33 async def get_sensitive_images( 28 34 request: Request, 35 + response: Response, 29 36 ) -> SensitiveImagesResponse: 30 37 """get all flagged sensitive images. 31 38 ··· 34 41 35 42 returns both image_ids (for R2-stored images) and full URLs 36 43 (for external images like avatars). clients should check both. 44 + 45 + cached at edge (5 min) and browser (1 min) to reduce load from 46 + SSR page loads hitting this endpoint on every request. 37 47 """ 48 + response.headers["Cache-Control"] = SENSITIVE_IMAGES_CACHE_CONTROL 38 49 client = get_moderation_client() 39 50 result = await client.get_sensitive_images() 40 51