diff --git a/index.js b/index.js index dee5e0a..4f3dcb9 100644 --- a/index.js +++ b/index.js @@ -72,10 +72,10 @@ function fastifyCaching (instance, options, next) { instance.addHook('onSend', function cachingSetCacheControlHeader (_req, reply, _payload, next) { if (!reply.hasHeader('Cache-control')) { - // Only apply the caching value to successful (2xx) responses. + // Only apply the caching value to successful (2xx) and 304 Not Modified responses. // Error responses must not be cached, otherwise browsers may serve // a stale 4xx/5xx for the duration of max-age. - if (reply.statusCode >= 200 && reply.statusCode < 300) { + if ((reply.statusCode >= 200 && reply.statusCode < 300) || reply.statusCode === 304) { reply.header('Cache-control', value) } else { reply.header('Cache-control', 'no-store') diff --git a/test/headers.test.js b/test/headers.test.js index 965a119..3f70f3b 100644 --- a/test/headers.test.js +++ b/test/headers.test.js @@ -346,6 +346,66 @@ test('does not override a Cache-control header set upstream on error responses', t.assert.strictEqual(response.headers['cache-control'], 'private, max-age=10') }) +test('sets configured Cache-control header on 304 Not Modified responses', async (t) => { + t.plan(2) + + const opts = { + privacy: plugin.privacy.PRIVATE, + expiresIn: 300 + } + + const fastify = Fastify() + await fastify.register(plugin, opts) + + fastify.get('/', (_req, reply) => { + reply.code(304).send() + }) + + await fastify.ready() + + const response = await fastify.inject({ + method: 'GET', + path: '/' + }) + t.assert.strictEqual(response.statusCode, 304) + t.assert.strictEqual(response.headers['cache-control'], 'private, max-age=300') +}) + +test('sets configured Cache-control header on conditional 304 etag hit responses', async (t) => { + t.plan(4) + + const opts = { + privacy: plugin.privacy.PUBLIC, + expiresIn: 300 + } + + const fastify = Fastify() + await fastify.register(plugin, opts) + + fastify.get('/', (_req, reply) => { + reply.etag('123456').send({ hello: 'world' }) + }) + + await fastify.ready() + + const first = await fastify.inject({ + method: 'GET', + path: '/' + }) + t.assert.strictEqual(first.statusCode, 200) + t.assert.strictEqual(first.headers['cache-control'], 'public, max-age=300') + + const second = await fastify.inject({ + method: 'GET', + path: '/', + headers: { + 'if-none-match': '123456' + } + }) + t.assert.strictEqual(second.statusCode, 304) + t.assert.strictEqual(second.headers['cache-control'], 'public, max-age=300') +}) + test('sets the expires header', async (t) => { t.plan(2)