From c7cbdfc5a4e21b5640b96345818f54694b85516b Mon Sep 17 00:00:00 2001 From: Marc-Antoine Fernandes Date: Thu, 16 Nov 2023 12:47:32 +0100 Subject: [PATCH] Better support stale-while-revalidate option --- index.js | 18 +++++++---- test/okhttptest.js | 75 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 87 insertions(+), 6 deletions(-) diff --git a/index.js b/index.js index 31fba48..8ef809f 100644 --- a/index.js +++ b/index.js @@ -36,7 +36,7 @@ const understoodStatuses = new Set([ const errorStatusCodes = new Set([ 500, 502, - 503, + 503, 504, ]); @@ -248,11 +248,17 @@ module.exports = class CachePolicy { // the stored response is either: // fresh, or allowed to be served stale if (this.stale()) { - const allowsStale = - requestCC['max-stale'] && - !this._rescc['must-revalidate'] && - (true === requestCC['max-stale'] || - requestCC['max-stale'] > this.age() - this.maxAge()); + let allowsStale = false; + if (requestCC['max-stale'] && !this._rescc['must-revalidate']) { + if (requestCC['max-stale'] === true || requestCC['max-stale'] > this.age() - this.maxAge()) { + allowsStale = true; + } + // Allow stale-while-revalidate queries to be served stale + // even if must-revalidate is set as the revalidation should be happening in the background + } else if (this.useStaleWhileRevalidate()) { + allowsStale = true; + } + if (!allowsStale) { return false; } diff --git a/test/okhttptest.js b/test/okhttptest.js index 7b4b215..075f0ef 100644 --- a/test/okhttptest.js +++ b/test/okhttptest.js @@ -210,6 +210,81 @@ describe('okhttp tests', function() { assert.equal(cache.timeToLive(), 260000); }); + it('stale-while-revalidate satisfies when stale', function() { + const cache = new CachePolicy( + { headers: {} }, + { + headers: { + age: 120, + 'cache-control': 'max-age=60, stale-while-revalidate=200', + }, + }, + { shared: false } + ); + + assert(cache.stale()); + assert(cache.useStaleWhileRevalidate()); + assert(cache.satisfiesWithoutRevalidation({ headers: {} })); + }); + + it('stale-while-revalidate satisfies when stale and must-revalidate', function() { + const cache = new CachePolicy( + { headers: {} }, + { + headers: { + age: 120, + 'cache-control': 'max-age=60, stale-while-revalidate=200, must-revalidate', + }, + }, + { shared: false } + ); + + assert(cache.stale()); + assert(cache.satisfiesWithoutRevalidation({ headers: {} })); + }); + + it('stale-while-revalidate work with max-stale', function() { + const cache = new CachePolicy( + { headers: {} }, + { + headers: { + age: 100, + 'cache-control': 'max-age=60, stale-while-revalidate=200', + }, + }, + { shared: false } + ); + + assert(cache.stale()); + assert(cache.satisfiesWithoutRevalidation({ + headers: { + 'cache-control': 'max-stale', + } + })); + assert(!cache.satisfiesWithoutRevalidation({ + headers: { + 'cache-control': 'max-stale=40', + } + })); + }); + + it('stale-while-revalidate not satisfies when stale and expired', function() { + const cache = new CachePolicy( + { headers: {} }, + { + headers: { + age: 260, + 'cache-control': 'max-age=60, stale-while-revalidate=200', + }, + }, + { shared: false } + ); + + assert(cache.stale()); + assert(!cache.useStaleWhileRevalidate()); + assert(!cache.satisfiesWithoutRevalidation({ headers: {} })); + }); + it('max age preferred over lower shared max age', function() { const cache = new CachePolicy( { headers: {} },