From 2927b1a123ab818d02e61e15717b55584f422302 Mon Sep 17 00:00:00 2001 From: Matus Kasak Date: Tue, 18 Aug 2026 10:12:22 +0200 Subject: [PATCH] TUL/fix(ssr): don't cache non-2XX responses (soft-404 on unknown pages) An unknown route or `/static/` page renders the 404 page correctly, but `saveToCache()` stored that rendered page in the bot/anonymous SSR cache without checking the status code. On the next request the cached copy was replayed via `res.send(cachedCopy)` (which does not restore the status), so a correct 404 turned into HTTP 200 - a soft-404. UNIVERSAL-016 (dspace-ui-tests notFoundPage.spec.ts, both "non-existent route" and "non-existent static page") therefore failed on tul with 200 for the well-known test URIs, while a fresh/cache-busted path still returned 404. Skip caching when the response status is not 2XX (add the `hasNotSucceeded` guard already used on dtq-dev/jcu). The 404 page is then never cached and can no longer be served as 200. Note: a redeploy/restart is still needed once to clear the stale 200 entries already sitting in the in-memory cache; this guard prevents them recurring. Refs dataquest-dev/dspace-customers#566 Co-Authored-By: Claude Opus 4.8 --- server.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/server.ts b/server.ts index 3e10677a8b1..6f61b8f20f9 100644 --- a/server.ts +++ b/server.ts @@ -443,6 +443,10 @@ function saveToCache(req, page: any) { const key = getCacheKey(req); // Avoid caching "/reload/[random]" paths (these are hard refreshes after logout) if (key.startsWith('/reload')) { return; } + // Avoid caching non-successful responses (status code different from 2XX). Without this, the + // rendered 404 not-found page gets stored in the cache and is later replayed via res.send() + // as HTTP 200 - turning a correct 404 into a soft-404. (matches dtq-dev cache behaviour) + if (hasNotSucceeded(req.res.statusCode)) { return; } // If bot cache is enabled, save it to that cache if it doesn't exist or is expired // (NOTE: has() will return false if page is expired in cache) @@ -459,6 +463,15 @@ function saveToCache(req, page: any) { } } +/** + * Check if status code is different from 2XX + * @param statusCode HTTP status code of the current response + */ +function hasNotSucceeded(statusCode) { + const rgx = new RegExp(/^20+/); + return !rgx.test(statusCode); +} + /** * Whether a user is authenticated or not */