feat(document): getThumbnailUrl appends URL-encoded timestamp as cache-buster
Matches the shape the frontend previously built via encodeURIComponent(thumbnailGeneratedAt), so the backend is now the single source of truth for the thumbnail URL convention (#309). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -8,6 +8,8 @@ import org.hibernate.annotations.UpdateTimestamp;
|
|||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
|
||||||
|
import java.net.URLEncoder;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
@@ -134,6 +136,8 @@ public class Document {
|
|||||||
|
|
||||||
public String getThumbnailUrl() {
|
public String getThumbnailUrl() {
|
||||||
if (thumbnailKey == null) return null;
|
if (thumbnailKey == null) return null;
|
||||||
return "/api/documents/" + id + "/thumbnail";
|
String base = "/api/documents/" + id + "/thumbnail";
|
||||||
|
if (thumbnailGeneratedAt == null) return base;
|
||||||
|
return base + "?v=" + URLEncoder.encode(thumbnailGeneratedAt.toString(), StandardCharsets.UTF_8);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package org.raddatz.familienarchiv.model;
|
|||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
@@ -36,4 +37,25 @@ class DocumentTest {
|
|||||||
assertThat(doc.getThumbnailUrl())
|
assertThat(doc.getThumbnailUrl())
|
||||||
.isEqualTo("/api/documents/" + id + "/thumbnail");
|
.isEqualTo("/api/documents/" + id + "/thumbnail");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void getThumbnailUrl_includesCacheBuster_whenBothKeyAndGeneratedAtPresent() {
|
||||||
|
UUID id = UUID.fromString("aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee");
|
||||||
|
LocalDateTime generatedAt = LocalDateTime.of(2026, 4, 23, 14, 30, 45);
|
||||||
|
Document doc = Document.builder()
|
||||||
|
.id(id)
|
||||||
|
.title("Brief")
|
||||||
|
.originalFilename("brief.pdf")
|
||||||
|
.status(DocumentStatus.UPLOADED)
|
||||||
|
.thumbnailKey("thumbnails/" + id + ".jpg")
|
||||||
|
.thumbnailGeneratedAt(generatedAt)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// frontend equivalent: `?v=${encodeURIComponent(doc.thumbnailGeneratedAt)}`
|
||||||
|
// where thumbnailGeneratedAt is the ISO-8601 string Jackson serialises.
|
||||||
|
// LocalDateTime.toString() produces "2026-04-23T14:30:45"; encodeURIComponent
|
||||||
|
// turns ":" into "%3A" but leaves "T" and digits alone.
|
||||||
|
String expected = "/api/documents/" + id + "/thumbnail?v=2026-04-23T14%3A30%3A45";
|
||||||
|
assertThat(doc.getThumbnailUrl()).isEqualTo(expected);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user