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鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

馃悰 Fixed redundant member data loading for static assets #20031

Merged
merged 14 commits into from May 20, 2024
Merged
18 changes: 10 additions & 8 deletions ghost/core/core/frontend/web/site.js
Expand Up @@ -121,9 +121,6 @@ module.exports = function setupSiteApp(routerConfig) {
// Serve site files using the storage adapter
siteApp.use(STATIC_FILES_URL_PREFIX, storage.getStorage('files').serve());

// Global handling for member session, ensures a member is logged in to the frontend
siteApp.use(membersService.middleware.loadMemberSession);

// /member/.well-known/* serves files (e.g. jwks.json) so it needs to be mounted before the prettyUrl mw to avoid trailing slashes
siteApp.use(
'/members/.well-known',
Expand All @@ -148,18 +145,23 @@ module.exports = function setupSiteApp(routerConfig) {

// Theme static assets/files
siteApp.use(mw.staticTheme());

// Serve robots.txt if not found in theme
siteApp.use(mw.servePublicFile('static', 'robots.txt', 'text/plain', config.get('caching:robotstxt:maxAge')));

debug('Static content done');

// site map - this should probably be refactored to be an internal app
sitemapHandler(siteApp);

// Global handling for member session, ensures a member is logged in to the frontend
siteApp.use(membersService.middleware.loadMemberSession);

// Theme middleware
// This should happen AFTER any shared assets are served, as it only changes things to do with templates
siteApp.use(themeMiddleware);
debug('Themes done');

// Serve robots.txt if not found in theme
siteApp.use(mw.servePublicFile('static', 'robots.txt', 'text/plain', config.get('caching:robotstxt:maxAge')));

// site map - this should probably be refactored to be an internal app
sitemapHandler(siteApp);
debug('Internal apps done');

// Add in all trailing slashes & remove uppercase
Expand Down
94 changes: 94 additions & 0 deletions ghost/core/test/e2e-frontend/middleware.test.js
@@ -0,0 +1,94 @@
const sinon = require('sinon');
const supertest = require('supertest');
const testUtils = require('../utils');
const configUtils = require('../utils/configUtils');
const membersService = require('../../core/server/services/members');

describe('Middleware Execution', function () {
let loadMemberSessionMiddlewareSpy;
let request;

before(async function () {
loadMemberSessionMiddlewareSpy = sinon.spy(membersService.middleware, 'loadMemberSession');

// Ensure we do a forced start so that spy is in place when the server starts
await testUtils.startGhost({forceStart: true});

request = supertest.agent(configUtils.config.get('url'));
});

after(async function () {
sinon.restore();

await testUtils.stopGhost();
});

afterEach(function () {
loadMemberSessionMiddlewareSpy.resetHistory();
});

describe('Loading a member session', function () {
describe('Page with member content', function () {
it('should load member session on home route', async function () {
await request.get('/');
sinon.assert.calledOnce(loadMemberSessionMiddlewareSpy);
});

it('should load member session on post route', async function () {
await request.get('/welcome/');
sinon.assert.calledOnce(loadMemberSessionMiddlewareSpy);
});
});

describe('Sitemap', function () {
it('should not load member session on sitemap route', async function () {
await request.get('/sitemap.xml');
sinon.assert.notCalled(loadMemberSessionMiddlewareSpy);
});

it('should not load member session on sitemap-pages route', async function () {
await request.get('/sitemap-pages.xml');
sinon.assert.notCalled(loadMemberSessionMiddlewareSpy);
});

it('should not load member session on sitemap-posts route', async function () {
await request.get('/sitemap-posts.xml');
sinon.assert.notCalled(loadMemberSessionMiddlewareSpy);
});

it('should not load member session on sitemap-tags route', async function () {
await request.get('/sitemap-tags.xml');
sinon.assert.notCalled(loadMemberSessionMiddlewareSpy);
});

it('should not load member session on sitemap-authors route', async function () {
await request.get('/sitemap-authors.xml');
sinon.assert.notCalled(loadMemberSessionMiddlewareSpy);
});
});

describe('Recommendations', function () {
it('should not load member session on recommendations route', async function () {
await request.get('/.well-known/recommendations.json');
sinon.assert.notCalled(loadMemberSessionMiddlewareSpy);
});
});

describe('Static assets', function () {
it('should not load member session on fonts route', async function () {
await request.get('/assets/fonts/inter-roman.woff2');
sinon.assert.notCalled(loadMemberSessionMiddlewareSpy);
});

it('should not load member session on source.js route', async function () {
await request.get('/assets/built/source.js');
sinon.assert.notCalled(loadMemberSessionMiddlewareSpy);
});

it('should not load member session on screen.css route', async function () {
await request.get('/assets/built/screen.css');
sinon.assert.notCalled(loadMemberSessionMiddlewareSpy);
});
});
});
});