mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-03-11 02:12:21 -05:00
Wrapped express router & expose from route service (#9206)
refs #9192 - Moving towards a centralised concept of routing / routes - The base router now wraps express router, and offers us the features we need - Site Router is the parent router, it gets initialised with all of our default routing - App Router is a sub router for apps - apps register their routes/routers onto it. - TODO: refactor channels subrouter to work this same way - MAYBE: move the app router to the apps service
This commit is contained in:
parent
90cfdbe7a6
commit
7656d0bdda
8 changed files with 115 additions and 52 deletions
|
@ -73,7 +73,7 @@ generateProxyFunctions = function (name, permissions, isInternal) {
|
|||
// Expose the route service...
|
||||
routeService: {
|
||||
// This allows for mounting an entirely new Router at a path...
|
||||
registerRouter: checkRegisterPermissions('routes', router.registerRouter.bind(router))
|
||||
registerRouter: checkRegisterPermissions('routes', router.mountRouter.bind(router))
|
||||
},
|
||||
// Mini proxy to the API - needs review
|
||||
api: {
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
'use strict';
|
||||
/**
|
||||
* An instance of router that is provided to Apps, to mount routes into.
|
||||
*/
|
||||
|
||||
var debug = require('ghost-ignition').debug('services:routes:app'),
|
||||
Router = require('./base/Router');
|
||||
|
||||
class AppRouter extends Router {
|
||||
registerRouter(path, router) {
|
||||
debug('registerRouter for', path);
|
||||
this.router.use(path, router);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = AppRouter;
|
4
core/server/services/route/app-router.js
Normal file
4
core/server/services/route/app-router.js
Normal file
|
@ -0,0 +1,4 @@
|
|||
var Router = require('./base/Router'),
|
||||
appRouter = new Router('apps');
|
||||
|
||||
module.exports = appRouter;
|
|
@ -1,10 +1,48 @@
|
|||
'use strict';
|
||||
/**
|
||||
* # Router
|
||||
*
|
||||
* A wrapper around express.Router
|
||||
* Intended to be extended anywhere that routes need to be registered in Ghost
|
||||
* Only allows for .use and .get at the moment - we don't have clear use-cases for anything else yet.
|
||||
*/
|
||||
|
||||
var expressRouter = require('express').Router;
|
||||
|
||||
var debug = require('ghost-ignition').debug('services:routes:ParentRouter'),
|
||||
express = require('express'),
|
||||
// This is a shared global cache
|
||||
// @TODO expand this as part of the route service
|
||||
routes = [];
|
||||
/**
|
||||
* We expose a very limited amount of express.Router via specialist methods
|
||||
*/
|
||||
class Router {
|
||||
constructor() {
|
||||
this.router = expressRouter({mergeParams: true});
|
||||
constructor(name) {
|
||||
this.name = name;
|
||||
this._router = express.Router({mergeParams: true});
|
||||
}
|
||||
|
||||
mountRouter(path, router) {
|
||||
if (arguments.length === 1) {
|
||||
router = path;
|
||||
debug(this.name + ': mountRouter: ' + router.name);
|
||||
this._router.use(router);
|
||||
} else {
|
||||
routes.push(path);
|
||||
debug(this.name + ': mountRouter: ' + router.name + ' at ' + path);
|
||||
this._router.use(path, router);
|
||||
}
|
||||
}
|
||||
|
||||
mountRoute(path, controller) {
|
||||
debug(this.name + ': mountRoute for', path, controller.name);
|
||||
routes.push(path);
|
||||
this._router.get(path, controller);
|
||||
}
|
||||
|
||||
router() {
|
||||
// @TODO: should this just be the handler that is returned?
|
||||
// return this._router.handle.bind(this._router);
|
||||
return this._router;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,9 +1,23 @@
|
|||
/**
|
||||
* # Route Service
|
||||
*
|
||||
* Everything in here is 100% experimental
|
||||
* Note: routes are patterns, not individual URLs, which have either
|
||||
* subrouters, or controllers mounted on them. There are not that many routes.
|
||||
*
|
||||
* The route service is intended to:
|
||||
* - handle the mounting of all the routes throughout the bootup sequence
|
||||
* - keep track of the registered routes, and what they have mounted on them
|
||||
* - provide a way for apps to register routes
|
||||
* - keep routes being served in a sane order
|
||||
*
|
||||
* The route service does not handle:
|
||||
* - redirects
|
||||
* - assets
|
||||
* These both happen prior to the routeService router being mounted
|
||||
*/
|
||||
|
||||
var AppRouter = require('./AppRouter');
|
||||
// We expose this via the App Proxy, so that Apps can register routes
|
||||
module.exports.appRouter = require('./app-router');
|
||||
// This is the main router, that gets mounted in the express app in /site
|
||||
module.exports.router = require('./site-router');
|
||||
|
||||
module.exports.appRouter = new AppRouter();
|
||||
|
|
48
core/server/services/route/site-router.js
Normal file
48
core/server/services/route/site-router.js
Normal file
|
@ -0,0 +1,48 @@
|
|||
var Router = require('./base/Router'),
|
||||
siteRouter = new Router('site'),
|
||||
|
||||
// Sub Routers
|
||||
appRouter = require('./app-router'),
|
||||
channelService = require('../channels'),
|
||||
|
||||
// Controllers
|
||||
controllers = require('../../controllers'),
|
||||
|
||||
// Utils for creating paths
|
||||
// @TODO: refactor these away
|
||||
config = require('../../config'),
|
||||
utils = require('../../utils'),
|
||||
|
||||
_private = {};
|
||||
|
||||
_private.mountDefaultRoutes = function mountDefaultRoutes() {
|
||||
// @TODO move this path out of this file!
|
||||
// Note this also exists in api/index.js
|
||||
var previewRoute = utils.url.urlJoin('/', config.get('routeKeywords').preview, ':uuid', ':options?');
|
||||
|
||||
// Preview - register controller as route
|
||||
// Ideal version, as we don't want these paths all over the place
|
||||
// previewRoute = new Route('GET /:t_preview/:uuid/:options?', previewController);
|
||||
// siteRouter.mountRoute(previewRoute);
|
||||
// Orrrrr maybe preview should be an internal App??!
|
||||
siteRouter.mountRoute(previewRoute, controllers.preview);
|
||||
|
||||
// Channels - register sub-router
|
||||
// The purpose of having a parentRouter for channels, is so that we can load channels from wherever we want:
|
||||
// config, settings, apps, etc, and that it will be possible for the router to be reloaded.
|
||||
siteRouter.mountRouter(channelService.router());
|
||||
|
||||
// Apps - register sub-router
|
||||
// The purpose of having a parentRouter for apps, is that Apps can register a route whenever they want.
|
||||
// Apps cannot yet deregister, it's complex to implement and I don't yet have a clear use-case for this.
|
||||
siteRouter.mountRouter(appRouter.router());
|
||||
|
||||
// Default - register entry controller as route
|
||||
siteRouter.mountRoute('*', controllers.entry);
|
||||
};
|
||||
|
||||
module.exports = function router() {
|
||||
_private.mountDefaultRoutes();
|
||||
|
||||
return siteRouter.router();
|
||||
};
|
|
@ -10,8 +10,8 @@ var debug = require('ghost-ignition').debug('blog'),
|
|||
// This should probably be an internal app
|
||||
sitemapHandler = require('../data/xml/sitemap/handler'),
|
||||
|
||||
// routes
|
||||
routes = require('./routes'),
|
||||
// Route Service
|
||||
routeService = require('../services/route'),
|
||||
|
||||
// Global/shared middleware
|
||||
cacheControl = require('../middleware/cache-control'),
|
||||
|
@ -122,7 +122,7 @@ module.exports = function setupSiteApp() {
|
|||
debug('General middleware done');
|
||||
|
||||
// Set up Frontend routes (including private blogging routes)
|
||||
siteApp.use(routes());
|
||||
siteApp.use(routeService.router());
|
||||
|
||||
// ### Error handlers
|
||||
siteApp.use(errorHandler.pageNotFound);
|
||||
|
|
|
@ -1,25 +0,0 @@
|
|||
var express = require('express'),
|
||||
config = require('../config'),
|
||||
controllers = require('../controllers'),
|
||||
channelService = require('../services/channels/'),
|
||||
appRouter = require('../services/route').appRouter,
|
||||
utils = require('../utils');
|
||||
|
||||
module.exports = function siteRouter() {
|
||||
var router = express.Router(),
|
||||
routeKeywords = config.get('routeKeywords');
|
||||
|
||||
// Preview - register controller as route
|
||||
router.get(utils.url.urlJoin('/', routeKeywords.preview, ':uuid', ':options?'), controllers.preview);
|
||||
|
||||
// Channels - register sub-router
|
||||
router.use(channelService.router());
|
||||
|
||||
// Apps - register sub-router
|
||||
router.use(appRouter.router);
|
||||
|
||||
// Default - register entry controller as route
|
||||
router.get('*', controllers.entry);
|
||||
|
||||
return router;
|
||||
};
|
Loading…
Add table
Reference in a new issue