55 lines
1.8 KiB
TypeScript
55 lines
1.8 KiB
TypeScript
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));
|
|
}
|