diff --git a/Readme.md b/Readme.md index 0155122..32aa416 100644 --- a/Readme.md +++ b/Readme.md @@ -106,13 +106,14 @@ fastify.listen(3000, (err) => { for a *cache-response-directive* as defined by RFC 2616. + `expiresIn` (Default: `undefined`): a value, in seconds, for the *max-age* the resource may be cached. When this is set, and `privacy` is not set to `no-cache`, -then `', max-age='` will be appended to the `cache-control` header. +then `', max-age='` will be appended to the `cache-control` header. + `cache` (Default: `abstract-cache.memclient`): an [abstract-cache][acache] protocol compliant cache object. Note: the plugin requires a cache instance to properly support the ETag mechanism. Therefore, if a falsy value is supplied the default will be used. + `cacheSegment` (Default: `'fastify-caching'`): segment identifier to use when communicating with the cache. ++ `serverExpiresIn` (Default: `undefined`): a value, in seconds, for the length of time the resource is fresh and may be held in a shared cache (e.g. a CDN). Shared caches will ignore max-age when this is specified, though browsers will continue to use max-age. Should be used with expiresIn, not in place of it. When this is set, and `privacy` is set to `public`, then `', s-maxage='` will be appended to the `cache-control` header. [acache]: https://www.npmjs.com/package/abstract-cache diff --git a/plugin.js b/plugin.js index ccd8619..2621ddc 100644 --- a/plugin.js +++ b/plugin.js @@ -8,6 +8,7 @@ const abstractCache = require('abstract-cache') const defaultOptions = { expiresIn: undefined, + serverExpiresIn: undefined, privacy: undefined, cache: undefined, cacheSegment: 'fastify-caching' @@ -69,6 +70,10 @@ function fastifyCachingPlugin (instance, options, next) { value = `${_options.privacy}, max-age=${_options.expiresIn}` } + if (_options.privacy !== undefined && _options.privacy.toLowerCase() === 'public' && _options.serverExpiresIn) { + value += `, s-maxage=${_options.serverExpiresIn}` + } + instance.addHook('onRequest', (req, res, next) => { res.header('Cache-control', value) next() diff --git a/test/headers.test.js b/test/headers.test.js index d8fa0b3..80b3d0b 100644 --- a/test/headers.test.js +++ b/test/headers.test.js @@ -108,6 +108,80 @@ test('sets private with max-age header', (t) => { }) }) +test('sets public with max-age and s-maxage header', (t) => { + t.plan(2) + const instance = fastify() + const opts = { + privacy: plugin.privacy.PUBLIC, + expiresIn: 300, + serverExpiresIn: 12345 + } + instance.register(plugin, opts) + instance.get('/', (req, reply) => { + reply.send({ hello: 'world' }) + }) + instance.listen(0, (err) => { + if (err) t.threw(err) + instance.server.unref() + const portNum = instance.server.address().port + const address = `http://127.0.0.1:${portNum}` + + http.get(address, (res) => { + t.ok(res.headers['cache-control']) + t.equal(res.headers['cache-control'], 'public, max-age=300, s-maxage=12345') + }).on('error', (err) => t.threw(err)) + }) +}) + +test('only sets max-age and ignores s-maxage with private header', (t) => { + t.plan(2) + const instance = fastify() + const opts = { + privacy: plugin.privacy.PRIVATE, + expiresIn: 300, + serverExpiresIn: 12345 + } + instance.register(plugin, opts) + instance.get('/', (req, reply) => { + reply.send({ hello: 'world' }) + }) + instance.listen(0, (err) => { + if (err) t.threw(err) + instance.server.unref() + const portNum = instance.server.address().port + const address = `http://127.0.0.1:${portNum}` + + http.get(address, (res) => { + t.ok(res.headers['cache-control']) + t.equal(res.headers['cache-control'], 'private, max-age=300') + }).on('error', (err) => t.threw(err)) + }) +}) + +test('s-maxage is optional with public header', (t) => { + t.plan(2) + const instance = fastify() + const opts = { + privacy: plugin.privacy.PUBLIC, + expiresIn: 300 + } + instance.register(plugin, opts) + instance.get('/', (req, reply) => { + reply.send({ hello: 'world' }) + }) + instance.listen(0, (err) => { + if (err) t.threw(err) + instance.server.unref() + const portNum = instance.server.address().port + const address = `http://127.0.0.1:${portNum}` + + http.get(address, (res) => { + t.ok(res.headers['cache-control']) + t.equal(res.headers['cache-control'], 'public, max-age=300') + }).on('error', (err) => t.threw(err)) + }) +}) + test('sets no-store with max-age header', (t) => { t.plan(2) const instance = fastify()