fix: 支持解析工作流受管上传文件
- 优先通过上传记录验证后的读取器加载文件内容 - 保留普通存储与远端地址校验回退路径 - 补充来源读取和解析桥接回归测试
This commit is contained in:
@@ -221,7 +221,10 @@ public class DocumentParseBridgeServiceImplTest {
|
||||
pptxDocumentParseService,
|
||||
xlsxDocumentParseService,
|
||||
parseService,
|
||||
new DocumentSourceLoader(new InMemoryFileStorageService()));
|
||||
new DocumentSourceLoader(
|
||||
new InMemoryFileStorageService(),
|
||||
org.mockito.Mockito.mock(
|
||||
tech.easyflow.ai.easyagentsflow.upload.WorkflowApiUploadedFileReader.class)));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -292,7 +295,10 @@ public class DocumentParseBridgeServiceImplTest {
|
||||
private long maxBytes;
|
||||
|
||||
private RecordingDocumentSourceLoader() {
|
||||
super(new InMemoryFileStorageService());
|
||||
super(
|
||||
new InMemoryFileStorageService(),
|
||||
org.mockito.Mockito.mock(
|
||||
tech.easyflow.ai.easyagentsflow.upload.WorkflowApiUploadedFileReader.class));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -2,6 +2,8 @@ package tech.easyflow.ai.document.support;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mockito;
|
||||
import tech.easyflow.ai.easyagentsflow.upload.WorkflowApiUploadedFileReader;
|
||||
import tech.easyflow.ai.document.exception.DocumentParseBridgeException;
|
||||
import tech.easyflow.ai.document.model.DocumentSourceRef;
|
||||
import tech.easyflow.common.filestorage.FileStorageService;
|
||||
@@ -9,9 +11,8 @@ import tech.easyflow.common.filestorage.FileStorageService;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import com.sun.net.httpserver.HttpServer;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* {@link DocumentSourceLoader} 单元测试。
|
||||
@@ -54,66 +55,78 @@ public class DocumentSourceLoaderTest {
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证 filePath 为远端 URL 时不会误走存储读取。
|
||||
* 验证普通 filePath 远端 URL 仍拒绝访问回环地址。
|
||||
*/
|
||||
@Test
|
||||
public void shouldPreferRemoteDownloadWhenFilePathIsRemoteUrl() throws IOException {
|
||||
public void shouldRejectLoopbackWhenRemoteUrlIsNotManagedUpload() {
|
||||
DocumentSourceLoader loader = new DocumentSourceLoader(new FailingFileStorageService());
|
||||
HttpServer server = HttpServer.create(new InetSocketAddress(0), 0);
|
||||
byte[] body = "demo-pdf".getBytes(StandardCharsets.UTF_8);
|
||||
server.createContext("/demo.pdf", exchange -> {
|
||||
exchange.sendResponseHeaders(200, body.length);
|
||||
exchange.getResponseBody().write(body);
|
||||
exchange.close();
|
||||
});
|
||||
server.start();
|
||||
DocumentSourceRef sourceRef = new DocumentSourceRef();
|
||||
sourceRef.setFileName("demo.pdf");
|
||||
sourceRef.setFilePath("http://127.0.0.1:39000/demo.pdf");
|
||||
|
||||
try {
|
||||
DocumentSourceRef sourceRef = new DocumentSourceRef();
|
||||
sourceRef.setFileName("demo.pdf");
|
||||
sourceRef.setFilePath("http://127.0.0.1:" + server.getAddress().getPort() + "/demo.pdf");
|
||||
|
||||
LoadedDocumentSource loadedSource = loader.load(sourceRef);
|
||||
|
||||
Assert.assertEquals("demo.pdf", loadedSource.getFileName());
|
||||
Assert.assertArrayEquals(body, loadedSource.getContentBytes());
|
||||
} finally {
|
||||
server.stop(0);
|
||||
loader.load(sourceRef);
|
||||
Assert.fail("expected DocumentParseBridgeException");
|
||||
} catch (DocumentParseBridgeException exception) {
|
||||
Assert.assertEquals("source_load_failed", exception.getCode());
|
||||
Assert.assertTrue(exception.getCause() instanceof java.net.UnknownHostException);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证远端响应声明值不可信时仍按实际读取字节数拒绝超限内容。
|
||||
* 验证已通过上传记录校验的内网存储 URL 会走恢复句柄读取。
|
||||
*
|
||||
* @throws IOException 测试服务启动失败时抛出
|
||||
* @throws IOException 测试流创建失败时抛出
|
||||
*/
|
||||
@Test
|
||||
public void shouldRejectRemoteContentThatExceedsActualByteLimit() throws IOException {
|
||||
DocumentSourceLoader loader = new DocumentSourceLoader(new FailingFileStorageService());
|
||||
HttpServer server = HttpServer.create(new InetSocketAddress(0), 0);
|
||||
byte[] body = "123456789".getBytes(StandardCharsets.UTF_8);
|
||||
server.createContext("/oversized.pdf", exchange -> {
|
||||
exchange.sendResponseHeaders(200, 0);
|
||||
exchange.getResponseBody().write(body);
|
||||
exchange.close();
|
||||
});
|
||||
server.start();
|
||||
try {
|
||||
DocumentSourceRef sourceRef = new DocumentSourceRef();
|
||||
sourceRef.setFileName("oversized.pdf");
|
||||
sourceRef.setFilePath(
|
||||
"http://127.0.0.1:" + server.getAddress().getPort() + "/oversized.pdf");
|
||||
sourceRef.setSize(1L);
|
||||
public void shouldLoadVerifiedManagedUploadBeforeRemoteAddressGuard() throws IOException {
|
||||
WorkflowApiUploadedFileReader uploadedFileReader =
|
||||
Mockito.mock(WorkflowApiUploadedFileReader.class);
|
||||
DocumentSourceLoader loader = new DocumentSourceLoader(
|
||||
new FailingFileStorageService(),
|
||||
uploadedFileReader);
|
||||
String fileUrl = "http://127.0.0.1:39000/easyflow/attachment/"
|
||||
+ "workflow-api-upload/0123456789abcdef0123456789abcdef/file.pdf";
|
||||
byte[] body = "demo-pdf".getBytes(StandardCharsets.UTF_8);
|
||||
Mockito.when(uploadedFileReader.openVerified(fileUrl))
|
||||
.thenReturn(Optional.of(new ByteArrayInputStream(body)));
|
||||
DocumentSourceRef sourceRef = new DocumentSourceRef();
|
||||
sourceRef.setFileName("demo.pdf");
|
||||
sourceRef.setFilePath(fileUrl);
|
||||
|
||||
try {
|
||||
loader.load(sourceRef, 8L);
|
||||
Assert.fail("expected DocumentParseBridgeException");
|
||||
} catch (DocumentParseBridgeException exception) {
|
||||
Assert.assertEquals("source_load_failed", exception.getCode());
|
||||
Assert.assertTrue(exception.getCause()
|
||||
instanceof DocumentInputStreamSupport.SizeLimitExceededException);
|
||||
}
|
||||
} finally {
|
||||
server.stop(0);
|
||||
LoadedDocumentSource loadedSource = loader.load(sourceRef);
|
||||
|
||||
Assert.assertEquals("demo.pdf", loadedSource.getFileName());
|
||||
Assert.assertArrayEquals(body, loadedSource.getContentBytes());
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证受管上传文件仍按实际读取字节数拒绝超限内容。
|
||||
*/
|
||||
@Test
|
||||
public void shouldRejectManagedContentThatExceedsActualByteLimit() throws IOException {
|
||||
WorkflowApiUploadedFileReader uploadedFileReader =
|
||||
Mockito.mock(WorkflowApiUploadedFileReader.class);
|
||||
DocumentSourceLoader loader = new DocumentSourceLoader(
|
||||
new FailingFileStorageService(),
|
||||
uploadedFileReader);
|
||||
byte[] body = "123456789".getBytes(StandardCharsets.UTF_8);
|
||||
String fileUrl = "http://127.0.0.1:39000/easyflow/attachment/"
|
||||
+ "workflow-api-upload/0123456789abcdef0123456789abcdef/oversized.pdf";
|
||||
Mockito.when(uploadedFileReader.openVerified(fileUrl))
|
||||
.thenReturn(Optional.of(new ByteArrayInputStream(body)));
|
||||
DocumentSourceRef sourceRef = new DocumentSourceRef();
|
||||
sourceRef.setFileName("oversized.pdf");
|
||||
sourceRef.setFilePath(fileUrl);
|
||||
sourceRef.setSize(1L);
|
||||
|
||||
try {
|
||||
loader.load(sourceRef, 8L);
|
||||
Assert.fail("expected DocumentParseBridgeException");
|
||||
} catch (DocumentParseBridgeException exception) {
|
||||
Assert.assertEquals("source_load_failed", exception.getCode());
|
||||
Assert.assertTrue(exception.getCause()
|
||||
instanceof DocumentInputStreamSupport.SizeLimitExceededException);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user