33 lines
1.2 KiB
TypeScript
33 lines
1.2 KiB
TypeScript
import type { ServerConfig } from '../config/server-config';
|
|
|
|
/** 数据库 objectKey 已含上传前缀;逐段编码且拒绝越界,不再次拼接前缀。 */
|
|
export function publicObjectUrl(
|
|
domain: string | null,
|
|
objectKey: string,
|
|
): string | null {
|
|
const parts = objectKey.split('/');
|
|
if (
|
|
!domain ||
|
|
objectKey.includes('\\') ||
|
|
[...objectKey].some(
|
|
(char) => char.charCodeAt(0) < 32 || char.charCodeAt(0) === 127,
|
|
) ||
|
|
parts.some((part) => !part || part === '.' || part === '..')
|
|
)
|
|
return null;
|
|
return `${domain}/${parts.map(encodeURIComponent).join('/')}`;
|
|
}
|
|
|
|
/** 字体等固定公开资源传备份相对路径,由配置统一补上传前缀;不解析旧 cloud 引用。 */
|
|
export function publicResourceUrl(
|
|
config: Pick<ServerConfig, 'qiniuPublicDomain' | 'qiniuKeyPrefix'>,
|
|
relativePath: string,
|
|
): string | null {
|
|
// 先独立验证相对路径,防止空路径或绝对路径被前缀掩盖。
|
|
if (!publicObjectUrl(config.qiniuPublicDomain, relativePath)) return null;
|
|
return publicObjectUrl(
|
|
config.qiniuPublicDomain,
|
|
`${config.qiniuKeyPrefix}${relativePath}`,
|
|
);
|
|
}
|