diff --git a/core/server/services/redirects/validation.js b/core/server/services/redirects/validation.js index 4975276935..98067da4f3 100644 --- a/core/server/services/redirects/validation.js +++ b/core/server/services/redirects/validation.js @@ -4,6 +4,7 @@ const errors = require('@tryghost/errors'); const messages = { redirectsWrongFormat: 'Incorrect redirects file format.', + invalidRedirectsFromRegex: 'Incorrect RegEx in redirects file.', redirectsHelp: 'https://ghost.org/docs/themes/routing/#redirects' }; /** @@ -26,6 +27,17 @@ const validate = (redirects) => { help: tpl(messages.redirectsHelp) }); } + + try { + // each 'from' property should be a valid RegExp string + new RegExp(redirect.from); + } catch (error) { + throw new errors.ValidationError({ + message: tpl(messages.invalidRedirectsFromRegex), + context: redirect, + help: tpl(messages.redirectsHelp) + }); + } }); }; diff --git a/core/server/web/shared/middlewares/custom-redirects.js b/core/server/web/shared/middlewares/custom-redirects.js index 866094ca3e..4679a7182f 100644 --- a/core/server/web/shared/middlewares/custom-redirects.js +++ b/core/server/web/shared/middlewares/custom-redirects.js @@ -96,11 +96,11 @@ _private.registerRoutes = (router, redirects) => { const loadRoutes = () => { try { + customRedirectsRouter = express.Router('redirects'); + const redirects = redirectsService.loadRedirectsFile(); redirectsService.validate(redirects); - customRedirectsRouter = express.Router('redirects'); - _private.registerRoutes(customRedirectsRouter, redirects); } catch (err) { if (errors.utils.isIgnitionError(err)) { diff --git a/test/unit/services/redirects/validation.test.js b/test/unit/services/redirects/validation.test.js new file mode 100644 index 0000000000..88e3b8222a --- /dev/null +++ b/test/unit/services/redirects/validation.test.js @@ -0,0 +1,44 @@ +const should = require('should'); + +const {validate} = require('../../../../core/server/services/redirects/validation'); + +describe('UNIT: custom redirects validation', function () { + it('passes validation for a valid redirects config', function () { + const config = [{ + permanent: true, + from: '/test-params', + to: '/result?q=abc' + }]; + + validate(config); + }); + + it('throws for an invalid redirects config format missing from parameter', function () { + const config = [{ + permanent: true, + to: '/' + }]; + + try { + validate(config); + should.fail('should have thrown'); + } catch (err) { + err.message.should.equal('Incorrect redirects file format.'); + } + }); + + it('throws for an invalid redirects config having invalid RegExp in from field', function () { + const config = [{ + permanent: true, + from: '/invalid_regex/(/size/[a-zA-Z0-9_-.]*/[a-zA-Z0-9_-.]*/[0-9]*/[0-9]*/)([a-zA-Z0-9_-.]*)', + to: '/' + }]; + + try { + validate(config); + should.fail('should have thrown'); + } catch (err) { + err.message.should.equal('Incorrect RegEx in redirects file.'); + } + }); +}); diff --git a/test/unit/web/shared/middleware/custom-redirects.test.js b/test/unit/web/shared/middleware/custom-redirects.test.js index 65d9a9bafa..00a3096462 100644 --- a/test/unit/web/shared/middleware/custom-redirects.test.js +++ b/test/unit/web/shared/middleware/custom-redirects.test.js @@ -2,10 +2,10 @@ const should = require('should'); const sinon = require('sinon'); const rewire = require('rewire'); const express = require('express'); +const supertest = require('supertest'); const customRedirects = rewire('../../../../../core/server/web/shared/middlewares/custom-redirects'); const registerRoutes = customRedirects.__get__('_private.registerRoutes'); -const supertest = require('supertest'); describe('UNIT: custom redirects', function () { let res;