diff --git a/README.md b/README.md index de88a38..dd9884a 100644 --- a/README.md +++ b/README.md @@ -246,6 +246,8 @@ routes to be cached from your public client, but NOT cached when from the admin is achieved by sending a `"x-apicache-bypass": true` header along with the requst from the admin. The presence of this header flag will bypass the cache, ensuring you aren't looking at stale data. +Additionally, you may want to bypass loading stale content for a request while still updating the cache with fresh content. To achieve this, include a `"x-apicache-bypass": true` header with the request. + ## Contributors Special thanks to all those that use this library and report issues, but especially to the following active users that have helped add to the core functionality! diff --git a/src/apicache.js b/src/apicache.js index 8601ba2..6585258 100644 --- a/src/apicache.js +++ b/src/apicache.js @@ -639,9 +639,11 @@ function ApiCache() { // attempt cache hit var redis = opt.redisClient var cached = !redis ? memCache.getValue(key) : null + // skip cache load when x-apicache-revalidate is present + var revalidate = req.headers['x-apicache-revalidate'] // send if cache hit from memory-cache - if (cached) { + if (!revalidate && cached) { var elapsed = new Date() - req.apicacheTimer debug('sending cached (memory-cache) version of', key, logDuration(elapsed)) @@ -650,7 +652,7 @@ function ApiCache() { } // send if cache hit from redis - if (redis && redis.connected) { + if (!revalidate && redis && redis.connected) { try { redis.hgetall(key, function(err, obj) { if (!err && obj && obj.response) { diff --git a/test/apicache_test.js b/test/apicache_test.js index c6c0dd8..8ee74f1 100644 --- a/test/apicache_test.js +++ b/test/apicache_test.js @@ -549,6 +549,31 @@ describe('.middleware {MIDDLEWARE}', function() { }) }) + it('revalidates cache when using header "x-apicache-revalidate"', function(done) { + var app = mockAPI.create('10 seconds') + + request(app) + .get('/api/movies') + .expect(200, movies) + .expect('Cache-Control', 'max-age=10') + .then(assertNumRequestsProcessed(app, 1)) + .then(function() { + setTimeout(function() { + return request(app) + .get('/api/movies') + .set('x-apicache-revalidate', true) + .expect(200, movies) + .expect('Cache-Control', 'max-age=10') + .then(function(res) { + expect(res.headers['apicache-store']).to.be.undefined + expect(res.headers['apicache-version']).to.be.undefined + expect(app.requestsProcessed).to.equal(2) + done() + }) + }, 500) + }) + }) + it('does not cache header in headerBlacklist', function() { var app = mockAPI.create('10 seconds', { headerBlacklist: ['x-blacklisted'] })