diff --git a/core/server/services/url/utils.js b/core/server/services/url/utils.js index f7319ac5fd..dec5617fb8 100644 --- a/core/server/services/url/utils.js +++ b/core/server/services/url/utils.js @@ -6,7 +6,7 @@ const moment = require('moment-timezone'), cheerio = require('cheerio'), config = require('../../config'), settingsCache = require('../settings/cache'), - BASE_API_PATH = '/ghost/api/', + BASE_API_PATH = '/ghost/api', STATIC_IMAGE_URL_PREFIX = 'content/images'; /** @@ -16,6 +16,17 @@ const moment = require('moment-timezone'), * @return {string} API Path for version */ function getApiPath(options) { + const versionPath = getVersionPath(options); + return `${BASE_API_PATH}${versionPath}`; +} + +/** + * Returns path containing only the path for the specific version asked or deprecated by default + * @param {Object} options {version} for which to get the path(stable, actice, deprecated), + * {type} admin|content: defaults to {version: deprecated, type: content} + * @return {string} API version path + */ +function getVersionPath(options) { const apiVersions = config.get('api:versions'); let requestedVersion = options.version || 'deprecated'; let requestedVersionType = options.type || 'content'; @@ -24,7 +35,7 @@ function getApiPath(options) { versionData = apiVersions[versionData]; } let versionPath = versionData[requestedVersionType]; - return `${BASE_API_PATH}${versionPath}/`; + return `/${versionPath}/`; } /** @@ -466,6 +477,7 @@ module.exports.redirect301 = redirect301; module.exports.createUrl = createUrl; module.exports.deduplicateDoubleSlashes = deduplicateDoubleSlashes; module.exports.getApiPath = getApiPath; +module.exports.getVersionPath = getVersionPath; module.exports.getBlogUrl = getBlogUrl; /** diff --git a/core/server/web/api/index.js b/core/server/web/api/index.js new file mode 100644 index 0000000000..a89eef55d9 --- /dev/null +++ b/core/server/web/api/index.js @@ -0,0 +1,21 @@ +const debug = require('ghost-ignition').debug('web:api:default:app'); +const express = require('express'); +const urlUtils = require('../../services/url/utils'); +const errorHandler = require('../shared/middlewares/error-handler'); + +module.exports = function setupApiApp() { + debug('Parent API setup start'); + const apiApp = express(); + + // Mount different API versions + apiApp.use(urlUtils.getVersionPath({version: 'v0.1'}), require('./v0.1/app')()); + apiApp.use(urlUtils.getVersionPath({version: 'v2', type: 'content'}), require('./v2/content/app')()); + apiApp.use(urlUtils.getVersionPath({version: 'v2', type: 'admin'}), require('./v2/admin/app')()); + + // Error handling for requests to non-existent API versions + apiApp.use(errorHandler.resourceNotFound); + apiApp.use(errorHandler.handleJSONResponse); + + debug('Parent API setup end'); + return apiApp; +}; \ No newline at end of file diff --git a/core/server/web/parent-app.js b/core/server/web/parent-app.js index d9245b8479..75bccd681f 100644 --- a/core/server/web/parent-app.js +++ b/core/server/web/parent-app.js @@ -4,7 +4,6 @@ const config = require('../config'); const compress = require('compression'); const netjet = require('netjet'); const shared = require('./shared'); -const urlUtils = require('../services/url/utils'); module.exports = function setupParentApp(options = {}) { debug('ParentApp setup start'); @@ -36,11 +35,10 @@ module.exports = function setupParentApp(options = {}) { parentApp.use(shared.middlewares.ghostLocals); // Mount the apps on the parentApp + // API // @TODO: finish refactoring the API app - parentApp.use(urlUtils.getApiPath({version: 'v0.1'}), require('./api/v0.1/app')()); - parentApp.use(urlUtils.getApiPath({version: 'v2', type: 'content'}), require('./api/v2/content/app')()); - parentApp.use(urlUtils.getApiPath({version: 'v2', type: 'admin'}), require('./api/v2/admin/app')()); + parentApp.use('/ghost/api', require('./api')()); // ADMIN parentApp.use('/ghost', require('./admin')()); diff --git a/core/test/unit/web/parent-app_spec.js b/core/test/unit/web/parent-app_spec.js index 658b77923a..79c914ba37 100644 --- a/core/test/unit/web/parent-app_spec.js +++ b/core/test/unit/web/parent-app_spec.js @@ -6,9 +6,7 @@ var should = require('should'), describe('parent app', function () { let expressStub; let use; - let apiV01Spy; - let apiContentV2Spy; - let apiAdminV2Spy; + let apiSpy; let parentApp; let adminSpy; let siteSpy; @@ -20,17 +18,13 @@ describe('parent app', function () { enable: () => {} }); - apiV01Spy = sinon.spy(); - apiContentV2Spy = sinon.spy(); - apiAdminV2Spy = sinon.spy(); + apiSpy = sinon.spy(); adminSpy = sinon.spy(); siteSpy = sinon.spy(); parentApp = proxyquire('../../../server/web/parent-app', { express: expressStub, - './api/v0.1/app': apiV01Spy, - './api/v2/content/app': apiContentV2Spy, - './api/v2/admin/app': apiAdminV2Spy, + './api': apiSpy, './admin': adminSpy, './site': siteSpy }); @@ -40,17 +34,13 @@ describe('parent app', function () { sandbox.restore(); }); - it('should mount 5 apps and assign correct routes to them', function () { + it('should mount 3 apps and assign correct routes to them', function () { parentApp(); - use.calledWith('/ghost/api/v0.1/').should.be.true(); - use.calledWith('/ghost/api/v2/content/').should.be.true(); - use.calledWith('/ghost/api/v2/admin/').should.be.true(); + use.calledWith('/ghost/api').should.be.true(); use.calledWith('/ghost').should.be.true(); - apiV01Spy.called.should.be.true(); - apiContentV2Spy.called.should.be.true(); - apiAdminV2Spy.called.should.be.true(); + apiSpy.called.should.be.true(); adminSpy.called.should.be.true(); siteSpy.called.should.be.true(); });