Repository navigation
Expand file tree
/
Copy pathroute.ts
More file actions
100 lines (93 loc) · 4.02 KB
/
Copy pathroute.ts
File metadata and controls
100 lines (93 loc) · 4.02 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
import { ROOT_PAGE_PATH } from "@repo/shared-data"
import { cookies, draftMode } from "next/headers"
import { hasLocale } from "next-intl"
import { getEnvVar } from "@/lib/env-vars"
import { redirect, routing } from "@/lib/navigation"
export async function GET(request: Request) {
const previewSecret = getEnvVar("STRAPI_PREVIEW_SECRET")
if (!previewSecret) {
console.warn(
"[STRAPI_PREVIEW]: Preview request received, but [STRAPI_PREVIEW_SECRET] has not been configured. Status: 404."
)
return new Response("Invalid Configuration", { status: 404 })
}
const { searchParams } = new URL(request.url)
// Check if the provided secret matches our secret key
const secret = String(searchParams.get("secret"))
if (secret !== previewSecret) {
console.warn(
"[STRAPI_PREVIEW]: Preview request received, but [secret] does not match [STRAPI_PREVIEW_SECRET]. Status: 401."
)
return new Response("Invalid token", { status: 401 })
}
// Validate the URL begins with ROOT_PAGE_PATH (e.g. index, with optional / for nested pages)
const urlParam = String(searchParams.get("url"))
const url = validPageUrlRegex.test(urlParam) ? urlParam : undefined
if (!url) {
return new Response("Invalid URL", { status: 404 })
}
// Check if the status in the request is configured correctly
const statusParam = String(searchParams.get("status"))
const status = validPageStatusKeys.has(statusParam)
? statusParam
: "published"
const dm = await draftMode()
if (status === "published") {
dm.disable()
} else {
/**
* This works by setting the `__prerender_bypass` response cookie, which is then used to display drafts
* This has a shortcoming when working with iframe embeddings (such as Strapi preview), where the cookie is being set from a different origin
* and therefore fails, so Strapi always displays the published version, because draftMode().isEnabled returns `false`
*/
dm.enable()
}
// ------ This code is a workaround for the aforementioned issue ------
const cookieStore = await cookies()
const draftCookie = cookieStore.get(draftModePrerenderCookieKey)
// If we have the cookie, update it with cross-origin iframe support
// NOTE: You cannot use any other cookie method other than .set() (such as .delete()), because
// they automatically assume the sameSite=Lax strategy, which will not work with iframes
cookieStore.set({
name: draftModePrerenderCookieKey,
value: draftCookie?.value || "",
/**
* Bounded lifetime instead of a session cookie: browsers restore session
* cookies across relaunches, so editors previously stayed stuck in draft
* mode indefinitely and reported the site "showing drafts". Each Preview
* open refreshes the window; `/api/exit-preview` ends it early.
*/
expires: draftCookie?.value ? Date.now() + DRAFT_MODE_COOKIE_TTL_MS : 0, // 0 => expires at timestamp 0 (deletes the cookie)
httpOnly: true,
path: "/",
secure: true,
sameSite: "none", // Allow cookie in cross-origin iframes
// Without this, browsers reject the cookie inside the Strapi
// admin iframe because that iframe is a different site from the frontend.
partitioned: true,
})
// --------------------------------------------------------------------
// Check if the locale in the request is a correct frontend locale
const localeParam = String(searchParams.get("locale"))
const locale = hasLocale(routing.locales, localeParam)
? localeParam
: routing.defaultLocale
console.warn(
`[STRAPI_PREVIEW]: Preview request generated. ${JSON.stringify({
locale,
url: {
urlParam,
processedUrl: `${url}`,
},
status,
})}`
)
// Redirect to the path from the fetched post
redirect({ href: `${url}`, locale })
}
const validPageStatusKeys = new Set(["draft", "published"])
const draftModePrerenderCookieKey = "__prerender_bypass"
const DRAFT_MODE_COOKIE_TTL_MS = 2 * 60 * 60 * 1000 // 2 hours
const validPageUrlRegex = new RegExp(
String.raw`^(${ROOT_PAGE_PATH}[a-zA-Z0-9-%]*)+$`
)