fix(SW-663): Fixed leaking of live preview hash and removing preview pages

This commit is contained in:
Erik Tiekstra
2024-11-07 12:49:13 +01:00
parent 0465f8e450
commit 953f860e5d
16 changed files with 117 additions and 301 deletions
+28 -34
View File
@@ -1,6 +1,6 @@
import "server-only"
import { ContentstackLivePreview } from "@contentstack/live-preview-utils"
// import { ContentstackLivePreview } from "@contentstack/live-preview-utils"
import { ClientError, GraphQLClient } from "graphql-request"
import { Lang } from "@/constants/languages"
@@ -17,47 +17,41 @@ export async function request<T>(
params?: RequestInit
): Promise<Data<T>> {
try {
const previewHash = ContentstackLivePreview.hash
client.setHeaders({
access_token: env.CMS_ACCESS_TOKEN,
"Content-Type": "application/json",
...params?.headers,
})
if (previewHash) {
client.setHeader("preview_token", env.CMS_PREVIEW_TOKEN)
client.setHeader("live_preview", previewHash)
} else {
client.requestConfig.cache = params?.cache
client.requestConfig.next = params?.next
client.requestConfig.cache = params?.cache
client.requestConfig.next = params?.next
if (env.PRINT_QUERY) {
const print = (await import("graphql/language/printer")).print
const rawResponse = await client.rawRequest<T>(
print(query as DocumentNode),
variables,
{
access_token: env.CMS_ACCESS_TOKEN,
"Content-Type": "application/json",
}
)
/**
* TODO: Send to Monitoring (Logging and Metrics)
*/
console.log({
complexityLimit: rawResponse.headers.get("x-query-complexity"),
})
console.log({
referenceDepth: rawResponse.headers.get("x-reference-depth"),
})
console.log({
resolverCost: rawResponse.headers.get("x-resolver-cost"),
})
return {
data: rawResponse.data,
if (env.PRINT_QUERY) {
const print = (await import("graphql/language/printer")).print
const rawResponse = await client.rawRequest<T>(
print(query as DocumentNode),
variables,
{
access_token: env.CMS_ACCESS_TOKEN,
"Content-Type": "application/json",
}
)
/**
* TODO: Send to Monitoring (Logging and Metrics)
*/
console.log({
complexityLimit: rawResponse.headers.get("x-query-complexity"),
})
console.log({
referenceDepth: rawResponse.headers.get("x-reference-depth"),
})
console.log({
resolverCost: rawResponse.headers.get("x-resolver-cost"),
})
return {
data: rawResponse.data,
}
}
-42
View File
@@ -1,42 +0,0 @@
import "server-only"
import { ContentstackLivePreview } from "@contentstack/live-preview-utils"
import { request as graphqlRequest } from "graphql-request"
import { env } from "@/env/server"
import type { DocumentNode } from "graphql"
import type { Data } from "@/types/request"
export async function previewRequest<T>(
query: string | DocumentNode,
variables?: {}
): Promise<Data<T>> {
try {
const hash = ContentstackLivePreview.hash
if (!hash) {
throw new Error("No hash received")
}
const headers = new Headers({
access_token: env.CMS_ACCESS_TOKEN,
preview_token: env.CMS_PREVIEW_TOKEN,
live_preview: hash,
})
const response = await graphqlRequest<T>({
document: query,
requestHeaders: headers,
url: env.CMS_PREVIEW_URL,
variables,
})
return { data: response }
} catch (error) {
console.error("Error in preview graphql request")
console.error(error)
throw new Error("Something went wrong")
}
}
+20 -6
View File
@@ -1,10 +1,10 @@
import { ContentstackLivePreview } from "@contentstack/live-preview-utils"
import fetchRetry from "fetch-retry"
import { DocumentNode } from "graphql"
import { GraphQLClient } from "graphql-request"
import { cache } from "react"
import { env } from "@/env/server"
import { getPreviewHash, isPreview } from "@/lib/previewContext"
import { request as _request } from "./_request"
@@ -12,12 +12,12 @@ import { Data } from "@/types/request"
export async function request<T>(
query: string | DocumentNode,
variables?: {},
variables?: Record<string, any>,
params?: RequestInit
): Promise<Data<T>> {
const previewHash = ContentstackLivePreview.hash
const cmsUrl = previewHash ? env.CMS_PREVIEW_URL : env.CMS_URL
const shouldUsePreview = isPreview(variables?.uid)
const previewHash = getPreviewHash()
const cmsUrl = shouldUsePreview ? env.CMS_PREVIEW_URL : env.CMS_URL
const client = new GraphQLClient(cmsUrl, {
fetch: cache(async function (url: URL | RequestInfo, params?: RequestInit) {
@@ -31,5 +31,19 @@ export async function request<T>(
}),
})
return _request(client, query, variables, params)
const mergedParams =
shouldUsePreview && previewHash
? {
...params,
headers: {
...params?.headers,
live_preview: previewHash,
preview_token: env.CMS_PREVIEW_TOKEN,
},
cache: undefined,
next: undefined,
}
: params
return _request(client, query, variables, mergedParams)
}
+42
View File
@@ -0,0 +1,42 @@
import { cache } from "react"
interface PreviewData {
hash: string
uid: string
}
const getRef = cache((): { current: PreviewData | undefined } => ({
current: undefined,
}))
/**
* Set the preview hash for the current request
*
* It works kind of like React's context,
* but on the server side, per request.
*
* @param hash
*/
export function setPreviewData(data: PreviewData | undefined) {
console.log("SETTING HASH")
getRef().current = data
}
/**
* Get the preview hash set for the current request
*/
export function getPreviewHash() {
return getRef().current?.hash
}
/**
* Check if the current request is a preview by comparing the uid
*/
export function isPreview(uid?: string) {
const data = getRef().current
if (uid && data?.hash) {
return data.uid === uid
}
return false
}