Refactor thumbnail URI handling to ensure proper ASCII encoding and improve srcset generation

feat/add-thumbnail-router
John Niang 2025-09-30 00:26:13 +08:00
parent 57602d60a2
commit b6ab744d15
No known key found for this signature in database
GPG Key ID: D7363C015BBCAA59
5 changed files with 28 additions and 11 deletions

View File

@ -54,7 +54,7 @@ public enum ThumbnailUtils {
.collect(Collectors.toMap(t -> t, t ->
UriComponentsBuilder.fromUri(permalink)
.queryParam("width", t.getWidth())
.build()
.build(true)
.toUri()
));
}

View File

@ -36,7 +36,6 @@ import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.util.unit.DataSize;
import org.springframework.web.util.UriComponentsBuilder;
import org.springframework.web.util.UriUtils;
import reactor.core.Exceptions;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@ -155,14 +154,14 @@ class LocalAttachmentUploadHandler implements AttachmentHandler {
attachment.setSpec(spec);
attachment.setStatus(new Attachment.AttachmentStatus());
doGetPermalink(attachment).ifPresent(permalink -> {
attachment.getStatus().setPermalink(permalink.toASCIIString());
});
doGetPermalink(attachment).ifPresent(permalink ->
attachment.getStatus().setPermalink(permalink.toASCIIString())
);
var thumbnailLinks = doGetThumbnailLinks(attachment);
var thumbnails = thumbnailLinks.keySet().stream()
.collect(Collectors.toMap(
ThumbnailSize::name,
size -> thumbnailLinks.get(size).toString()
size -> thumbnailLinks.get(size).toASCIIString()
));
if (!thumbnails.isEmpty()) {
attachment.getStatus().setThumbnails(thumbnails);
@ -319,11 +318,10 @@ class LocalAttachmentUploadHandler implements AttachmentHandler {
}
var uriStr = annotations.get(Constant.URI_ANNO_KEY);
// the uriStr is encoded before.
uriStr = UriUtils.decode(uriStr, StandardCharsets.UTF_8);
var uri = UriComponentsBuilder.fromUri(externalUrl.get())
// The URI has been encoded before, so there is no need to encode it again.
.path(uriStr)
.build()
.build(true)
.toUri();
return Optional.of(uri);
}

View File

@ -18,8 +18,10 @@ public class ThumbnailFinderImpl implements ThumbnailFinder {
@Override
public Mono<String> gen(String uriStr, String size) {
return thumbnailService.get(URI.create(uriStr), ThumbnailSize.fromName(size))
.map(URI::toASCIIString);
return Mono.fromCallable(() -> URI.create(uriStr))
.flatMap(uri -> thumbnailService.get(uri, ThumbnailSize.fromName(size)))
.map(URI::toASCIIString)
.onErrorReturn(IllegalArgumentException.class, uriStr);
}
}

View File

@ -1,8 +1,11 @@
package run.halo.app.core.attachment;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.net.URI;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import org.springframework.http.MediaType;
@ -26,4 +29,17 @@ class ThumbnailUtilsTest {
assertFalse(ThumbnailUtils.isSupportedImage(MediaType.parseMediaType(mimeType)));
}
@Test
void shouldBuildSrcSetWithUriWithSpecialCharacters() {
var permalink = URI.create("/中文.png").toASCIIString();
var srcsetMap = ThumbnailUtils.buildSrcsetMap(URI.create(permalink));
assertEquals("/%E4%B8%AD%E6%96%87.png?width=400",
srcsetMap.get(ThumbnailSize.S).toString());
assertEquals("/%E4%B8%AD%E6%96%87.png?width=800",
srcsetMap.get(ThumbnailSize.M).toString());
assertEquals("/%E4%B8%AD%E6%96%87.png?width=1200",
srcsetMap.get(ThumbnailSize.L).toString());
assertEquals("/%E4%B8%AD%E6%96%87.png?width=1600",
srcsetMap.get(ThumbnailSize.XL).toString());
}
}

View File

@ -1,6 +1,7 @@
package run.halo.app.theme.finders.impl;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@ -37,7 +38,7 @@ class ThumbnailFinderImplTest {
.expectNext("invalid uri")
.verifyComplete();
verify(thumbnailService, times(0)).generate(any(), any());
verify(thumbnailService, never()).get(any(), any());
}
@Test