mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-12-21 09:52:06 +03:00
6a4af1f465
refs https://github.com/TryGhost/Team/issues/65 We are currently work on dynamic routing (aka channels). An important piece of this feature is the url service, which always knows the url of a resource at any time. Resources can belong to collections or taxonomies, which can be defined in a [routing yaml file](https://github.com/TryGhost/Ghost/issues/9528). We are currently shipping portions, which will at end form the full dynamic routing feature. ### Key Notes - each routing type (collections, taxonomies, static pages) is registered in order - depending on the yaml routes file configuration - static pages are an internal concept - they sit at the end of the subscriber queue - we make use of a temporary [`Channels2`](https://github.com/TryGhost/Ghost/pull/9550/files#diff-9e7251409844521470c9829013cd1563) file, which simulates the current static routing in Ghost (this file will be modified, removed or whatever - this is one of the next steps) - two way binding: you can ask for a resource url based on the resource id, you can ask for the resource based on the url - in theory it's possible that multiple resources generate the same url: we don't handle this with collision (because this is error prone), we handle this with the order of serving content. if you ask the service for a resource, which lives behind e.g. /test/, you will get the resource which is served - loose error handling -> log errors and handle instead of throw error and do nothing (we log the errors with a specific code, so we can react in case there is a bug) - the url services fetches all resources on bootstrap. we only fetch and keep a reduced set of attributes (basically the main body of a resource) - the bootstrap time will decrease a very little (depending on the amount of resources you have in your database) - we still offer the option to disable url preloading (in your config `disableUrlPreload: true`) - this option will be removed as soon as the url service is connected. You can disable the service in case you encounter a problem - **the url service is not yet connected, we will connect the service step by step. The first version should be released to pre-catch bugs. The next version will add 503 handling if the url service is not ready and it will consume urls for resources.** ---- - the url service generates urls based on resources (posts, pages, users, tags) - the url service keeps track of resource changes - the url service keeps track of resource removal/insert - the architecture: - each routing type is represented by a url generator - a routing type is a collection, a taxonomiy or static pages - a queue which ensures that urls are unique and can be owned by one url generator - the hierarchy of registration defines that - we query knex, because bookshelf is too slow - removed old url service files + logic - added temp channels alternative (Channels2) -> this file will look different soon, it's for now the temporary connector to the url service. Also the name of the file is not optimal, but that is not really important right now.
140 lines
5.2 KiB
JavaScript
140 lines
5.2 KiB
JavaScript
var debug = require('ghost-ignition').debug('blog'),
|
|
path = require('path'),
|
|
express = require('express'),
|
|
|
|
// App requires
|
|
config = require('../../config'),
|
|
constants = require('../../lib/constants'),
|
|
storage = require('../../adapters/storage'),
|
|
urlService = require('../../services/url'),
|
|
|
|
// This should probably be an internal app
|
|
sitemapHandler = require('../../data/xml/sitemap/handler'),
|
|
|
|
// Route Service
|
|
siteRoutes = require('./routes'),
|
|
|
|
// Global/shared middleware
|
|
cacheControl = require('../middleware/cache-control'),
|
|
errorHandler = require('../middleware/error-handler'),
|
|
frontendClient = require('../middleware/frontend-client'),
|
|
maintenance = require('../middleware/maintenance'),
|
|
prettyURLs = require('../middleware/pretty-urls'),
|
|
urlRedirects = require('../middleware/url-redirects'),
|
|
|
|
// local middleware
|
|
servePublicFile = require('../middleware/serve-public-file'),
|
|
staticTheme = require('../middleware/static-theme'),
|
|
customRedirects = require('../middleware/custom-redirects'),
|
|
serveFavicon = require('../middleware/serve-favicon'),
|
|
adminRedirects = require('../middleware/admin-redirects'),
|
|
|
|
// middleware for themes
|
|
themeMiddleware = require('../../services/themes').middleware;
|
|
|
|
module.exports = function setupSiteApp() {
|
|
debug('Site setup start');
|
|
|
|
var siteApp = express();
|
|
|
|
// ## App - specific code
|
|
// set the view engine
|
|
siteApp.set('view engine', 'hbs');
|
|
|
|
// you can extend Ghost with a custom redirects file
|
|
// see https://github.com/TryGhost/Ghost/issues/7707
|
|
customRedirects.use(siteApp);
|
|
|
|
// More redirects
|
|
siteApp.use(adminRedirects());
|
|
|
|
// force SSL if blog url is set to https. The redirects handling must happen before asset and page routing,
|
|
// otherwise we serve assets/pages with http. This can cause mixed content warnings in the admin client.
|
|
siteApp.use(urlRedirects);
|
|
|
|
// Static content/assets
|
|
// @TODO make sure all of these have a local 404 error handler
|
|
// Favicon
|
|
siteApp.use(serveFavicon());
|
|
// /public/ghost-sdk.js
|
|
siteApp.use(servePublicFile('public/ghost-sdk.js', 'application/javascript', constants.ONE_HOUR_S));
|
|
siteApp.use(servePublicFile('public/ghost-sdk.min.js', 'application/javascript', constants.ONE_YEAR_S));
|
|
// Serve sitemap.xsl file
|
|
siteApp.use(servePublicFile('sitemap.xsl', 'text/xsl', constants.ONE_DAY_S));
|
|
|
|
// Serve stylesheets for default templates
|
|
siteApp.use(servePublicFile('public/ghost.css', 'text/css', constants.ONE_HOUR_S));
|
|
siteApp.use(servePublicFile('public/ghost.min.css', 'text/css', constants.ONE_YEAR_S));
|
|
|
|
// Serve images for default templates
|
|
siteApp.use(servePublicFile('public/404-ghost@2x.png', 'png', constants.ONE_HOUR_S));
|
|
siteApp.use(servePublicFile('public/404-ghost.png', 'png', constants.ONE_HOUR_S));
|
|
|
|
// Serve blog images using the storage adapter
|
|
siteApp.use('/' + urlService.utils.STATIC_IMAGE_URL_PREFIX, storage.getStorage().serve());
|
|
|
|
// @TODO find this a better home
|
|
// We do this here, at the top level, because helpers require so much stuff.
|
|
// Moving this to being inside themes, where it probably should be requires the proxy to be refactored
|
|
// Else we end up with circular dependencies
|
|
require('../../helpers').loadCoreHelpers();
|
|
debug('Helpers done');
|
|
|
|
// Theme middleware
|
|
// This should happen AFTER any shared assets are served, as it only changes things to do with templates
|
|
// At this point the active theme object is already updated, so we have the right path, so it can probably
|
|
// go after staticTheme() as well, however I would really like to simplify this and be certain
|
|
siteApp.use(themeMiddleware);
|
|
debug('Themes done');
|
|
|
|
// Theme static assets/files
|
|
siteApp.use(staticTheme());
|
|
debug('Static content done');
|
|
|
|
// Serve robots.txt if not found in theme
|
|
siteApp.use(servePublicFile('robots.txt', 'text/plain', constants.ONE_HOUR_S));
|
|
|
|
// setup middleware for internal apps
|
|
// @TODO: refactor this to be a proper app middleware hook for internal & external apps
|
|
config.get('apps:internal').forEach(function (appName) {
|
|
var app = require(path.join(config.get('paths').internalAppPath, appName));
|
|
if (app.hasOwnProperty('setupMiddleware')) {
|
|
app.setupMiddleware(siteApp);
|
|
}
|
|
});
|
|
|
|
// site map - this should probably be refactored to be an internal app
|
|
sitemapHandler(siteApp);
|
|
debug('Internal apps done');
|
|
|
|
// send 503 error page in case of maintenance
|
|
siteApp.use(maintenance);
|
|
|
|
// Add in all trailing slashes & remove uppercase
|
|
// must happen AFTER asset loading and BEFORE routing
|
|
siteApp.use(prettyURLs);
|
|
|
|
// ### Caching
|
|
// Site frontend is cacheable
|
|
siteApp.use(cacheControl('public'));
|
|
|
|
// Fetch the frontend client into res.locals
|
|
siteApp.use(frontendClient);
|
|
|
|
debug('General middleware done');
|
|
|
|
// @temporary
|
|
require('../../services/channels/Channels2');
|
|
|
|
// Set up Frontend routes (including private blogging routes)
|
|
siteApp.use(siteRoutes());
|
|
|
|
// ### Error handlers
|
|
siteApp.use(errorHandler.pageNotFound);
|
|
siteApp.use(errorHandler.handleThemeResponse);
|
|
|
|
debug('Site setup end');
|
|
|
|
return siteApp;
|
|
};
|