diff --git a/core/server/web/shared/middleware/uncapitalise.js b/core/server/web/shared/middleware/uncapitalise.js index 9c8b644c25..70d0f56ba2 100644 --- a/core/server/web/shared/middleware/uncapitalise.js +++ b/core/server/web/shared/middleware/uncapitalise.js @@ -27,13 +27,13 @@ const uncapitalise = (req, res, next) => { let decodedURI; const isSignupOrReset = pathToTest.match(/^(.*\/ghost\/(signup|reset)\/)/i); - const isAPI = pathToTest.match(/^(.*\/ghost\/api\/(v[\d.]+|canary)\/.*?\/)/i); + const isAPI = pathToTest.match(/^(.*\/ghost\/api(\/(v[\d.]+|canary))?\/.*?\/)/i); if (isSignupOrReset) { pathToTest = isSignupOrReset[1]; } - // Do not lowercase anything after e.g. /api/v{X}/ to protect :key/:slug + // Do not lowercase anything after e.g. /ghost/api(/v{X})?/ to protect :key/:slug if (isAPI) { pathToTest = isAPI[1]; } diff --git a/test/unit/server/web/shared/middleware/uncapitalise.test.js b/test/unit/server/web/shared/middleware/uncapitalise.test.js index b82bbb4c2d..d3fdbe9b0e 100644 --- a/test/unit/server/web/shared/middleware/uncapitalise.test.js +++ b/test/unit/server/web/shared/middleware/uncapitalise.test.js @@ -127,10 +127,14 @@ describe('Middleware: uncapitalise', function () { }); describe('An API request', function () { - ['v0.1', 'canary', 'v10'].forEach((apiVersion) => { + ['v0.1', 'canary', 'v10', null].forEach((apiVersion) => { + const getApiPath = (version) => { + return version ? `/${version}` : ''; + }; + describe(`for ${apiVersion}`, function () { it('does nothing if there are no capitals', function (done) { - req.path = `/ghost/api/${apiVersion}/endpoint/`; + req.path = `/ghost/api${getApiPath(apiVersion)}/endpoint/`; uncapitalise(req, res, next); next.calledOnce.should.be.true(); @@ -138,32 +142,38 @@ describe('Middleware: uncapitalise', function () { }); it('version identifier is uppercase', function (done) { - req.path = `/ghost/api/${apiVersion.toUpperCase()}/endpoint/`; + // CASE: capitalizing "empty" string does not make sense + if (apiVersion === null) { + done(); + return; + } + + req.path = `/ghost/api${getApiPath(apiVersion).toUpperCase()}/endpoint/`; req.url = req.path; uncapitalise(req, res, next); next.called.should.be.false(); res.redirect.calledOnce.should.be.true(); - res.redirect.calledWith(301, `/ghost/api/${apiVersion}/endpoint/`).should.be.true(); + res.redirect.calledWith(301, `/ghost/api${getApiPath(apiVersion)}/endpoint/`).should.be.true(); done(); }); it('redirects to the lower case slug if there are capitals', function (done) { - req.path = `/ghost/api/${apiVersion}/ASDfJ/`; + req.path = `/ghost/api${getApiPath(apiVersion)}/ASDfJ/`; req.url = req.path; uncapitalise(req, res, next); next.called.should.be.false(); res.redirect.calledOnce.should.be.true(); - res.redirect.calledWith(301, `/ghost/api/${apiVersion}/asdfj/`).should.be.true(); + res.redirect.calledWith(301, `/ghost/api${getApiPath(apiVersion)}/asdfj/`).should.be.true(); done(); }); it('redirects to the lower case slug if there are capitals in req.baseUrl', function (done) { req.baseUrl = '/Blog'; - req.path = `/ghost/api/${apiVersion}/ASDfJ/`; + req.path = `/ghost/api${getApiPath(apiVersion)}/ASDfJ/`; req.url = req.path; req.originalUrl = req.baseUrl + req.path; @@ -171,27 +181,27 @@ describe('Middleware: uncapitalise', function () { next.called.should.be.false(); res.redirect.calledOnce.should.be.true(); - res.redirect.calledWith(301, `/blog/ghost/api/${apiVersion}/asdfj/`).should.be.true(); + res.redirect.calledWith(301, `/blog/ghost/api${getApiPath(apiVersion)}/asdfj/`).should.be.true(); done(); }); it('does not convert any capitals after the endpoint', function (done) { const query = '?filter=mAgic'; - req.path = `/Ghost/API/${apiVersion}/settings/is_private/`; + req.path = `/Ghost/API${getApiPath(apiVersion)}/settings/is_private/`; req.url = `${req.path}${query}`; uncapitalise(req, res, next); next.called.should.be.false(); res.redirect.calledOnce.should.be.true(); - res.redirect.calledWith(301, `/ghost/api/${apiVersion}/settings/is_private/${query}`).should.be.true(); + res.redirect.calledWith(301, `/ghost/api${getApiPath(apiVersion)}/settings/is_private/${query}`).should.be.true(); done(); }); it('does not convert any capitals after the endpoint with baseUrl', function (done) { const query = '?filter=mAgic'; req.baseUrl = '/Blog'; - req.path = `/ghost/api/${apiVersion}/mail/test@example.COM/`; + req.path = `/ghost/api${getApiPath(apiVersion)}/mail/test@example.COM/`; req.url = `${req.path}${query}`; req.originalUrl = `${req.baseUrl}${req.path}${query}`; @@ -199,7 +209,7 @@ describe('Middleware: uncapitalise', function () { next.called.should.be.false(); res.redirect.calledOnce.should.be.true(); - res.redirect.calledWith(301, `/blog/ghost/api/${apiVersion}/mail/test@example.COM/${query}`).should.be.true(); + res.redirect.calledWith(301, `/blog/ghost/api${getApiPath(apiVersion)}/mail/test@example.COM/${query}`).should.be.true(); done(); }); });