Make media URLs stable and cacheable, add real image thumbnails
Signed media URLs embedded the current second (TimestampSigner), so every API response re-minted every raw/thumbnail/staged URL and the browser re-downloaded each file on every poll or navigation. Responses also carried no cache headers at all. - sign with a plain Signer plus a bucket-quantized exp (7d TTL, 24h bucket), so a URL is byte-identical across responses and rotates once a day; legacy TimestampSigner URLs stay accepted for one release - add a v=<md5> version parameter to library media URLs so replacing a file under the same J-ID (the optimize flow) busts caches exactly when needed - serve_file now sends ETag/Last-Modified and a private Cache-Control and answers conditional requests with 304; library media gets max-age 6d + immutable, staged/similarity files 1h - build cached 480px JPEG thumbnails for images (Pillow, keyed by MD5 under MEDIA_ROOT/thumbs) instead of serving full-size originals through the thumbnail endpoint; the library grid uses thumbnail_url for images too
This commit is contained in:
@@ -3,7 +3,6 @@ from datetime import timedelta
|
||||
from pathlib import Path
|
||||
|
||||
from django.conf import settings
|
||||
from django.core import signing
|
||||
from rest_framework import serializers
|
||||
|
||||
from .models import (
|
||||
@@ -20,6 +19,7 @@ from .services import (
|
||||
VIDEO_EXTENSIONS,
|
||||
signed_media_url,
|
||||
)
|
||||
from .signing_urls import sign_payload
|
||||
|
||||
|
||||
class MediaLocationSerializer(serializers.ModelSerializer):
|
||||
@@ -199,9 +199,9 @@ class TempUploadSerializer(serializers.ModelSerializer):
|
||||
user = self._request_user()
|
||||
if user is None:
|
||||
return None
|
||||
signature = signing.dumps(
|
||||
signature = sign_payload(
|
||||
{"temp": str(obj.id), "user": user.id},
|
||||
salt=UPLOAD_FILE_SALT,
|
||||
UPLOAD_FILE_SALT,
|
||||
)
|
||||
url = f"/api/uploads/{obj.id}/file/?sig={signature}"
|
||||
request = self.context.get("request")
|
||||
@@ -339,9 +339,9 @@ class SimilarityCheckSerializer(serializers.ModelSerializer):
|
||||
user = self._request_user()
|
||||
if user is None or not obj.file:
|
||||
return None
|
||||
signature = signing.dumps(
|
||||
signature = sign_payload(
|
||||
{"check": str(obj.id), "user": user.id},
|
||||
salt=UPLOAD_FILE_SALT,
|
||||
UPLOAD_FILE_SALT,
|
||||
)
|
||||
url = f"/api/similarity/{obj.id}/file/?sig={signature}"
|
||||
request = self.context.get("request")
|
||||
|
||||
Reference in New Issue
Block a user