Skip to content

Commit

Permalink
Ensure On-Demand revalidate does not consider preview cookie (#39313)
Browse files Browse the repository at this point in the history
  • Loading branch information
ijjk committed Aug 4, 2022
1 parent 6b49d47 commit d315ee1
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 0 deletions.
7 changes: 7 additions & 0 deletions packages/next/server/api-utils/node.ts
Expand Up @@ -2,6 +2,7 @@ import type { IncomingMessage, ServerResponse } from 'http'
import type { NextApiRequest, NextApiResponse } from '../../shared/lib/utils'
import type { PageConfig } from 'next/types'
import {
checkIsManualRevalidate,
PRERENDER_REVALIDATE_ONLY_GENERATED_HEADER,
__ApiPreviewProps,
} from '.'
Expand Down Expand Up @@ -41,6 +42,12 @@ export function tryGetPreviewData(
res: ServerResponse | BaseNextResponse,
options: __ApiPreviewProps
): PreviewData {
// if an On-Demand revalidation is being done preview mode
// is disabled
if (options && checkIsManualRevalidate(req, options).isManualRevalidate) {
return false
}

// Read cached preview data if present
if (SYMBOL_PREVIEW_DATA in req) {
return (req as any)[SYMBOL_PREVIEW_DATA] as any
Expand Down
75 changes: 75 additions & 0 deletions test/e2e/prerender.test.ts
@@ -1,4 +1,5 @@
import fs from 'fs-extra'
import cookie from 'cookie'
import cheerio from 'cheerio'
import { join, sep } from 'path'
import escapeRegex from 'escape-string-regexp'
Expand Down Expand Up @@ -178,6 +179,11 @@ describe('Prerender', () => {
initialRevalidateSeconds: 1,
srcRoute: null,
},
'/preview': {
dataRoute: `/_next/data/${next.buildId}/preview.json`,
initialRevalidateSeconds: false,
srcRoute: null,
},
'/api-docs/first': {
dataRoute: `/_next/data/${next.buildId}/api-docs/first.json`,
initialRevalidateSeconds: false,
Expand Down Expand Up @@ -1518,6 +1524,14 @@ describe('Prerender', () => {
p: 'p',
},
},
{
dataRouteRegex: normalizeRegEx(
`^\\/_next\\/data\\/${escapeRegex(
next.buildId
)}\\/preview.json$`
),
page: '/preview',
},
{
dataRouteRegex: normalizeRegEx(
`^\\/_next\\/data\\/${escapeRegex(
Expand Down Expand Up @@ -1772,6 +1786,67 @@ describe('Prerender', () => {
})
}

it('should revalidate manual revalidate with preview cookie', async () => {
const initialRes = await fetchViaHTTP(next.url, '/preview')
expect(initialRes.status).toBe(200)

const initial$ = cheerio.load(await initialRes.text())
const initialProps = JSON.parse(initial$('#props').text())

expect(initialProps).toEqual({
preview: false,
previewData: null,
})

const previewRes = await fetchViaHTTP(next.url, '/api/enable')
let previewCookie = ''

expect(previewRes.headers.get('set-cookie')).toMatch(
/(__prerender_bypass|__next_preview_data)/
)

previewRes.headers
.get('set-cookie')
.split(',')
.forEach((c) => {
c = cookie.parse(c)
const isBypass = c.__prerender_bypass

if (isBypass || c.__next_preview_data) {
if (previewCookie) previewCookie += '; '

previewCookie += `${
isBypass ? '__prerender_bypass' : '__next_preview_data'
}=${c[isBypass ? '__prerender_bypass' : '__next_preview_data']}`
}
})

const apiRes = await fetchViaHTTP(
next.url,
'/api/manual-revalidate',
{ pathname: '/preview' },
{
headers: {
cookie: previewCookie,
},
}
)

expect(apiRes.status).toBe(200)
expect(await apiRes.json()).toEqual({ revalidated: true })

const postRevalidateRes = await fetchViaHTTP(next.url, '/preview')
expect(initialRes.status).toBe(200)

const postRevalidate$ = cheerio.load(await postRevalidateRes.text())
const postRevalidateProps = JSON.parse(postRevalidate$('#props').text())

expect(postRevalidateProps).toEqual({
preview: false,
previewData: null,
})
})

it('should handle revalidating HTML correctly', async () => {
const route = '/blog/post-2/comment-2'
const initialHtml = await renderViaHTTP(next.url, route)
Expand Down
4 changes: 4 additions & 0 deletions test/e2e/prerender/pages/api/enable.js
@@ -0,0 +1,4 @@
export default function handler(req, res) {
res.setPreviewData({ hello: 'world' })
res.json({ enabled: true })
}
17 changes: 17 additions & 0 deletions test/e2e/prerender/pages/preview.js
@@ -0,0 +1,17 @@
export function getStaticProps({ preview, previewData }) {
return {
props: {
preview: preview || false,
previewData: previewData || null,
},
}
}

export default function Page(props) {
return (
<>
<p id="page">/preview</p>
<p id="props">{JSON.stringify(props)}</p>
</>
)
}

0 comments on commit d315ee1

Please sign in to comment.