mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-01-20 22:42:53 -05:00
Optimized link redirects handling
refs https://github.com/TryGhost/Toolbox/issues/515 - The link redirect handled was querying database on every single frontend request causing a significant amount of unnecessary traffic - The optimization is returning early if the incoming URL does not start with a common "r/" prefix
This commit is contained in:
parent
3f5e34f840
commit
32cd3b9433
3 changed files with 49 additions and 6 deletions
|
@ -23,7 +23,7 @@ module.exports = class LinkRedirectRepository {
|
|||
*/
|
||||
async save(linkRedirect) {
|
||||
const model = await this.#LinkRedirect.add({
|
||||
// Only store the parthname (no support for variable query strings)
|
||||
// Only store the pathname (no support for variable query strings)
|
||||
from: this.stripSubdirectoryFromPath(linkRedirect.from.pathname),
|
||||
to: linkRedirect.to.href
|
||||
}, {});
|
||||
|
|
|
@ -17,6 +17,9 @@ class LinkRedirectsService {
|
|||
/** @type URL */
|
||||
#baseURL;
|
||||
|
||||
/** @type String */
|
||||
#redirectURLPrefix = 'r/';
|
||||
|
||||
/**
|
||||
* @param {object} deps
|
||||
* @param {ILinkRedirectRepository} deps.linkRedirectRepository
|
||||
|
@ -43,7 +46,7 @@ class LinkRedirectsService {
|
|||
let url;
|
||||
while (!url || await this.#linkRedirectRepository.getByURL(url)) {
|
||||
const slug = crypto.randomBytes(4).toString('hex');
|
||||
url = new URL(`r/${slug}`, this.#baseURL);
|
||||
url = new URL(`${this.#redirectURLPrefix}${slug}`, this.#baseURL);
|
||||
}
|
||||
return url;
|
||||
}
|
||||
|
@ -82,6 +85,12 @@ class LinkRedirectsService {
|
|||
* @returns {Promise<void>}
|
||||
*/
|
||||
async handleRequest(req, res, next) {
|
||||
// skip handling if original url doesn't match the prefix
|
||||
const fullURLWithRedirectPrefix = `${this.#baseURL.pathname}${this.#redirectURLPrefix}`;
|
||||
if (!req.originalUrl.startsWith(fullURLWithRedirectPrefix)) {
|
||||
return next();
|
||||
}
|
||||
|
||||
const url = new URL(req.originalUrl, this.#baseURL);
|
||||
const link = await this.#linkRedirectRepository.getByURL(url);
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
const LinkRedirectsService = require('../lib/LinkRedirectsService');
|
||||
const {LinkRedirectsService} = require('../index');
|
||||
const assert = require('assert');
|
||||
const sinon = require('sinon');
|
||||
const crypto = require('crypto');
|
||||
|
@ -73,7 +73,7 @@ describe('LinkRedirectsService', function () {
|
|||
it('redirects if found', async function () {
|
||||
const linkRedirectRepository = {
|
||||
getByURL: (url) => {
|
||||
if (url.toString() === 'https://localhost:2368/a') {
|
||||
if (url.toString() === 'https://localhost:2368/r/a') {
|
||||
return Promise.resolve({
|
||||
to: new URL('https://localhost:2368/b')
|
||||
});
|
||||
|
@ -88,7 +88,7 @@ describe('LinkRedirectsService', function () {
|
|||
}
|
||||
});
|
||||
const req = {
|
||||
originalUrl: '/a'
|
||||
originalUrl: '/r/a'
|
||||
};
|
||||
const res = {
|
||||
redirect: sinon.fake(),
|
||||
|
@ -111,12 +111,46 @@ describe('LinkRedirectsService', function () {
|
|||
}
|
||||
});
|
||||
const req = {
|
||||
url: '/a'
|
||||
originalUrl: 'r/a'
|
||||
};
|
||||
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 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…
Add table
Reference in a new issue