diff --git a/ghost/core/core/server/api/endpoints/utils/serializers/output/utils/url.js b/ghost/core/core/server/api/endpoints/utils/serializers/output/utils/url.js index b99e6133408..f0170c2bae9 100644 --- a/ghost/core/core/server/api/endpoints/utils/serializers/output/utils/url.js +++ b/ghost/core/core/server/api/endpoints/utils/serializers/output/utils/url.js @@ -31,7 +31,9 @@ const forPost = (id, attrs, frame, type = 'posts') => { * Needs further discussion. */ if (!localUtils.isContentAPI(frame)) { - if (attrs.status !== 'published' && attrs.url.match(/\/404\//)) { + // Gate on status alone — the previous `/404/` URL check broke + // under `config.lazyRouting` (the lazy service returns `/{slug}/`). + if (attrs.status !== 'published') { if (attrs.posts_meta && attrs.posts_meta.email_only) { attrs.url = urlUtils.urlFor({ relativeUrl: urlUtils.urlJoin('/email', attrs.uuid, '/') diff --git a/ghost/core/test/unit/api/canary/utils/serializers/output/utils/url.test.js b/ghost/core/test/unit/api/canary/utils/serializers/output/utils/url.test.js index 27a3de18ca6..b2b4853ed70 100644 --- a/ghost/core/test/unit/api/canary/utils/serializers/output/utils/url.test.js +++ b/ghost/core/test/unit/api/canary/utils/serializers/output/utils/url.test.js @@ -90,6 +90,59 @@ describe('Unit: endpoints/utils/serializers/output/utils/url', function () { assert.equal(resource.id, 'post-id'); assert.equal(resource.type, 'posts'); }); + + describe('preview URL override for non-published posts', function () { + it('sets /email// for email-only sent posts regardless of the facade URL', function () { + getUrlForResourceStub.returns('http://localhost/the-slug/'); + + const post = { + id: 'post-id', + uuid: 'post-uuid', + slug: 'the-slug', + status: 'sent', + posts_meta: {email_only: true} + }; + + urlUtil.forPost(post.id, post, {options: {}}); + + assert.equal(post.url, 'urlFor'); + const [args] = urlUtils.urlFor.firstCall.args; + assert.equal(args.relativeUrl, '/email/post-uuid/'); + }); + + it('sets /p// for draft posts regardless of the facade URL', function () { + getUrlForResourceStub.returns('http://localhost/the-slug/'); + + const post = { + id: 'post-id', + uuid: 'post-uuid', + slug: 'the-slug', + status: 'draft' + }; + + urlUtil.forPost(post.id, post, {options: {}}); + + assert.equal(post.url, 'urlFor'); + const [args] = urlUtils.urlFor.firstCall.args; + assert.equal(args.relativeUrl, '/p/post-uuid/'); + }); + + it('keeps the facade URL for published posts', function () { + getUrlForResourceStub.returns('http://localhost/the-slug/'); + + const post = { + id: 'post-id', + uuid: 'post-uuid', + slug: 'the-slug', + status: 'published' + }; + + urlUtil.forPost(post.id, post, {options: {}}); + + assert.equal(post.url, 'http://localhost/the-slug/'); + sinon.assert.notCalled(urlUtils.urlFor); + }); + }); }); describe('forTag', function () {