1
0
mirror of synced 2026-01-08 21:02:10 -05:00

Merge pull request #18418 from github/repo-sync

repo sync
This commit is contained in:
Octomerger Bot
2022-06-03 12:28:37 -05:00
committed by GitHub
4 changed files with 80 additions and 14 deletions

View File

@@ -0,0 +1,14 @@
// This middleware allows the client to cause the server-side processing to fail with a specific error.
// It is used for testing error handling with Fastly. It should only be enabled in non-production environments!
//
// NOTE: This middleware is intended to be removed once testing is complete!
//
export default function fastlyBehavior(req, res, next) {
if ((req.method === 'GET' || req.method === 'HEAD') && req.get('X-CacheTest-Error')) {
const error = parseInt(req.get('X-CacheTest-Error'))
res.status(error).send(`SIMULATED ERROR ${error}`)
return
}
next()
}

View File

@@ -7,21 +7,36 @@
//
// NOTE: This middleware is intended to be removed once testing is complete!
//
export default function fastlyCacheTest(req, res, next) {
import express from 'express'
import crypto from 'crypto'
const router = express.Router()
router.get('/*', function (req, res) {
// If X-CacheTest-Error is set, simulate the site being down (regardless of URL)
if (req.get('X-CacheTest-Error')) {
res.status(parseInt(req.get('X-CacheTest-Error'))).end()
return
}
const cacheControlModeParam = req.get('X-CacheTest-CCMode') ?? 'none'
const staleIfErrorParam = req.get('X-CacheTest-StaleIfError') ?? '300'
const staleWhileRevalidateParam = req.get('X-CacheTest-StaleWhileRevalidate') ?? '60'
const maxAgeParam = req.get('X-CacheTest-MaxAge') ?? '300'
const path = req.params[0]
const content = `<html>
<body>
<p>Timestamp: ${new Date()}</p>
</body>
</html>`
let status = 200
const surrogateControlValues = []
if (path.includes('max-age')) surrogateControlValues.push(`max-age=${maxAgeParam}`)
if (path.includes('must-revalidate')) surrogateControlValues.push('must-revalidate')
if (path.includes('no-cache')) surrogateControlValues.push('no-cache')
if (path.includes('no-store')) surrogateControlValues.push('no-store')
@@ -38,6 +53,12 @@ export default function fastlyCacheTest(req, res, next) {
res.removeHeader('Set-Cookie')
}
if (path.includes('etag')) {
res.set({
ETag: `"${crypto.createHash('md5').update(content).digest('hex')}"`,
})
}
if (path.includes('error500')) {
status = 500
} else if (path.includes('error502')) {
@@ -49,16 +70,31 @@ export default function fastlyCacheTest(req, res, next) {
}
if (surrogateControlValues.length > 0) {
res.set({
'surrogate-control': surrogateControlValues.join(', '),
})
switch (cacheControlModeParam) {
case 'none':
res.set({
'surrogate-control': surrogateControlValues.join(', '),
})
break
case 'both':
res.set({
'surrogate-control': surrogateControlValues.join(', '),
'cache-control': surrogateControlValues.join(', ').replace('max-age', 's-maxage'),
})
break
case 'only':
res.set({
'cache-control': surrogateControlValues.join(', ').replace('max-age', 's-maxage'),
})
break
}
}
res.status(status)
res.send(`<html>
<body>
<p>Timestamp: ${new Date()}</p>
</body>
</html>`)
res.send(content)
res.end()
}
})
export default router

View File

@@ -65,11 +65,14 @@ import fastHead from './fast-head.js'
import fastlyCacheTest from './fastly-cache-test.js'
import fastRootRedirect from './fast-root-redirect.js'
import trailingSlashes from './trailing-slashes.js'
import fastlyBehavior from './fastly-behavior.js'
const { DEPLOYMENT_ENV, NODE_ENV } = process.env
const isAzureDeployment = DEPLOYMENT_ENV === 'azure'
const isTest = NODE_ENV === 'test' || process.env.GITHUB_ACTIONS === 'true'
const ENABLE_FASTLY_TESTING = JSON.parse(process.env.ENABLE_FASTLY_TESTING || 'false')
// Catch unhandled promise rejections and passing them to Express's error handler
// https://medium.com/@Abazhenov/using-async-await-in-express-with-node-8-b8af872c0016
const asyncMiddleware = (fn) => (req, res, next) => {
@@ -218,6 +221,11 @@ export default function (app) {
app.use(csp) // Must come after helmet
app.use(cookieParser) // Must come before csrf
app.use(express.json()) // Must come before csrf
if (ENABLE_FASTLY_TESTING) {
app.use(fastlyBehavior) // FOR TESTING. Must come before csrf
}
app.use(csrf)
app.use(handleCsrfErrors) // Must come before regular handle-errors
@@ -296,10 +304,12 @@ export default function (app) {
app.use(asyncMiddleware(instrument(featuredLinks, './featured-links')))
app.use(asyncMiddleware(instrument(learningTrack, './learning-track')))
// The fastlyCacheTest middleware is intended to be used with Fastly to test caching behavior.
// This middleware will intercept ALL requests routed to it, so be careful if you need to
// make any changes to the following line:
app.use('/fastly-cache-test/*', fastlyCacheTest)
if (ENABLE_FASTLY_TESTING) {
// The fastlyCacheTest middleware is intended to be used with Fastly to test caching behavior.
// This middleware will intercept ALL requests routed to it, so be careful if you need to
// make any changes to the following line:
app.use('/fastly-cache-test', fastlyCacheTest)
}
// *** Headers for pages only ***
app.use(setFastlyCacheHeaders)

View File

@@ -42,4 +42,10 @@ module.exports = {
// https://nextjs.org/docs/api-reference/next.config.js/compression
compress: false,
// ETags break stale content serving from the CDN. When a response has
// an ETag, the CDN attempts to revalidate the content in the background.
// This causes problems with serving stale content, since upon revalidating
// the CDN marks the cached content as "fresh".
generateEtags: false,
}