Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added stale-if-error and fixed bug for frontend cache staleWhileRevaidate config (#21886) #21887

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
12 changes: 8 additions & 4 deletions ghost/core/core/frontend/web/middleware/frontend-caching.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ function calculateMemberTier(member, freeTier) {
const activeSubscriptions = member.subscriptions.filter(sub => sub.status === 'active');
if (activeSubscriptions.length === 0) {
return freeTier;
}
}
if (activeSubscriptions.length === 1) {
return activeSubscriptions[0].tier;
}
Expand Down Expand Up @@ -62,10 +62,14 @@ const getMiddleware = async (getFreeTier = async () => {
// The member is either on the free tier or has a single active subscription
// Cache the content based on the member's tier
res.set({'X-Member-Cache-Tier': memberTier.id});
return shared.middleware.cacheControl('public', {maxAge: config.get('caching:frontend:maxAge')})(req, res, next);
}

// CASE: Site is not private and the request is not made by a member — cache the content
return shared.middleware.cacheControl('public', {maxAge: config.get('caching:frontend:maxAge')})(req, res, next);
return shared.middleware.cacheControl('public', {
maxAge: config.get('caching:frontend:maxAge'),
staleWhileRevalidate: config.get('caching:frontend:staleWhileRevalidate'),
staleIfError: config.get('caching:frontend:staleIfError')
})(req, res, next);
}

return setFrontendCacheHeadersMiddleware;
Expand All @@ -74,4 +78,4 @@ const getMiddleware = async (getFreeTier = async () => {
module.exports = {
getMiddleware,
calculateMemberTier // exported for testing
};
};
6 changes: 4 additions & 2 deletions ghost/mw-cache-control/lib/mw-cache-control.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,15 @@ const isString = require('lodash/isString');
* @param {object} [options]
* @param {number} [options.maxAge] The max-age in seconds to use when profile is "public"
* @param {number} [options.staleWhileRevalidate] The stale-while-revalidate in seconds to use when profile is "public"
* @param {number} [options.staleIfError] The stale-if-error in seconds to use when profile is "public"
*/
const cacheControl = (profile, options = {maxAge: 0}) => {
const isOptionHasProperty = property => Object.prototype.hasOwnProperty.call(options, property);
const isOptionHasProperty = property => Object.prototype.hasOwnProperty.call(options, property) && options[property];
const publicOptions = [
'public',
`max-age=${options.maxAge}`,
isOptionHasProperty('staleWhileRevalidate') ? `stale-while-revalidate=${options.staleWhileRevalidate}` : ''
isOptionHasProperty('staleWhileRevalidate') ? `stale-while-revalidate=${options.staleWhileRevalidate}` : '',
isOptionHasProperty('staleIfError') ? `stale-if-error=${options.staleIfError}` : ''
];

const profiles = {
Expand Down
45 changes: 45 additions & 0 deletions ghost/mw-cache-control/test/cache-control.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,15 @@ describe('Cache-Control middleware', function () {
});
});

it('correctly sets the public profile headers with custom maxAge while both staleWhileRevalidate and staleIfError are undefined', function (done) {
cacheControl('public', {maxAge: 123456, staleWhileRevalidate: undefined, staleIfError: undefined})(null, res, function (a) {
should.not.exist(a);
res.set.calledOnce.should.be.true();
res.set.calledWith({'Cache-Control': 'public, max-age=123456'}).should.be.true();
done();
});
});

it('correctly sets the public profile headers with staleWhileRevalidate', function (done) {
cacheControl('public', {maxAge: 1, staleWhileRevalidate: 9})(null, res, function (a) {
should.not.exist(a);
Expand All @@ -43,6 +52,42 @@ describe('Cache-Control middleware', function () {
});
});

it('correctly sets the public profile headers with staleWhileRevalidate while staleIfError is undefined', function (done) {
cacheControl('public', {maxAge: 1, staleWhileRevalidate: 9, staleIfError: undefined})(null, res, function (a) {
should.not.exist(a);
res.set.calledOnce.should.be.true();
res.set.calledWith({'Cache-Control': 'public, max-age=1, stale-while-revalidate=9'}).should.be.true();
done();
});
});

it('correctly sets the public profile headers with staleIfError', function (done) {
cacheControl('public', {maxAge: 1, staleIfError: 10})(null, res, function (a) {
should.not.exist(a);
res.set.calledOnce.should.be.true();
res.set.calledWith({'Cache-Control': 'public, max-age=1, stale-if-error=10'}).should.be.true();
done();
});
});

it('correctly sets the public profile headers with staleIfError while staleWhileRevalidate is undefined', function (done) {
cacheControl('public', {maxAge: 1, staleIfError: 10, staleWhileRevalidate: undefined})(null, res, function (a) {
should.not.exist(a);
res.set.calledOnce.should.be.true();
res.set.calledWith({'Cache-Control': 'public, max-age=1, stale-if-error=10'}).should.be.true();
done();
});
});

it('correctly sets the public profile headers with both staleWhileRevalidate and staleIfError', function (done) {
cacheControl('public', {maxAge: 1, staleWhileRevalidate: 10, staleIfError: 11})(null, res, function (a) {
should.not.exist(a);
res.set.calledOnce.should.be.true();
res.set.calledWith({'Cache-Control': 'public, max-age=1, stale-while-revalidate=10, stale-if-error=11'}).should.be.true();
done();
});
});

it('correctly sets the private profile headers', function (done) {
cacheControl('private')(null, res, function (a) {
should.not.exist(a);
Expand Down
Loading