0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2025-02-03 23:00:14 -05:00

🐛 Fixed missing 404 for unknown API routes (#10070)

closes #10020

* Append trailing slash to version path
This commit is contained in:
anaplian 2018-11-26 09:35:38 +00:00 committed by Fabien O'Carroll
parent e48c28b98f
commit c539d39875
4 changed files with 43 additions and 22 deletions

View file

@ -6,7 +6,7 @@ const moment = require('moment-timezone'),
cheerio = require('cheerio'), cheerio = require('cheerio'),
config = require('../../config'), config = require('../../config'),
settingsCache = require('../settings/cache'), settingsCache = require('../settings/cache'),
BASE_API_PATH = '/ghost/api/', BASE_API_PATH = '/ghost/api',
STATIC_IMAGE_URL_PREFIX = 'content/images'; STATIC_IMAGE_URL_PREFIX = 'content/images';
/** /**
@ -16,6 +16,17 @@ const moment = require('moment-timezone'),
* @return {string} API Path for version * @return {string} API Path for version
*/ */
function getApiPath(options) { 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'); const apiVersions = config.get('api:versions');
let requestedVersion = options.version || 'deprecated'; let requestedVersion = options.version || 'deprecated';
let requestedVersionType = options.type || 'content'; let requestedVersionType = options.type || 'content';
@ -24,7 +35,7 @@ function getApiPath(options) {
versionData = apiVersions[versionData]; versionData = apiVersions[versionData];
} }
let versionPath = versionData[requestedVersionType]; 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.createUrl = createUrl;
module.exports.deduplicateDoubleSlashes = deduplicateDoubleSlashes; module.exports.deduplicateDoubleSlashes = deduplicateDoubleSlashes;
module.exports.getApiPath = getApiPath; module.exports.getApiPath = getApiPath;
module.exports.getVersionPath = getVersionPath;
module.exports.getBlogUrl = getBlogUrl; module.exports.getBlogUrl = getBlogUrl;
/** /**

View file

@ -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;
};

View file

@ -4,7 +4,6 @@ const config = require('../config');
const compress = require('compression'); const compress = require('compression');
const netjet = require('netjet'); const netjet = require('netjet');
const shared = require('./shared'); const shared = require('./shared');
const urlUtils = require('../services/url/utils');
module.exports = function setupParentApp(options = {}) { module.exports = function setupParentApp(options = {}) {
debug('ParentApp setup start'); debug('ParentApp setup start');
@ -36,11 +35,10 @@ module.exports = function setupParentApp(options = {}) {
parentApp.use(shared.middlewares.ghostLocals); parentApp.use(shared.middlewares.ghostLocals);
// Mount the apps on the parentApp // Mount the apps on the parentApp
// API // API
// @TODO: finish refactoring the API app // @TODO: finish refactoring the API app
parentApp.use(urlUtils.getApiPath({version: 'v0.1'}), require('./api/v0.1/app')()); parentApp.use('/ghost/api', require('./api')());
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')());
// ADMIN // ADMIN
parentApp.use('/ghost', require('./admin')()); parentApp.use('/ghost', require('./admin')());

View file

@ -6,9 +6,7 @@ var should = require('should'),
describe('parent app', function () { describe('parent app', function () {
let expressStub; let expressStub;
let use; let use;
let apiV01Spy; let apiSpy;
let apiContentV2Spy;
let apiAdminV2Spy;
let parentApp; let parentApp;
let adminSpy; let adminSpy;
let siteSpy; let siteSpy;
@ -20,17 +18,13 @@ describe('parent app', function () {
enable: () => {} enable: () => {}
}); });
apiV01Spy = sinon.spy(); apiSpy = sinon.spy();
apiContentV2Spy = sinon.spy();
apiAdminV2Spy = sinon.spy();
adminSpy = sinon.spy(); adminSpy = sinon.spy();
siteSpy = sinon.spy(); siteSpy = sinon.spy();
parentApp = proxyquire('../../../server/web/parent-app', { parentApp = proxyquire('../../../server/web/parent-app', {
express: expressStub, express: expressStub,
'./api/v0.1/app': apiV01Spy, './api': apiSpy,
'./api/v2/content/app': apiContentV2Spy,
'./api/v2/admin/app': apiAdminV2Spy,
'./admin': adminSpy, './admin': adminSpy,
'./site': siteSpy './site': siteSpy
}); });
@ -40,17 +34,13 @@ describe('parent app', function () {
sandbox.restore(); 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(); parentApp();
use.calledWith('/ghost/api/v0.1/').should.be.true(); use.calledWith('/ghost/api').should.be.true();
use.calledWith('/ghost/api/v2/content/').should.be.true();
use.calledWith('/ghost/api/v2/admin/').should.be.true();
use.calledWith('/ghost').should.be.true(); use.calledWith('/ghost').should.be.true();
apiV01Spy.called.should.be.true(); apiSpy.called.should.be.true();
apiContentV2Spy.called.should.be.true();
apiAdminV2Spy.called.should.be.true();
adminSpy.called.should.be.true(); adminSpy.called.should.be.true();
siteSpy.called.should.be.true(); siteSpy.called.should.be.true();
}); });