Skip to content

fix: stop caching a failed /api/config - #839

Merged
danieltruong merged 1 commit into
developfrom
fix/config-no-store-on-failure
Aug 14, 2026
Merged

fix: stop caching a failed /api/config#839
danieltruong merged 1 commit into
developfrom
fix/config-no-store-on-failure

Conversation

@danieltruong

@danieltruong danieltruong commented Aug 14, 2026

Copy link
Copy Markdown
Collaborator

What

app.js:75-80 stamps Cache-Control: max-age=60 on every unauthenticated GET before routing, so it lands on /api/config's 404 and 500 as well as its 200. The controller set no header of its own. Both error paths now set no-store; the 200 stays cacheable.

Why this matters, and why now

Today this is theoretical: eao-nginx's location = /api/config is an exact match and beats the /api proxy, so this controller is unreachable and nothing here changes behaviour on deploy.

It stops being theoretical at cutover. Once eagle-api answers the path, a three-second Mongo blip returns one 500 — and that 500 is then cached at rproxy and in every browser for a full minute after the database has recovered. The cache converts a transient into a minute-long outage for anyone who loads a page during it.

This is a precondition for the frontend work that reacts to a failed config fetch (bcgov/eagle-admin#921), which is why it lands ahead of the cutover rather than with it.

Mechanism

Actions.sendResponse (api/helpers/actions.js:59-61) is res.status().json() and overrides no headers, so a res.setHeader immediately before it wins over the app-level default.

Not in this PR

The same pre-routing stamp still marks every other public 404 and 500 cacheable for a minute. The real fix is to downgrade any status ≥ 400 to no-store — an on-headers hook or a res.writeHead wrapper — which changes behaviour on every public route and wants its own ticket and its own soak. Raised in review; deliberately not folded in here.

Also still to come, in the eao-nginx cutover commit rather than this one: proxy_cache_valid 200 60s and proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504 on the /api block. The repo currently has proxy_cache globalcache with neither directive anywhere, so a good config does not keep serving through an eagle-api blip.

Tests

Two cases added to test/controllers/config.test.js asserting Cache-Control: no-store on the 404 and the 500. The existing fakeRes() had no setHeader, so it gained one — without it the pre-existing 404 and 500 tests would have thrown.

Full suite: 638 passing.

app.js stamps max-age=60 on every unauthenticated GET before routing, so it
lands on this route's 404 and 500 too. Once the nginx exact-match block is
removed and eagle-api actually answers the path, a few seconds of Mongo
trouble would be cached at rproxy and in every browser for a full minute
after the database recovers. A good config stays cacheable; a failure does not.
@danieltruong
danieltruong merged commit 96dd5a6 into develop Aug 14, 2026
4 checks passed
@danieltruong
danieltruong deleted the fix/config-no-store-on-failure branch August 14, 2026 17:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant