diff --git a/core/server/middleware/url-redirects.js b/core/server/middleware/url-redirects.js index f5c405ba62..a775411b4c 100644 --- a/core/server/middleware/url-redirects.js +++ b/core/server/middleware/url-redirects.js @@ -22,6 +22,8 @@ _private.redirectUrl = function redirectUrl(options) { _private.getAdminRedirectUrl = function getAdminRedirectUrl(options) { var blogHostWithProtocol = utils.url.urlFor('home', true), adminHostWithProtocol = utils.url.urlFor('admin', true), + adminHostWithoutProtocol = adminHostWithProtocol.replace(/(^\w+:|^)\/\//, ''), + blogHostWithoutProtocol = blogHostWithProtocol.replace(/(^\w+:|^)\/\//, ''), requestedHost = options.requestedHost, requestedUrl = options.requestedUrl, queryParameters = options.queryParameters, @@ -30,7 +32,11 @@ _private.getAdminRedirectUrl = function getAdminRedirectUrl(options) { debug('getAdminRedirectUrl', requestedHost, requestedUrl, adminHostWithProtocol); // CASE: we only redirect the admin access if `admin.url` is configured - if (adminHostWithProtocol !== utils.url.urlJoin(blogHostWithProtocol, 'ghost/')) { + // If url and admin.url are not equal AND the requested host does not match, redirect. + // The first condition is the most important, because it ensures that you have a custom admin url configured, + // because we don't force an admin redirect if you have a custom url configured, but no admin url. + if (adminHostWithoutProtocol !== utils.url.urlJoin(blogHostWithoutProtocol, 'ghost/') && + adminHostWithoutProtocol !== utils.url.urlJoin(requestedHost, utils.url.getSubdir(), 'ghost/')) { debug('redirect because admin host does not match'); return _private.redirectUrl({ diff --git a/core/test/unit/middleware/url-redirects_spec.js b/core/test/unit/middleware/url-redirects_spec.js index f93931f0c2..d0a9fcf2a2 100644 --- a/core/test/unit/middleware/url-redirects_spec.js +++ b/core/test/unit/middleware/url-redirects_spec.js @@ -214,6 +214,11 @@ describe('UNIT: url redirects', function () { urlRedirects(req, res, next); next.called.should.be.false(); res.redirect.calledWith(301, 'https://admin.default.com:2368/blog/ghost').should.be.true(); + + req.secure = true; + host = 'admin.default.com:2368'; + urlRedirects(req, res, next); + next.called.should.be.true(); done(); }); @@ -238,4 +243,62 @@ describe('UNIT: url redirects', function () { res.redirect.calledWith(301, 'https://admin.default.com:2368/ghost?test=true').should.be.true(); done(); }); + + it('[redirect] same url and admin url, but different protocol.', function (done) { + configUtils.set({ + url: 'http://default.com:2368', + admin: { + url: 'https://default.com:2368' + } + }); + + host = 'default.com:2368'; + res.isAdmin = true; + + req.originalUrl = '/ghost'; + urlRedirects(req, res, next); + next.called.should.be.false(); + res.redirect.calledWith(301, 'https://default.com:2368/ghost').should.be.true(); + + req.secure = true; + urlRedirects(req, res, next); + next.called.should.be.true(); + done(); + }); + + it('[no redirect] different url and admin url, but different protocol.', function (done) { + configUtils.set({ + url: 'http://blog.ghost.org', + admin: { + url: 'http://something.com' + } + }); + + host = 'something.com'; + res.isAdmin = true; + req.secure = false; + + req.originalUrl = '/ghost'; + urlRedirects(req, res, next); + next.called.should.be.true(); + done(); + }); + + it('[no redirect] different url and admin url, but different protocol.', function (done) { + configUtils.set({ + url: 'http://blog.ghost.org', + admin: { + url: 'http://something.com' + } + }); + + host = 'something.com'; + res.isAdmin = true; + req.secure = true; + + req.originalUrl = '/ghost'; + urlRedirects(req, res, next); + next.called.should.be.true(); + done(); + }); });