diff --git a/app.js b/app.js index 741dac93f..4e74062d5 100644 --- a/app.js +++ b/app.js @@ -5,7 +5,12 @@ const path = require('path'); const helmet = require('helmet'); const compression = require('compression'); const cookieParser = require('cookie-parser'); -const {BASE_URL, BASE_PATH, MOUNT_PATH} = require('./url'); +const { + BASE_URL, + BASE_PATH, + MOUNT_PATH, + STATIC_URL, +} = require('./url'); const routes = require('./routes'); const debug = require('debug')('talk:app'); @@ -55,6 +60,7 @@ app.set('view engine', 'ejs'); app.locals.BASE_URL = BASE_URL; app.locals.BASE_PATH = BASE_PATH; app.locals.MOUNT_PATH = MOUNT_PATH; +app.locals.STATIC_URL = STATIC_URL; debug(`mounting routes on the ${MOUNT_PATH} path`); diff --git a/config.js b/config.js index d7e247ec3..1a54ece5a 100644 --- a/config.js +++ b/config.js @@ -117,6 +117,13 @@ const CONFIG = { // TALK_ROOT_URL and use it to mount the paths on. ROOT_URL_MOUNT_PATH: process.env.TALK_ROOT_URL_MOUNT_PATH === 'TRUE', + // DISABLE_STATIC_SERVER when TRUE will disable the routes used for static + // asset serving. + DISABLE_STATIC_SERVER: process.env.TALK_DISABLE_STATIC_SERVER === 'TRUE', + + // STATIC_URI is the base uri where static files are hosted. + STATIC_URI: process.env.TALK_STATIC_URI || process.env.TALK_ROOT_URL, + // The keepalive timeout (in ms) that should be used to send keep alive // messages through the websocket to keep the socket alive. KEEP_ALIVE: process.env.TALK_KEEP_ALIVE || '30s', diff --git a/docs/_docs/02-01-configuration.md b/docs/_docs/02-01-configuration.md index 6ffb9afc0..021735fb9 100644 --- a/docs/_docs/02-01-configuration.md +++ b/docs/_docs/02-01-configuration.md @@ -90,6 +90,12 @@ These are only used during the webpack build. managing the auth state manually, auth cannot be persisted, for further information refer to the [Persistence Documentation]({{ "/docs/running/persistence/" | absolute_url }})** (Default `${ssl ? 'ws' : 'wss'}://${location.host}${TALK_ROOT_URL_MOUNT_PATH}api/v1/live`) +- `TALK_STATIC_URI` (_optional_) - Used to set the uri where the static assets + should be served from. This is used when you want to upload the static assets + through your build process to a service like Google Cloud Storage or Amazon S3 + and you would then specify the CDN/Storage url. (Default `process.env.TALK_ROOT_URL`) +- `TALK_DISABLE_STATIC_SERVER` (_optional_) - When `TRUE`, it will not mount the + static asset serving routes on the router. (Default `FALSE`) ### Word Filter diff --git a/routes/admin/index.js b/routes/admin/index.js index ab6189e85..b3872d626 100644 --- a/routes/admin/index.js +++ b/routes/admin/index.js @@ -1,9 +1,6 @@ const express = require('express'); const router = express.Router(); -const { - RECAPTCHA_PUBLIC, - WEBSOCKET_LIVE_URI, -} = require('../../config'); +const {data} = require('../static'); // Get /email-confirmation expects a signed JWT in the hash router.get('/confirm-email', (req, res) => { @@ -20,11 +17,6 @@ router.get('/password-reset', (req, res) => { }); router.get('*', (req, res) => { - const data = { - TALK_RECAPTCHA_PUBLIC: RECAPTCHA_PUBLIC, - LIVE_URI: WEBSOCKET_LIVE_URI, - }; - res.render('admin', {data}); }); diff --git a/routes/embed/index.js b/routes/embed/index.js index 256d03b30..c360c1f76 100644 --- a/routes/embed/index.js +++ b/routes/embed/index.js @@ -1,20 +1,12 @@ const express = require('express'); const router = express.Router(); const SettingsService = require('../../services/settings'); -const { - RECAPTCHA_PUBLIC, - WEBSOCKET_LIVE_URI, -} = require('../../config'); +const {data} = require('../static'); router.use('/:embed', async (req, res, next) => { switch (req.params.embed) { case 'stream': { const {customCssUrl} = await SettingsService.retrieve(); - const data = { - TALK_RECAPTCHA_PUBLIC: RECAPTCHA_PUBLIC, - LIVE_URI: WEBSOCKET_LIVE_URI, - }; - return res.render('embed/stream', {customCssUrl, data}); } } diff --git a/routes/index.js b/routes/index.js index 6a8920dc3..23e8d8a47 100644 --- a/routes/index.js +++ b/routes/index.js @@ -11,6 +11,7 @@ const errors = require('../errors'); const {createGraphOptions} = require('../graph'); const accepts = require('accepts'); const apollo = require('graphql-server-express'); +const {DISABLE_STATIC_SERVER} = require('../config'); const router = express.Router(); @@ -39,20 +40,26 @@ if (process.env.NODE_ENV === 'production') { }); } -router.use('/client', express.static(path.join(__dirname, '../dist'))); -router.use('/public', express.static(path.join(__dirname, '../public'))); +if (!DISABLE_STATIC_SERVER) { -/** - * Serves a file based on a relative path. - */ -const serveFile = (filename) => (req, res) => res.sendFile(path.join(__dirname, filename)); + /** + * Serve the directories under public/dist from this router. + */ + router.use('/client', express.static(path.join(__dirname, '../dist'))); + router.use('/public', express.static(path.join(__dirname, '../public'))); -/** - * Serves the embed javascript files. - */ -router.get('/embed.js', serveFile('../dist/embed.js')); -router.get('/embed.js.gz', serveFile('../dist/embed.js.gz')); -router.get('/embed.js.map', serveFile('../dist/embed.js.map')); + /** + * Serves a file based on a relative path. + */ + const serveFile = (filename) => (req, res) => res.sendFile(path.join(__dirname, filename)); + + /** + * Serves the embed javascript files. + */ + router.get('/embed.js', serveFile('../dist/embed.js')); + router.get('/embed.js.gz', serveFile('../dist/embed.js.gz')); + router.get('/embed.js.map', serveFile('../dist/embed.js.map')); +} //============================================================================== // PASSPORT MIDDLEWARE diff --git a/routes/static.js b/routes/static.js new file mode 100644 index 000000000..12bf01282 --- /dev/null +++ b/routes/static.js @@ -0,0 +1,13 @@ +const { + RECAPTCHA_PUBLIC, + WEBSOCKET_LIVE_URI, +} = require('../config'); +const { + STATIC_URL, +} = require('../url'); + +module.exports.data = { + TALK_RECAPTCHA_PUBLIC: RECAPTCHA_PUBLIC, + LIVE_URI: WEBSOCKET_LIVE_URI, + STATIC_URL, +}; diff --git a/url.js b/url.js index 1def7a707..10013ce35 100644 --- a/url.js +++ b/url.js @@ -1,9 +1,15 @@ -const {ROOT_URL, ROOT_URL_MOUNT_PATH} = require('./config'); +const { + ROOT_URL, + ROOT_URL_MOUNT_PATH, + STATIC_URI, +} = require('./config'); const {URL} = require('url'); +const trailingSlash = (url) => url && url.length > 0 && url[url.length - 1] === '/' ? url : `${url}/`; + // Set the BASE_URL as the ROOT_URL, here we derive the root url by ensuring // that it ends in a `/`. -const BASE_URL = ROOT_URL && ROOT_URL.length > 0 && ROOT_URL[ROOT_URL.length - 1] === '/' ? ROOT_URL : `${ROOT_URL}/`; +const BASE_URL = trailingSlash(ROOT_URL); // The BASE_PATH is simply the path component of the BASE_URL. const BASE_PATH = new URL(BASE_URL).pathname; @@ -12,8 +18,12 @@ const BASE_PATH = new URL(BASE_URL).pathname; // This will mount all the application routes onto it. const MOUNT_PATH = ROOT_URL_MOUNT_PATH ? BASE_PATH : '/'; +// The STATIC_URL is the url where static assets should be loaded from. +const STATIC_URL = trailingSlash(STATIC_URI); + module.exports = { - BASE_URL: BASE_URL, - BASE_PATH: BASE_PATH, - MOUNT_PATH: MOUNT_PATH, + BASE_URL, + BASE_PATH, + MOUNT_PATH, + STATIC_URL, }; diff --git a/views/admin.ejs b/views/admin.ejs index 2aa23aa58..70fed054e 100644 --- a/views/admin.ejs +++ b/views/admin.ejs @@ -4,19 +4,19 @@ Talk - Coral Admin - - - - - - - - - - - - - + + + + + + + + + + + + + @@ -42,6 +42,6 @@
- + diff --git a/views/admin/docs.ejs b/views/admin/docs.ejs index d13dff064..ae2fe2dcf 100644 --- a/views/admin/docs.ejs +++ b/views/admin/docs.ejs @@ -28,6 +28,6 @@
- + diff --git a/views/article.ejs b/views/article.ejs index 0f8c75594..0bda3a6e0 100644 --- a/views/article.ejs +++ b/views/article.ejs @@ -24,7 +24,7 @@

<%= body %>

Admin - All Assets

- +