From 4f06bf6551538044c418b041f785d5099be430b5 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 25 May 2026 06:41:06 +0000 Subject: [PATCH] =?UTF-8?q?fix(docs):=20resolveDocPath=20=E6=94=BE?= =?UTF-8?q?=E5=AE=BD=E8=B6=85=E6=97=B6+SSR=20UA+=E5=A4=B1=E8=B4=A5?= =?UTF-8?q?=E6=97=A5=E5=BF=97=EF=BC=8C=E4=BF=AE=E7=94=9F=E4=BA=A7=20404=20?= =?UTF-8?q?=E8=87=AA=E6=84=88=E5=A4=B1=E6=95=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit resolveDocPath 的 fetch 之前 400ms 超时太紧、catch 静默无日志, 导致 Vercel SSR 调后端 resolve 拿不到结果时静默降级 404,服务端 308 自愈在生产不生效(DB/后端/数据均已验证正常)。 - 超时 400ms → 2500ms(Vercel→CF→Oracle 跨区+冷缓存留余量) - 加 SSR UA + accept header(对齐 feed/page,规避 CF bot filter) - catch 与非 3xx 分支加 console.error(status/cf-ray/error), 便于从 Vercel 运行时日志定位真实失败原因 --- app/[locale]/docs/[...slug]/page.tsx | 30 ++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/app/[locale]/docs/[...slug]/page.tsx b/app/[locale]/docs/[...slug]/page.tsx index 2f3b051..5e9b25f 100644 --- a/app/[locale]/docs/[...slug]/page.tsx +++ b/app/[locale]/docs/[...slug]/page.tsx @@ -39,10 +39,20 @@ async function resolveDocPath( const strippedPath = `/docs/${slug.join("/")}`; try { const controller = new AbortController(); - const timeout = setTimeout(() => controller.abort(), 400); + // 跨区(Vercel→CF→Oracle)+ 后端冷缓存可能 >1s,400ms 太紧会误降级 404 + const timeout = setTimeout(() => controller.abort(), 2500); const res = await fetch( `${BACKEND_URL}/api/docs/resolve?path=${encodeURIComponent(strippedPath)}`, - { redirect: "manual", signal: controller.signal, cache: "no-store" }, + { + redirect: "manual", + signal: controller.signal, + cache: "no-store", + // 显式 UA:Vercel SSR 默认出口 UA 可能被 CF bot filter 拦(对齐 feed/page fetchLinks) + headers: { + accept: "application/json", + "user-agent": "InvolutionHell-SSR/1.0 (+https://involutionhell.com)", + }, + }, ); clearTimeout(timeout); if (res.status === 301 || res.status === 308) { @@ -51,9 +61,21 @@ async function resolveDocPath( if (loc && loc !== strippedPath) { return `/${locale}${loc}`; } + return null; } - } catch { - // 超时或后端不可达:降级到 notFound() + // 非 3xx:记录真实状态,便于从 Vercel 日志定位(CF 403 / 后端异常等) + console.error("[docs/resolve] non-redirect status", { + path: strippedPath, + status: res.status, + cfRay: res.headers.get("cf-ray"), + }); + } catch (err) { + // 超时(AbortError)或后端不可达:记录后降级 notFound() + console.error("[docs/resolve] fetch failed", { + path: strippedPath, + backend: BACKEND_URL, + error: err instanceof Error ? `${err.name}: ${err.message}` : String(err), + }); } return null; }