Skip to content

Commit

Permalink
Add delta time to stale-while-revalidate header
Browse files Browse the repository at this point in the history
As per specification (RFC 5861), the cache control parameter
stale-while-revalidate accepts a duration in seconds
on how long serving stale (but unvalidated) requests is
considered to be acceptable. As far as I can tell omitting
this duration is not allowed by RFC 5861 at all.

At least some cloud providers refuse to accept this header
when it omits a duration, while they accept it when containing
a duration.

As far as I can tell the next.js interpretation of leaving out a value
was that it means "infinite". This commit approximates an infinite
duration with 1 year, which is consistent with the maxage parameter
sent for requests without revalidation.
  • Loading branch information
NobodysNightmare committed Jul 7, 2023
1 parent eb3d748 commit b7c7af8
Show file tree
Hide file tree
Showing 6 changed files with 25 additions and 25 deletions.
4 changes: 2 additions & 2 deletions packages/next/src/server/send-payload/revalidate-headers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ export function setRevalidateHeaders(

res.setHeader(
'Cache-Control',
`s-maxage=${options.revalidate}, stale-while-revalidate`
`s-maxage=${options.revalidate}, stale-while-revalidate=31536000`
)
} else if (options.revalidate === false) {
res.setHeader('Cache-Control', `s-maxage=31536000, stale-while-revalidate`)
res.setHeader('Cache-Control', `s-maxage=31536000, stale-while-revalidate=31536000`)
}
}
4 changes: 2 additions & 2 deletions test/e2e/prerender.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -599,7 +599,7 @@ describe('Prerender', () => {
expect(initialRes.headers.get('cache-control')).toBe(
isDeploy
? 'public, max-age=0, must-revalidate'
: 's-maxage=2, stale-while-revalidate'
: 's-maxage=2, stale-while-revalidate=31536000'
)
})
}
Expand Down Expand Up @@ -1265,7 +1265,7 @@ describe('Prerender', () => {
expect(initialRes.headers.get('cache-control')).toBe(
isDeploy
? 'public, max-age=0, must-revalidate'
: 's-maxage=31536000, stale-while-revalidate'
: 's-maxage=31536000, stale-while-revalidate=31536000'
)
const initialHtml = await initialRes.text()
expect(initialHtml).toMatch(/hello.*?world/)
Expand Down
12 changes: 6 additions & 6 deletions test/integration/not-found-revalidate/test/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ const runTests = () => {

const props = JSON.parse($('#props').text())
expect(res.headers.get('cache-control')).toBe(
's-maxage=1, stale-while-revalidate'
's-maxage=1, stale-while-revalidate=31536000'
)
expect(res.status).toBe(200)
expect(props.found).toBe(true)
Expand All @@ -114,7 +114,7 @@ const runTests = () => {

const props2 = JSON.parse($('#props').text())
expect(res.headers.get('cache-control')).toBe(
's-maxage=1, stale-while-revalidate'
's-maxage=1, stale-while-revalidate=31536000'
)
expect(res.status).toBe(200)
expect(props2.found).toBe(true)
Expand All @@ -127,7 +127,7 @@ const runTests = () => {

const props3 = JSON.parse($('#props').text())
expect(res.headers.get('cache-control')).toBe(
's-maxage=1, stale-while-revalidate'
's-maxage=1, stale-while-revalidate=31536000'
)
expect(res.status).toBe(200)
expect(props3.found).toBe(true)
Expand Down Expand Up @@ -157,7 +157,7 @@ const runTests = () => {

const props = JSON.parse($('#props').text())
expect(res.headers.get('cache-control')).toBe(
's-maxage=1, stale-while-revalidate'
's-maxage=1, stale-while-revalidate=31536000'
)
expect(res.status).toBe(200)
expect(props.found).toBe(true)
Expand All @@ -170,7 +170,7 @@ const runTests = () => {

const props2 = JSON.parse($('#props').text())
expect(res.headers.get('cache-control')).toBe(
's-maxage=1, stale-while-revalidate'
's-maxage=1, stale-while-revalidate=31536000'
)
expect(res.status).toBe(200)
expect(props2.found).toBe(true)
Expand All @@ -183,7 +183,7 @@ const runTests = () => {

const props3 = JSON.parse($('#props').text())
expect(res.headers.get('cache-control')).toBe(
's-maxage=1, stale-while-revalidate'
's-maxage=1, stale-while-revalidate=31536000'
)
expect(res.status).toBe(200)
expect(props3.found).toBe(true)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import next from 'next' // force a warning during `next build`
import { useRouter } from 'next/router'

export async function getServerSideProps({ res }) {
res.setHeader('cache-control', 's-maxage=1, stale-while-revalidate')
res.setHeader('cache-control', 's-maxage=1, stale-while-revalidate=31536000')

const data = await fs.promises.readFile(
path.join(process.cwd(), 'data.txt'),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ describe('should set-up next', () => {
})
expect(res.status).toBe(200)
expect(res.headers.get('cache-control')).toBe(
's-maxage=1, stale-while-revalidate'
's-maxage=1, stale-while-revalidate=31536000'
)

await waitFor(2000)
Expand All @@ -182,7 +182,7 @@ describe('should set-up next', () => {
})
expect(res2.status).toBe(404)
expect(res2.headers.get('cache-control')).toBe(
's-maxage=1, stale-while-revalidate'
's-maxage=1, stale-while-revalidate=31536000'
)
})

Expand All @@ -194,7 +194,7 @@ describe('should set-up next', () => {
})
expect(res.status).toBe(200)
expect(res.headers.get('cache-control')).toBe(
's-maxage=1, stale-while-revalidate'
's-maxage=1, stale-while-revalidate=31536000'
)

await next.patchFile('standalone/data.txt', 'hide')
Expand All @@ -206,7 +206,7 @@ describe('should set-up next', () => {

expect(res2.status).toBe(404)
expect(res2.headers.get('cache-control')).toBe(
's-maxage=1, stale-while-revalidate'
's-maxage=1, stale-while-revalidate=31536000'
)
})

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -192,13 +192,13 @@ describe('should set-up next', () => {
case: 'redirect no revalidate',
path: '/optional-ssg/redirect-1',
dest: '/somewhere',
cacheControl: 's-maxage=31536000, stale-while-revalidate',
cacheControl: 's-maxage=31536000, stale-while-revalidate=31536000',
},
{
case: 'redirect with revalidate',
path: '/optional-ssg/redirect-2',
dest: '/somewhere-else',
cacheControl: 's-maxage=5, stale-while-revalidate',
cacheControl: 's-maxage=5, stale-while-revalidate=31536000',
},
])(
`should have correct cache-control for $case`,
Expand Down Expand Up @@ -233,13 +233,13 @@ describe('should set-up next', () => {
case: 'notFound no revalidate',
path: '/optional-ssg/not-found-1',
dest: '/somewhere',
cacheControl: 's-maxage=31536000, stale-while-revalidate',
cacheControl: 's-maxage=31536000, stale-while-revalidate=31536000',
},
{
case: 'notFound with revalidate',
path: '/optional-ssg/not-found-2',
dest: '/somewhere-else',
cacheControl: 's-maxage=5, stale-while-revalidate',
cacheControl: 's-maxage=5, stale-while-revalidate=31536000',
},
])(
`should have correct cache-control for $case`,
Expand All @@ -266,7 +266,7 @@ describe('should set-up next', () => {
const res = await fetchViaHTTP(appPort, '/optional-ssg/props-no-revalidate')
expect(res.status).toBe(200)
expect(res.headers.get('cache-control')).toBe(
's-maxage=31536000, stale-while-revalidate'
's-maxage=31536000, stale-while-revalidate=31536000'
)
const $ = cheerio.load(await res.text())
expect(JSON.parse($('#props').text()).params).toEqual({
Expand All @@ -280,7 +280,7 @@ describe('should set-up next', () => {
)
expect(dataRes.status).toBe(200)
expect(res.headers.get('cache-control')).toBe(
's-maxage=31536000, stale-while-revalidate'
's-maxage=31536000, stale-while-revalidate=31536000'
)
expect((await dataRes.json()).pageProps.params).toEqual({
rest: ['props-no-revalidate'],
Expand Down Expand Up @@ -442,7 +442,7 @@ describe('should set-up next', () => {
})
expect(res.status).toBe(200)
expect(res.headers.get('cache-control')).toBe(
's-maxage=1, stale-while-revalidate'
's-maxage=1, stale-while-revalidate=31536000'
)

await waitFor(2000)
Expand All @@ -453,7 +453,7 @@ describe('should set-up next', () => {
})
expect(res2.status).toBe(404)
expect(res2.headers.get('cache-control')).toBe(
's-maxage=1, stale-while-revalidate'
's-maxage=1, stale-while-revalidate=31536000'
)
})

Expand All @@ -465,7 +465,7 @@ describe('should set-up next', () => {
})
expect(res.status).toBe(200)
expect(res.headers.get('cache-control')).toBe(
's-maxage=1, stale-while-revalidate'
's-maxage=1, stale-while-revalidate=31536000'
)

await next.patchFile('standalone/data.txt', 'hide')
Expand All @@ -477,7 +477,7 @@ describe('should set-up next', () => {

expect(res2.status).toBe(404)
expect(res2.headers.get('cache-control')).toBe(
's-maxage=1, stale-while-revalidate'
's-maxage=1, stale-while-revalidate=31536000'
)
})

Expand Down

0 comments on commit b7c7af8

Please sign in to comment.