diff --git a/middleware/fastly-cache-test.js b/middleware/fastly-cache-test.js new file mode 100644 index 0000000000..8f460aa613 --- /dev/null +++ b/middleware/fastly-cache-test.js @@ -0,0 +1,64 @@ +// +// This middleware function is intended to be used for testing caching behavior with Fastly. +// It will intercept ALL URLs that are routed to it and respond with a simple HTML body +// containing a timestamp. +// The logic will detect certain values in the path and set the HTTP status and/or the +// Surrogate-Control header value. +// +// NOTE: This middleware is intended to be removed once testing is complete! +// +export default function fastlyCacheTest(req, res, next) { + // If CACHE_TEST_ERROR is set, simulate the site being down (regardless of URL) + if (process.env.CACHE_TEST_ERROR) { + res.status(parseInt(process.env.CACHE_TEST_ERROR)).end() + return + } + + const staleIfErrorParam = process.env.CACHE_TEST_STALE_IF_ERROR ?? '300' + const staleWhileRevalidateParam = process.env.CACHE_TEST_STALE_WHILE_REVALIDATE ?? '60' + + const path = req.params[0] + + let status = 200 + const surrogateControlValues = [] + + 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') + if (path.includes('private')) surrogateControlValues.push('private') + if (path.includes('proxy-revalidate')) surrogateControlValues.push('proxy-revalidate') + if (path.includes('public')) surrogateControlValues.push('public') + + if (path.includes('stale-if-error')) + surrogateControlValues.push(`stale-if-error=${staleIfErrorParam}`) + if (path.includes('stale-while-revalidate')) + surrogateControlValues.push(`stale-while-revalidate=${staleWhileRevalidateParam}`) + + if (path.includes('no-cookies')) { + res.removeHeader('Set-Cookie') + } + + if (path.includes('error500')) { + status = 500 + } else if (path.includes('error502')) { + status = 502 + } else if (path.includes('error503')) { + status = 503 + } else if (path.includes('error504')) { + status = 504 + } + + if (surrogateControlValues.length > 0) { + res.set({ + 'surrogate-control': surrogateControlValues.join(', '), + }) + } + + res.status(status) + res.send(` + +

Timestamp: ${new Date()}

+ +`) + res.end() +} diff --git a/middleware/index.js b/middleware/index.js index d2961cf4f6..2767f8d4bb 100644 --- a/middleware/index.js +++ b/middleware/index.js @@ -66,6 +66,8 @@ import setStaticAssetCaching from './static-asset-caching.js' import protect from './overload-protection.js' import fastHead from './fast-head.js' +import fastlyCacheTest from './fastly-cache-test.js' + const { DEPLOYMENT_ENV, NODE_ENV } = process.env const isDevelopment = NODE_ENV === 'development' const isAzureDeployment = DEPLOYMENT_ENV === 'azure' @@ -330,6 +332,11 @@ 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) + // *** Headers for pages only *** app.use(setFastlyCacheHeaders)