修复生成图片OSS签名缓存链路

前端将完整阿里云OSS generated 地址归一为 legacy path 后走 read-url 换签。

platform-oss 为 generated 私有对象 PostObject 和 PutObject 写入 immutable Cache-Control。

补齐 shared-contracts 与 api-server 直传票据字段映射。

更新后端、运维文档和 Hermes 团队记忆,明确不使用服务端磁盘缓存兜底。
This commit is contained in:
2026-06-07 17:19:03 +08:00
parent 3965f34b02
commit 5daeef21bf
10 changed files with 193 additions and 8 deletions

View File

@@ -67,6 +67,26 @@ export function isGeneratedLegacyPath(value: string) {
return /^\/?generated-[^/?#]+\/.+/u.test(value.trim());
}
function isAliyunOssHost(hostname: string) {
return /^[^.]+\.oss-[^.]+\.aliyuncs\.com$/iu.test(hostname.trim());
}
function resolveGeneratedLegacyPathFromUrl(value: string) {
try {
const parsedUrl = new URL(
value,
globalThis.location?.origin ?? 'http://localhost',
);
if (!isAliyunOssHost(parsedUrl.hostname)) {
return '';
}
const legacyPath = decodeURIComponent(parsedUrl.pathname);
return isGeneratedLegacyPath(legacyPath) ? legacyPath : '';
} catch {
return '';
}
}
function normalizeLegacyPublicPath(value: string) {
return `/${value.trim().replace(/^\/+/u, '')}`;
}
@@ -284,6 +304,21 @@ export async function resolveAssetReadUrl(
value.startsWith('data:') ||
value.startsWith('blob:')
) {
const legacyPath = resolveGeneratedLegacyPathFromUrl(value);
if (legacyPath) {
const signedUrl = await getSignedAssetReadUrl(
{
legacyPublicPath: legacyPath,
expireSeconds: options.expireSeconds,
},
options.signal,
{
bypassCache:
options.refreshKey !== null && options.refreshKey !== undefined,
},
);
return signedUrl;
}
return appendCacheBustParam(value, options.refreshKey);
}