fix(proxy): stable image-proxy URLs so expo-image actually caches thumbnails

make_token embedded the current timestamp in the expiry, so every /scenes fetch
produced a DIFFERENT proxied URL for the same thumbnail → expo-image (keyed by URI)
cache-missed and re-downloaded every list load / app launch. Add stable_bucket_sec:
quantize the expiry base to a window so the URL is identical across requests.
_wrap_image_proxy uses a 7-day bucket → thumbnails disk-cache for a week instead of
re-fetching constantly. Answers "czy miniatury są cache'owane" — now yes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
jtrzupek 2026-06-09 09:45:22 +02:00
parent 3e8a221981
commit abddd27856
2 changed files with 12 additions and 2 deletions

View file

@ -456,7 +456,9 @@ def _wrap_image_proxy(url: str, referer: str) -> str:
znać sekretu Referer backend wstawi sam. Long TTL (30d) bo thumby
stabilne, krótkie ttl by tylko niepotrzebnie zaśmiecało cache."""
from app.api.stream_proxy import make_token
token = make_token(url, referer, ttl_sec=30 * 24 * 3600)
# stable_bucket_sec=7d → proxied URL identyczny przez tydzień → expo-image
# disk-cache hit zamiast re-download miniatur przy każdym fetchu listy / starcie apki.
token = make_token(url, referer, ttl_sec=30 * 24 * 3600, stable_bucket_sec=7 * 24 * 3600)
# Path zachowuje rozszerzenie żeby HTTP Content-Type był rozpoznany.
import os as _os
ext = _os.path.splitext(url.split("?")[0])[1].lstrip(".") or "jpg"

View file

@ -162,6 +162,7 @@ def make_token(
refresh: str | None = None,
refresh_hoster: str | None = None,
impersonate: bool = False,
stable_bucket_sec: int | None = None,
) -> str:
"""Build proxy token.
@ -171,8 +172,15 @@ def make_token(
dispatch do dedicated re-extract logic.
`impersonate`: użyć curl_cffi chrome120 zamiast httpx (dla hosterów z JA3 bot
detection mxcontent, cloudflare-protected).
`stable_bucket_sec`: kwantyzuje czas bazowy expiry do okna N sekund, więc token
( proxied URL) jest IDENTYCZNY dla wszystkich requestów w oknie. Bez tego `e`
zawiera bieżący timestamp URL inny przy każdym fetchu listy expo-image cache
miss re-download miniatur za każdym razem. Dla thumbów (stabilne) dajemy 7d bucket
URL stały przez tydzień disk-cache hit. exp = bucket_start + ttl (zawsze > now).
"""
payload: dict = {"u": url, "r": referer or "", "e": int(time.time()) + ttl_sec}
now = int(time.time())
base = (now // stable_bucket_sec) * stable_bucket_sec if stable_bucket_sec else now
payload: dict = {"u": url, "r": referer or "", "e": base + ttl_sec}
if refresh:
payload["rf"] = refresh
if refresh_hoster: