feat: 接入预览模式(Next.js Draft Mode)
This commit is contained in:
@@ -0,0 +1,54 @@
|
||||
import { NextRequest, NextResponse } from "next/server";
|
||||
import { draftMode, cookies } from "next/headers";
|
||||
import {
|
||||
fetchPreviewPage,
|
||||
resolvePreviewPath,
|
||||
PREVIEW_CONTENT_TYPE_COOKIE,
|
||||
PREVIEW_TOKEN_COOKIE,
|
||||
} from "@/services/preview.service";
|
||||
import type { WagtailPageSummary } from "@/types/wagtail";
|
||||
|
||||
/**
|
||||
* Wagtail 编辑器点击"预览"后会重定向到此路由(详见 wagtailcms/settings/base.py
|
||||
* 中 WAGTAIL_HEADLESS_PREVIEW.CLIENT_URLS)。校验 token 有效后开启 Next.js
|
||||
* Draft Mode 并重定向到对应内容的前端路由,由页面组件通过 getPreviewOrFallback
|
||||
* 拉取草稿数据渲染。
|
||||
*/
|
||||
export async function GET(request: NextRequest) {
|
||||
const contentType = request.nextUrl.searchParams.get("content_type");
|
||||
const token = request.nextUrl.searchParams.get("token");
|
||||
|
||||
if (!contentType || !token) {
|
||||
return NextResponse.json(
|
||||
{ error: "缺少 content_type 或 token 参数" },
|
||||
{ status: 400 },
|
||||
);
|
||||
}
|
||||
|
||||
// 先校验 token 是否有效并取回 slug,未开启 Draft Mode,避免暴露无效预览。
|
||||
const page = await fetchPreviewPage<WagtailPageSummary>(contentType, token);
|
||||
const path = page ? resolvePreviewPath(contentType, page) : null;
|
||||
|
||||
if (!page || !path) {
|
||||
return NextResponse.json(
|
||||
{ error: "预览链接无效或已过期" },
|
||||
{ status: 404 },
|
||||
);
|
||||
}
|
||||
|
||||
const draft = await draftMode();
|
||||
draft.enable();
|
||||
|
||||
const isProduction = process.env.NODE_ENV === "production";
|
||||
const cookieStore = await cookies();
|
||||
const cookieOptions = {
|
||||
httpOnly: true,
|
||||
sameSite: "lax" as const,
|
||||
secure: isProduction,
|
||||
path: "/",
|
||||
};
|
||||
cookieStore.set(PREVIEW_CONTENT_TYPE_COOKIE, contentType, cookieOptions);
|
||||
cookieStore.set(PREVIEW_TOKEN_COOKIE, token, cookieOptions);
|
||||
|
||||
return NextResponse.redirect(new URL(path, request.url));
|
||||
}
|
||||
Reference in New Issue
Block a user