fix(web): /promotion 独立 try_files 防 SPA 误判;静态探测支持 Range 与 HTML 识别

Made-with: Cursor
This commit is contained in:
whm
2026-03-21 13:01:25 +08:00
parent d6767c2c5c
commit db3a8d8cd1
3 changed files with 36 additions and 13 deletions

View File

@@ -17,6 +17,12 @@ server {
add_header Cache-Control "public, immutable"; add_header Cache-Control "public, immutable";
} }
# 推广素材:文件必须真实存在,禁止落到 SPA index.html否则前端误判「静态存在」、视频拿到 HTML
location ^~ /promotion/ {
try_files $uri =404;
add_header Cache-Control "public, max-age=86400";
}
location = / { location = / {
try_files /index.html =404; try_files /index.html =404;
} }

View File

@@ -15,6 +15,11 @@ server {
add_header Cache-Control "public, immutable"; add_header Cache-Control "public, immutable";
} }
location ^~ /promotion/ {
try_files $uri =404;
add_header Cache-Control "public, max-age=86400";
}
location = / { location = / {
try_files /index.html =404; try_files /index.html =404;
} }

View File

@@ -44,8 +44,20 @@ export const PROMOTION_VIDEOS_BASE = [
} }
] ]
function responseLooksLikeSpaHtml(res) {
const ct = (res.headers.get('content-type') || '').toLowerCase()
return ct.includes('text/html')
}
function responseIsUsableAsset(res) {
if (res.ok) return !responseLooksLikeSpaHtml(res)
return res.status === 206
}
/** /**
* 检测同域静态 /promotion/ 文件是否可访问(优先 HEAD405 时用 Range GET * 检测同域静态 /promotion/ 文件是否真实存在。
* - 需配合 Nginx`location ^~ /promotion/ { try_files $uri =404; }`,避免缺失时返回 index.html 误判为 200。
* - HEAD 非 2xx 或疑似 SPA 回退时,再用 Range GET 探测(部分环境对 .mov 的 HEAD 不友好)。
* @param {string} url * @param {string} url
* @returns {Promise<boolean>} * @returns {Promise<boolean>}
*/ */
@@ -57,8 +69,8 @@ export async function promotionStaticUrlExists(url) {
credentials: 'same-origin', credentials: 'same-origin',
cache: 'default' cache: 'default'
}) })
if (head.ok) return true if (head.ok && !responseLooksLikeSpaHtml(head)) return true
if (head.status === 405) {
const r = await fetch(url, { const r = await fetch(url, {
method: 'GET', method: 'GET',
headers: { Range: 'bytes=0-0' }, headers: { Range: 'bytes=0-0' },
@@ -66,9 +78,9 @@ export async function promotionStaticUrlExists(url) {
credentials: 'same-origin', credentials: 'same-origin',
cache: 'default' cache: 'default'
}) })
return r.ok || r.status === 206 if (!responseIsUsableAsset(r)) return false
} if (responseLooksLikeSpaHtml(r)) return false
return false return true
} catch { } catch {
return false return false
} }