Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
5 changes: 5 additions & 0 deletions ghost/core/core/frontend/web/routers/link-redirects.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
const linkRedirects = require('../../../server/services/link-redirection');

module.exports = function handleRedirects(siteApp) {
siteApp.get(linkRedirects.service.relativeRedirectPrefix() + '*', linkRedirects.service.handleRequest);
};
4 changes: 2 additions & 2 deletions ghost/core/core/frontend/web/site.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const themeMiddleware = themeEngine.middleware;
const membersService = require('../../server/services/members');
const offersService = require('../../server/services/offers');
const customRedirects = require('../../server/services/custom-redirects');
const linkRedirects = require('../../server/services/link-redirection');
const linkRedirectsHandler = require('./routers/link-redirects');
const siteRoutes = require('./routes');
const shared = require('../../server/web/shared');
const errorHandler = require('@tryghost/mw-error-handler');
Expand Down Expand Up @@ -51,7 +51,7 @@ module.exports = function setupSiteApp(routerConfig) {

siteApp.use(offersService.middleware);

siteApp.use(linkRedirects.service.handleRequest);
linkRedirectsHandler(siteApp);

// you can extend Ghost with a custom redirects file
// see https://github.com/TryGhost/Ghost/issues/7707
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,15 @@ class LinkRedirectsService {
return link;
}

/**
* Returns the relative path prefix without subdirectory (e.g., /r/)
* Used for Express route matching where subdirectory is already stripped
* @return {string}
**/
relativeRedirectPrefix() {
return '/' + this.#redirectURLPrefix;
}

/**
* @param {import('express').Request} req
* @param {import('express').Response} res
Expand All @@ -86,18 +95,6 @@ class LinkRedirectsService {
*/
async handleRequest(req, res, next) {
try {
// skip handling if original url doesn't match the prefix
const fullURLWithRedirectPrefix = `${this.#baseURL.pathname}${this.#redirectURLPrefix}`;
// @NOTE: below is equivalent to doing:
// router.get('/r/'), (req, res) ...
// To make it cleaner we should rework it to:
// linkRedirects.service.handleRequest(router);
// and mount routes on top like for example sitemapHandler does
// Cleanup issue: https://github.com/TryGhost/Toolbox/issues/516
if (!req.originalUrl.startsWith(fullURLWithRedirectPrefix)) {
return next();
}

const url = new URL(req.originalUrl, this.#baseURL);
const link = await this.#linkRedirectRepository.getByURL(url);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,28 @@ describe('LinkRedirectsService', function () {
});
});

describe('relativeRedirectPrefix', function () {
it('returns relative path without subdirectory for Express routing', function () {
const instance = new LinkRedirectsService({
linkRedirectRepository: {},
config: {
baseURL: new URL('https://localhost:2368/blog/')
}
});
assert.equal(instance.relativeRedirectPrefix(), '/r/');
});

it('returns same value as redirectPrefix when no subdirectory configured', function () {
const instance = new LinkRedirectsService({
linkRedirectRepository: {},
config: {
baseURL: new URL('https://localhost:2368/')
}
});
assert.equal(instance.relativeRedirectPrefix(), '/r/');
});
});

describe('handleRequest', function () {
it('redirects if found', async function () {
const linkRedirectRepository = {
Expand Down Expand Up @@ -115,38 +137,5 @@ describe('LinkRedirectsService', function () {
assert.equal(next.callCount, 1);
});

it('does not redirect if url does not contain a redirect prefix on site with no subdir', async function () {
const instance = new LinkRedirectsService({
config: {
baseURL: new URL('https://localhost:2368/')
}
});
const req = {
originalUrl: 'no_r/prefix'
};
const res = {};
const next = sinon.fake();

await instance.handleRequest(req, res, next);

assert.equal(next.callCount, 1);
});

it('does not redirect if url does not contain a redirect prefix on site with subdir', async function () {
const instance = new LinkRedirectsService({
config: {
baseURL: new URL('https://localhost:2368/blog')
}
});
const req = {
originalUrl: 'blog/no_r/prefix'
};
const res = {};
const next = sinon.fake();

await instance.handleRequest(req, res, next);

assert.equal(next.callCount, 1);
});
});
});
Loading