diff --git a/application/src/main/java/run/halo/app/core/attachment/endpoint/LocalAttachmentUploadHandler.java b/application/src/main/java/run/halo/app/core/attachment/endpoint/LocalAttachmentUploadHandler.java index 3de4453bf..837ed57c1 100644 --- a/application/src/main/java/run/halo/app/core/attachment/endpoint/LocalAttachmentUploadHandler.java +++ b/application/src/main/java/run/halo/app/core/attachment/endpoint/LocalAttachmentUploadHandler.java @@ -283,18 +283,27 @@ class LocalAttachmentUploadHandler implements AttachmentHandler { return Mono.just(doGetThumbnailLinks(attachment)); } - private Optional doGetPermalink(Attachment attachment) { + protected Optional doGetPermalink(Attachment attachment) { var annotations = attachment.getMetadata().getAnnotations(); if (annotations == null || !annotations.containsKey(Constant.URI_ANNO_KEY)) { return Optional.empty(); } var uriStr = annotations.get(Constant.URI_ANNO_KEY); - var uri = UriComponentsBuilder.fromUri(externalUrl.get()) - // The URI has been encoded before, so there is no need to encode it again. - .path(uriStr) - .build(true) - .toUri(); + URI uri; + try { + uri = UriComponentsBuilder.fromUri(externalUrl.get()) + // The URI has been encoded before, so there is no need to encode it again. + .path(uriStr) + .build(true) + .toUri(); + } catch (IllegalArgumentException e) { + // The URI may not be encoded, so we need to build with encoding. + uri = UriComponentsBuilder.fromUri(externalUrl.get()) + .path(uriStr) + .build() + .toUri(); + } return Optional.of(uri); } diff --git a/application/src/test/java/run/halo/app/core/attachment/endpoint/LocalAttachmentUploadHandlerTest.java b/application/src/test/java/run/halo/app/core/attachment/endpoint/LocalAttachmentUploadHandlerTest.java index fe0bce2f9..b343c0b4e 100644 --- a/application/src/test/java/run/halo/app/core/attachment/endpoint/LocalAttachmentUploadHandlerTest.java +++ b/application/src/test/java/run/halo/app/core/attachment/endpoint/LocalAttachmentUploadHandlerTest.java @@ -17,6 +17,7 @@ import java.util.Map; import java.util.function.Consumer; import java.util.stream.Stream; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.io.TempDir; import org.junit.jupiter.params.ParameterizedTest; @@ -32,9 +33,11 @@ import reactor.core.publisher.Flux; import reactor.test.StepVerifier; import run.halo.app.core.attachment.AttachmentRootGetter; import run.halo.app.core.extension.attachment.Attachment; +import run.halo.app.core.extension.attachment.Constant; import run.halo.app.core.extension.attachment.Policy; import run.halo.app.core.extension.attachment.endpoint.UploadOption; import run.halo.app.extension.ConfigMap; +import run.halo.app.extension.Metadata; import run.halo.app.infra.ExternalUrlSupplier; @ExtendWith(MockitoExtension.class) @@ -210,4 +213,16 @@ class LocalAttachmentUploadHandlerTest { } + @Test + void shouldGetPermalinkWhenUriContainsIllegalChars() { + var attachment = new Attachment(); + attachment.setMetadata(new Metadata()); + attachment.getMetadata().setAnnotations(Map.of( + Constant.URI_ANNO_KEY, "/path/with space.png" + )); + var permalink = uploadHandler.doGetPermalink(attachment); + assertTrue(permalink.isPresent()); + assertEquals("/path/with%20space.png", permalink.get().toASCIIString()); + } + } \ No newline at end of file