diff --git a/ghost/api-framework/lib/pipeline.js b/ghost/api-framework/lib/pipeline.js index 8d4a4b1e15..bf60b5d03b 100644 --- a/ghost/api-framework/lib/pipeline.js +++ b/ghost/api-framework/lib/pipeline.js @@ -160,6 +160,8 @@ const STAGES = { } }; +const controllerMap = new Map(); + /** * @description The pipeline runs the request through all stages (validation, serialisation, permissions). * @@ -180,12 +182,16 @@ const STAGES = { * @return {Object} */ const pipeline = (apiController, apiUtils, apiType) => { + if (controllerMap.has(apiController)) { + return controllerMap.get(apiController); + } + const keys = Object.keys(apiController); const docName = apiController.docName; // CASE: api controllers are objects with configuration. // We have to ensure that we expose a functional interface e.g. `api.posts.add` has to be available. - return keys.reduce((obj, method) => { + const result = keys.reduce((obj, method) => { const apiImpl = _.cloneDeep(apiController)[method]; Object.freeze(apiImpl.headers); @@ -267,6 +273,10 @@ const pipeline = (apiController, apiUtils, apiType) => { Object.assign(obj[method], apiImpl); return obj; }, {}); + + controllerMap.set(apiController, result); + + return result; }; module.exports = pipeline; diff --git a/ghost/core/test/regression/mock-express-style/api-vs-frontend.test.js b/ghost/core/test/regression/mock-express-style/api-vs-frontend.test.js index c6685ed1cb..5f8b56451f 100644 --- a/ghost/core/test/regression/mock-express-style/api-vs-frontend.test.js +++ b/ghost/core/test/regression/mock-express-style/api-vs-frontend.test.js @@ -33,8 +33,8 @@ describe('Frontend behavior tests', function () { beforeEach(function () { sinon.stub(themeEngine.getActive(), 'config').withArgs('posts_per_page').returns(2); - const postsAPI = require('../../../core/server/api/endpoints/posts-public'); - postSpy = sinon.spy(postsAPI.browse, 'query'); + const postsAPI = require('../../../core/server/api/endpoints').postsPublic; + postSpy = sinon.spy(postsAPI, 'browse'); }); afterEach(function () { @@ -143,22 +143,20 @@ describe('Frontend behavior tests', function () { }); }); - it('serve tag', function () { + it('serve tag', async function () { const req = { method: 'GET', url: '/tag/bacon/', host: 'example.com' }; - return localUtils.mockExpress.invoke(app, req) - .then(function (response) { - response.statusCode.should.eql(200); - response.template.should.eql('tag'); + const response = await localUtils.mockExpress.invoke(app, req); + response.statusCode.should.eql(200); + response.template.should.eql('tag'); - postSpy.args[0][0].options.filter.should.eql('(tags:\'bacon\'+tags.visibility:public)+type:post'); - postSpy.args[0][0].options.page.should.eql(1); - postSpy.args[0][0].options.limit.should.eql(2); - }); + postSpy.args[0][0].filter.should.eql('tags:\'bacon\'+tags.visibility:public'); + postSpy.args[0][0].page.should.eql(1); + postSpy.args[0][0].limit.should.eql(2); }); it('serve tag rss', function () {