Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions api/controllers/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ exports.publicGet = async function (args, res) {

if (!doc) {
defaultLog.error('GET /api/config: no Config document — has the seed migration run?');
// app.js stamps max-age=60 on every unauthenticated GET before routing. A good config
// should be cacheable; a failure must not be, or a brief outage sticks in rproxy and in
// every browser for a minute after the database comes back.
res.setHeader('Cache-Control', 'no-store');
return Actions.sendResponse(res, 404, { message: 'Configuration not found' });
}

Expand All @@ -57,6 +61,7 @@ exports.publicGet = async function (args, res) {
return Actions.sendResponse(res, 200, payload);
} catch (err) {
defaultLog.error('GET /api/config failed:', err);
res.setHeader('Cache-Control', 'no-store');
return Actions.sendResponse(res, 500, { message: 'Could not read configuration' });
}
};
22 changes: 22 additions & 0 deletions test/controllers/config.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ function fakeRes() {
return {
statusCode: null,
body: null,
headers: {},
setHeader(name, value) { this.headers[name] = value; },
status(code) { this.statusCode = code; return this; },
json(payload) { this.body = payload; return this; }
};
Expand Down Expand Up @@ -108,6 +110,17 @@ describe('Config Controller', () => {
expect(res.statusCode).to.equal(404);
});

it('does not let the 404 be cached', async () => {
// app.js has already stamped max-age=60 on this unauthenticated GET by the time the
// controller runs — a missing config must not stick in rproxy for a minute.
stubConfigModel(null);
const res = fakeRes();

await configController.publicGet({}, res);

expect(res.headers['Cache-Control']).to.equal('no-store');
});

it('500s when the read fails', async () => {
stubConfigModel(null, new Error('connection lost'));
const res = fakeRes();
Expand All @@ -117,4 +130,13 @@ describe('Config Controller', () => {
expect(res.statusCode).to.equal(500);
expect(res.body).to.not.have.property('stack');
});

it('does not let the 500 be cached', async () => {
stubConfigModel(null, new Error('connection lost'));
const res = fakeRes();

await configController.publicGet({}, res);

expect(res.headers['Cache-Control']).to.equal('no-store');
});
});