fix(webdav): the source type belongs in the cache key

The same bytes uploaded under two types are not the same thumbnail: the type picks the extractor, and with Tika in front what it finds depends on it.
This commit is contained in:
Dominik Schmidt committed 2026-10-20 16:03:06 +02:00
1 parent 4f79fdf9bb
commit 41b7160f3a
2 files changed
+12 -10

No files matched your search

@@ -129,9 +129,11 @@ func fileIsProcessing(info *providerv1beta1.ResourceInfo) bool {
//
// The checksum is hashed rather than used as it comes: it is not this service's
// to trust, an OCM share takes it from a remote PROPFIND, and it ends up as a
// path on disk and as an object key.
func thumbnailStorageKey(checksum string, w, h int, format, operation string) string {
sum := sha256.Sum256([]byte(checksum))
// path on disk and as an object key. The source type is hashed with it, because
// the same bytes under two types are not the same thumbnail: the type picks the
// extractor, and what it finds depends on it.
func thumbnailStorageKey(checksum, mimeType string, w, h int, format, operation string) string {
sum := sha256.Sum256([]byte(checksum + "\x00" + mimeType))
hash := hex.EncodeToString(sum[:])
return hash[:2] + "/" + hash[2:4] + "/" + hash[4:] + "/" + fmt.Sprintf("%dx%d-%s.%s", w, h, operation, format)
@@ -453,7 +455,7 @@ func (w *ThumbnailWorkflow) generate(ctx context.Context, ref *providerv1beta1.R
// requests that produce the same image share one entry and the number of
// entries per file stays bounded by the ladder. It needs nothing but the
// request, so a hit still returns without touching storage.
cacheKey := thumbnailStorageKey(checksum, box.Dx(), box.Dy(), outputFormat, operation)
cacheKey := thumbnailStorageKey(checksum, mimeType, box.Dx(), box.Dy(), outputFormat, operation)
if w.cache != nil {
cached, err := w.cache.Get(cacheKey)
@@ -421,7 +421,7 @@ var _ = Describe("ThumbnailWorkflow", func() {
Expect(data).To(Equal(thumbBytes))
Expect(contentType).To(Equal("image/jpeg"))
cached, err := testCache.Get(thumbnailStorageKey("cb56752477cae6405f85b131872c60d21b967c6a", 128, 128, "jpg", "fill"))
cached, err := testCache.Get(thumbnailStorageKey("cb56752477cae6405f85b131872c60d21b967c6a", "image/jpeg", 128, 128, "jpg", "fill"))
Expect(err).ToNot(HaveOccurred())
Expect(cached).To(Equal(thumbBytes))
})
@@ -936,13 +936,13 @@ var _ = Describe("ThumbnailWorkflow", func() {
},
Entry("a png keeps its alpha channel",
"image/png", "img.png", "smart/filters:format(png)", "image/png",
thumbnailStorageKey("1f0c9f1b6e4b4b2a9c1d7f3e8a5b6c7d8e9f0a1b", 64, 64, "png", "fill")),
thumbnailStorageKey("1f0c9f1b6e4b4b2a9c1d7f3e8a5b6c7d8e9f0a1b", "image/png", 64, 64, "png", "fill")),
Entry("a gif keeps its animation",
"image/gif", "anim.gif", "filters:format(gif)", "image/gif",
thumbnailStorageKey("1f0c9f1b6e4b4b2a9c1d7f3e8a5b6c7d8e9f0a1b", 64, 64, "gif", "stretch")),
thumbnailStorageKey("1f0c9f1b6e4b4b2a9c1d7f3e8a5b6c7d8e9f0a1b", "image/gif", 64, 64, "gif", "stretch")),
Entry("a bmp becomes a jpeg",
"image/bmp", "scan.bmp", "smart/filters:format(jpg)", "image/jpeg",
thumbnailStorageKey("1f0c9f1b6e4b4b2a9c1d7f3e8a5b6c7d8e9f0a1b", 64, 64, "jpg", "fill")),
thumbnailStorageKey("1f0c9f1b6e4b4b2a9c1d7f3e8a5b6c7d8e9f0a1b", "image/bmp", 64, 64, "jpg", "fill")),
)
It("follows a configured chain into a format the built-in generator cannot write", func() {
@@ -986,7 +986,7 @@ var _ = Describe("ThumbnailWorkflow", func() {
Describe("cache hit shortcut", func() {
It("should return cached thumbnail without calling generator or downloading the file", func() {
cachedThumb := []byte("cached-thumbnail")
err := testCache.Put(thumbnailStorageKey("cb56752477cae6405f85b131872c60d21b967c6a", 128, 128, "jpg", "fill"), cachedThumb)
err := testCache.Put(thumbnailStorageKey("cb56752477cae6405f85b131872c60d21b967c6a", "image/jpeg", 128, 128, "jpg", "fill"), cachedThumb)
Expect(err).ToNot(HaveOccurred())
// No download expectations are set up. If the workflow tried to
@@ -1266,7 +1266,7 @@ var _ = Describe("ThumbnailWorkflow", func() {
Expect(data).To(Equal(thumbBytes))
Expect(contentType).To(Equal("image/jpeg"))
cached, err := testCache.Get(thumbnailStorageKey("5ba1b086d95a7e0fd8ff4323caee0c412ab07fc3", 64, 64, "jpg", "fill"))
cached, err := testCache.Get(thumbnailStorageKey("5ba1b086d95a7e0fd8ff4323caee0c412ab07fc3", "image/jpeg", 64, 64, "jpg", "fill"))
Expect(err).ToNot(HaveOccurred())
Expect(cached).To(Equal(thumbBytes))
})