🐛 Fixed frontend routing prioritizing collections over built in routes (#20765)
ref https://linear.app/tryghost/issue/ONC-242/frontend-routing-prioritizes-collections-over-taxonomies - Under a fairly specific edge case with a collection route that conflicts with a default, built-in route ("taxonomy" — like tags, authors, etc), the frontend routing would prioritize the collection over the taxonomy. - For example, with the following in a custom `routes.yaml`: ``` collections: /: permalink: /{primary_tag}/{slug}/ template: index ``` If a post exists with the same slug as its primary tag's slug, the frontend routing would redirect the `/tag/{slug}/` route to the post in the collection, rather than serving the tag itself. - This commit changes that, so if a collection's route conflicts with e.g. a `/tag/{slug}/` default route, Ghost will still return the built in route, rather than the collection.
This commit is contained in:
parent
f08e4d4728
commit
c0471f0c28
@ -126,6 +126,13 @@ class RouterManager {
|
||||
this.registry.setRouter(staticRoutesRouter.identifier, staticRoutesRouter);
|
||||
});
|
||||
|
||||
_.each(routerSettings.taxonomies, (value, key) => {
|
||||
const taxonomyRouter = new TaxonomyRouter(key, value, RESOURCE_CONFIG, this.routerCreated.bind(this));
|
||||
this.siteRouter.mountRouter(taxonomyRouter.router());
|
||||
|
||||
this.registry.setRouter(taxonomyRouter.identifier, taxonomyRouter);
|
||||
});
|
||||
|
||||
_.each(routerSettings.collections, (value, key) => {
|
||||
const collectionRouter = new CollectionRouter(key, value, RESOURCE_CONFIG, this.routerCreated.bind(this));
|
||||
this.siteRouter.mountRouter(collectionRouter.router());
|
||||
@ -137,13 +144,6 @@ class RouterManager {
|
||||
|
||||
this.registry.setRouter('staticPagesRouter', staticPagesRouter);
|
||||
|
||||
_.each(routerSettings.taxonomies, (value, key) => {
|
||||
const taxonomyRouter = new TaxonomyRouter(key, value, RESOURCE_CONFIG, this.routerCreated.bind(this));
|
||||
this.siteRouter.mountRouter(taxonomyRouter.router());
|
||||
|
||||
this.registry.setRouter(taxonomyRouter.identifier, taxonomyRouter);
|
||||
});
|
||||
|
||||
const appRouter = new ParentRouter('AppsRouter');
|
||||
this.siteRouter.mountRouter(appRouter.router());
|
||||
|
||||
|
@ -80,3 +80,36 @@ describe('Custom Frontend routing', function () {
|
||||
.expect(assertCorrectFrontendHeaders);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Custom frontend routing - edge cases', function () {
|
||||
let request;
|
||||
|
||||
before(async function () {
|
||||
const routesFilePath = path.join(configUtils.config.get('paths:appRoot'), 'test/utils/fixtures/settings/edgecaseroutes.yaml');
|
||||
await configUtils.restore();
|
||||
await testUtils.stopGhost();
|
||||
|
||||
await testUtils.startGhost({
|
||||
forceStart: true,
|
||||
routesFilePath,
|
||||
subdir: false
|
||||
});
|
||||
|
||||
request = supertest.agent(configUtils.config.get('url'));
|
||||
});
|
||||
|
||||
after(async function () {
|
||||
await testUtils.stopGhost();
|
||||
});
|
||||
|
||||
it('should prioritize taxonomies over collections', async function () {
|
||||
// Create a tag and a post with the same slug
|
||||
const slug = 'cheese';
|
||||
await testUtils.createTag({tag: {slug}});
|
||||
await testUtils.createPost({post: {tags: [{slug}], slug}});
|
||||
|
||||
// Test that the tag route takes precedence
|
||||
await request.get(`/tag/${slug}/`)
|
||||
.expect(200);
|
||||
});
|
||||
});
|
||||
|
10
ghost/core/test/utils/fixtures/settings/edgecaseroutes.yaml
Normal file
10
ghost/core/test/utils/fixtures/settings/edgecaseroutes.yaml
Normal file
@ -0,0 +1,10 @@
|
||||
routes:
|
||||
|
||||
collections:
|
||||
/:
|
||||
permalink: /{primary_tag}/{slug}/
|
||||
template: index
|
||||
|
||||
taxonomies:
|
||||
tag: /tag/{slug}/
|
||||
author: /author/{slug}/
|
@ -79,6 +79,12 @@ const createPost = function createPost(options) {
|
||||
return models.Post.add(post, context.internal);
|
||||
};
|
||||
|
||||
const createTag = function createTag(options) {
|
||||
const tag = DataGenerator.forKnex.createTag(options.tag);
|
||||
|
||||
return models.Tag.add(tag, context.internal);
|
||||
};
|
||||
|
||||
const createEmail = function createEmail(options) {
|
||||
const email = DataGenerator.forKnex.createEmail(options.email);
|
||||
return models.Email.add(email, context.internal);
|
||||
@ -103,6 +109,7 @@ module.exports = {
|
||||
setup: setup,
|
||||
createUser: createUser,
|
||||
createPost: createPost,
|
||||
createTag: createTag,
|
||||
createEmailedPost,
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user