78 lines
2.1 KiB
TypeScript
78 lines
2.1 KiB
TypeScript
import { CNDHOST } from './../app.config'
|
||
const ensureTrailingSlash = (s: string) => (s.endsWith('/') ? s : s + '/')
|
||
|
||
/**
|
||
* 从 CDN 地址中提取 key(例如返回 material/xxx.mp4)
|
||
* @param input 完整URL,如 https://cdn.roasmax.cn/material/xxx.mp4?x=y
|
||
* @param cdnHost 可选,默认使用 https://cdn.roasmax.cn/
|
||
*/
|
||
export const extractCdnKey = (input: string, cdnHost = CNDHOST): string | null => {
|
||
if (!input) return null
|
||
|
||
const base = ensureTrailingSlash(cdnHost)
|
||
|
||
// 简单前缀匹配(最快)
|
||
if (input?.startsWith(base)) {
|
||
const rest = input.slice(base.length)
|
||
return rest.split(/[?#]/)[0].replace(/^\/+/, '')
|
||
}
|
||
|
||
// URL 解析兜底
|
||
try {
|
||
const u = new URL(input)
|
||
const b = new URL(base)
|
||
if (u.origin === b.origin) {
|
||
return u.pathname.replace(/^\/+/, '')
|
||
}
|
||
return null
|
||
} catch {
|
||
// 不是URL,直接返回 null
|
||
return null
|
||
}
|
||
}
|
||
|
||
/** 判断是否为指定 CDN 的地址 */
|
||
export const isFromCdn = (input: string, cdnHost = CNDHOST): boolean => {
|
||
if (!input) return false
|
||
try {
|
||
const u = new URL(input)
|
||
const b = new URL(ensureTrailingSlash(cdnHost))
|
||
return u.origin === b.origin
|
||
} catch {
|
||
return input.startsWith(ensureTrailingSlash(cdnHost))
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 将 key 拼接为完整 CDN URL。若传入已是完整URL则直接返回规范化结果
|
||
* @param keyOrUrl 资源 key 或 完整 URL
|
||
* @param cdnHost CDN 根域名
|
||
*/
|
||
export const buildCdnUrl = (keyOrUrl: string, cdnHost = CNDHOST): string | null => {
|
||
if (!keyOrUrl) return null
|
||
const base = ensureTrailingSlash(cdnHost)
|
||
|
||
// 已是该 CDN 的完整 URL,返回去除查询/哈希后的规范化结果
|
||
if (isFromCdn(keyOrUrl, cdnHost)) {
|
||
try {
|
||
const u = new URL(keyOrUrl)
|
||
return `${u.origin}${u.pathname}`
|
||
} catch {
|
||
return keyOrUrl
|
||
}
|
||
}
|
||
|
||
// 传入为其他域的URL或纯key,提取路径作为key再拼接
|
||
const pathOrKey = (() => {
|
||
try {
|
||
const u = new URL(keyOrUrl)
|
||
return u.pathname
|
||
} catch {
|
||
return keyOrUrl
|
||
}
|
||
})()
|
||
|
||
const cleaned = pathOrKey.split(/[?#]/)[0].replace(/^\/+/, '')
|
||
return base + cleaned
|
||
}
|