task-147: downloadUrl 永不过期验证(result/ 走下载域名、无签名参数、bucket 前缀、null/空白安全、输出稳定)+ 8 条测试

This commit is contained in:
2026-09-02 06:00:53 +08:00
parent eced873779
commit dc90ead263
@@ -0,0 +1,97 @@
package com.nanri.aiimage.modules.file.service.oss;
import com.nanri.aiimage.config.OssProperties;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* task-147downloadUrl 永不过期验证(plan 08)。
* generateFreshDownloadUrlresult/ 前缀走下载域名、非 result/ 走公开端点、
* URL 无签名(不含 X-Amz 系列 / Expires / Signature 等过期参数)、bucket 前缀正确、
* null/空白安全、同输入同输出稳定。
*/
class DownloadUrlNonExpiringTest {
private OssProperties properties;
private OssStorageService storageService;
@BeforeEach
void setUp() {
properties = new OssProperties();
properties.setEndpoint("https://oss.aishufu.top");
properties.setPublicEndpoint("https://oss.aishufu.top");
properties.setDownloadEndpoint("https://download.aishufu.top");
properties.setBucket("nanri-ai-images");
properties.setImageVideoBucket("shufu-video");
properties.setDigitalHumanBucket("nanri-ai-digital-human");
properties.setTemplateBucket("aiimage-templates");
properties.setAccessKeyId("test-access-key");
properties.setAccessKeySecret("test-secret-key");
storageService = new OssStorageService(properties);
}
@Test
void resultPrefixUsesDownloadEndpoint() {
assertEquals(
"https://download.aishufu.top/nanri-ai-images/result/publish/1/result.xlsx",
storageService.generateFreshDownloadUrl("result/publish/1/result.xlsx"));
}
@Test
void nonResultPrefixUsesPublicEndpoint() {
assertEquals(
"https://oss.aishufu.top/nanri-ai-images/supply_images/main.jpg",
storageService.generateFreshDownloadUrl("supply_images/main.jpg"));
}
@Test
void urlHasNoExpiringSignatureParameters() {
String url = storageService.generateFreshDownloadUrl("result/publish/1/result.xlsx");
assertFalse(url.contains("X-Amz-"), "不得包含 AWS 签名参数: " + url);
assertFalse(url.contains("Signature"), "不得包含签名: " + url);
assertFalse(url.contains("Expires"), "不得包含过期时间: " + url);
assertFalse(url.contains("?") || url.contains("&"), "不得携带任何查询参数: " + url);
}
@Test
void bucketPrefixIsCorrect() {
String url = storageService.generateFreshDownloadUrl("result/collect_data/2/data.xlsx");
assertTrue(url.contains("/nanri-ai-images/result/collect_data/2/data.xlsx"),
"主 bucket 前缀正确: " + url);
String imageUrl = storageService.generateFreshDownloadUrl("shufu-video/result/image_video/demo.mp4");
assertTrue(imageUrl.contains("/shufu-video/result/image_video/demo.mp4"),
"image-video bucket 前缀正确: " + imageUrl);
}
@Test
void nullUrlIsSafe() {
assertNull(storageService.generateFreshDownloadUrl(null), "null 输入返回 null 不抛错");
}
@Test
void blankUrlIsSafe() {
assertNull(storageService.generateFreshDownloadUrl(" "), "空白输入返回 null 不抛错");
assertNull(storageService.generateFreshDownloadUrl(""), "空串返回 null 不抛错");
}
@Test
void generatedUrlIsStable() {
String first = storageService.generateFreshDownloadUrl("result/similar_asin/3/re.xlsx");
String second = storageService.generateFreshDownloadUrl("result/similar_asin/3/re.xlsx");
assertEquals(first, second, "同输入同输出(无随机签名)");
}
@Test
void contractFrozen() {
String url = storageService.generateFreshDownloadUrl("result/similar_asin/3/re.xlsx");
assertNotNull(url);
// 快照:https://{download-endpoint}/{bucket}/{objectKey},纯路径无签名
assertEquals("https://download.aishufu.top/nanri-ai-images/result/similar_asin/3/re.xlsx", url);
}
}