refactor: optimize request headers when generating thumbnails from URI (#6628)

#### What type of PR is this?
/kind improvement
/area core
/milestone 2.20.x

#### What this PR does / why we need it:
优化根据 URI 生成缩略图时的请求头

1. 由于之前 attachment 的 permalink 是 `URI.toString` 会导致根据 permalink 索引查询附件可能由于编码问题无法查询到导致生成缩略图只能根据 URI 生成
2. 可能配置了 nginx 判断请求头不允许脚本请求如导致根据 URI 访问图片无法访问导致无法生成,如
```
if ($http_user agent ~*(python curlljava wget go-http-client httpclient okhttp)){
}
```

Fixes #6627

#### Does this PR introduce a user-facing change?
```release-note
None
```
pull/6638/head
guqing 2024-09-10 17:28:10 +08:00 committed by GitHub
parent b02ab8d809
commit 39545a1e4c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 19 additions and 5 deletions

View File

@ -6,6 +6,7 @@ import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;
@ -172,7 +173,11 @@ public class ThumbnailGenerator {
File tempFile = File.createTempFile("halo-image-thumb-", ".tmp");
long totalBytesDownloaded = 0;
var tempFilePath = tempFile.toPath();
try (InputStream inputStream = url.openStream();
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestProperty("User-Agent",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko)"
+ " Chrome/92.0.4515.131 Safari/537.36");
try (InputStream inputStream = connection.getInputStream();
FileOutputStream outputStream = new FileOutputStream(tempFile)) {
byte[] buffer = new byte[4096];

View File

@ -58,7 +58,7 @@ public class AttachmentReconciler implements Reconciler<Request> {
var annotations = attachment.getMetadata().getAnnotations();
if (annotations != null) {
attachmentService.getPermalink(attachment)
.map(URI::toString)
.map(URI::toASCIIString)
.switchIfEmpty(Mono.fromSupplier(() -> {
// Only for back-compatibility
return annotations.get(Constant.EXTERNAL_LINK_ANNO_KEY);

View File

@ -27,6 +27,7 @@ import run.halo.app.core.extension.attachment.Attachment;
import run.halo.app.core.extension.attachment.Constant;
import run.halo.app.core.extension.attachment.LocalThumbnail;
import run.halo.app.extension.ExtensionClient;
import run.halo.app.extension.ExtensionUtil;
import run.halo.app.extension.ListOptions;
import run.halo.app.extension.PageRequestImpl;
import run.halo.app.extension.controller.Controller;
@ -47,6 +48,9 @@ public class LocalThumbnailsReconciler implements Reconciler<Reconciler.Request>
public Result reconcile(Request request) {
client.fetch(LocalThumbnail.class, request.name())
.ifPresent(thumbnail -> {
if (ExtensionUtil.isDeleted(thumbnail)) {
return;
}
if (shouldGenerate(thumbnail)) {
requestGenerateThumbnail(thumbnail);
nullSafeAnnotations(thumbnail).remove(REQUEST_TO_GENERATE_ANNO);

View File

@ -4,11 +4,13 @@ import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
@ -57,7 +59,9 @@ class ThumbnailGeneratorTest {
String mockImageData = "fakeImageData";
InputStream mockInputStream = new ByteArrayInputStream(mockImageData.getBytes());
doAnswer(invocation -> mockInputStream).when(spyImageUrl).openStream();
var urlConnection = mock(HttpURLConnection.class);
doAnswer(invocation -> urlConnection).when(spyImageUrl).openConnection();
doReturn(mockInputStream).when(urlConnection).getInputStream();
var path = imageDownloader.downloadFileInternal(spyImageUrl);
assertThat(path).isNotNull();
@ -81,8 +85,9 @@ class ThumbnailGeneratorTest {
var fileSizeByte = ThumbnailGenerator.MAX_FILE_SIZE + 10;
byte[] largeImageData = new byte[fileSizeByte];
InputStream mockInputStream = new ByteArrayInputStream(largeImageData);
doReturn(mockInputStream).when(spyImageUrl).openStream();
var urlConnection = mock(HttpURLConnection.class);
doAnswer(invocation -> urlConnection).when(spyImageUrl).openConnection();
doReturn(mockInputStream).when(urlConnection).getInputStream();
assertThatThrownBy(() -> imageDownloader.downloadFileInternal(spyImageUrl))
.isInstanceOf(IOException.class)
.hasMessageContaining("File size exceeds the limit");