diff --git a/server.js b/server.js index 6f5634f41..18f5cba1a 100644 --- a/server.js +++ b/server.js @@ -60,6 +60,7 @@ import basicAuthMiddleware from './src/middleware/basicAuth.js'; import whitelistMiddleware from './src/middleware/whitelist.js'; import multerMonkeyPatch from './src/middleware/multerMonkeyPatch.js'; import initRequestProxy from './src/request-proxy.js'; +import getCacheBusterMiddleware from './src/middleware/cacheBuster.js'; import { getVersion, getConfigValue, @@ -515,7 +516,7 @@ if (!disableCsrf) { // Static files // Host index page -app.get('/', (request, response) => { +app.get('/', getCacheBusterMiddleware(), (request, response) => { if (shouldRedirectToLogin(request)) { const query = request.url.split('?')[1]; const redirectUrl = query ? `/login?${query}` : '/login'; diff --git a/src/middleware/cacheBuster.js b/src/middleware/cacheBuster.js new file mode 100644 index 000000000..5c38d2da1 --- /dev/null +++ b/src/middleware/cacheBuster.js @@ -0,0 +1,28 @@ +import crypto from 'node:crypto'; +import { DEFAULT_USER } from '../constants.js'; + +/** + * Middleware to bust the browser cache for the current user. + * @returns {import('express').RequestHandler} + */ +export default function getCacheBusterMiddleware() { + /** + * @type {Set} Handles/User-Agents that have already been busted. + */ + const keys = new Set(); + + return (request, response, next) => { + const handle = request.user?.profile?.handle || DEFAULT_USER.handle; + const userAgent = request.headers['user-agent'] || ''; + const hash = crypto.createHash('sha256').update(userAgent).digest('hex'); + const key = `${handle}-${hash}`; + + if (keys.has(key)) { + return next(); + } + + keys.add(key); + response.setHeader('Clear-Site-Data', '"cache"'); + next(); + }; +}