feat: front-end pages middleware

custom pages may now override any built-in pages on the fly as lolisafe
is running

also added internal persistent cache feature into NunjucksRenderer
front-end pages will now be persistently cached during production
This commit is contained in:
Bobby Wibowo 2022-07-12 10:31:59 +07:00
parent 9852dec3d1
commit 80d59ff2f0
No known key found for this signature in database
GPG Key ID: 51C3A1E1E22D26CF
2 changed files with 38 additions and 21 deletions

View File

@ -4,6 +4,8 @@ class NunjucksRenderer {
directory
environment
#persistentCaches = new Map()
constructor (directory = '', options = {}) {
if (typeof directory !== 'string') {
throw new TypeError('Root directory must be a string value')
@ -21,14 +23,27 @@ class NunjucksRenderer {
#middleware (req, res, next) {
// Inject render() method into Response on each requests
res.render = (path, params) => this.#render(res, path, params)
// If usePersistentCache, the rendered template will be cached forever (thus only use for absolutely static pages)
res.render = (path, params, usePersistentCache) => this.#render(res, path, params, usePersistentCache)
return next()
}
#render (res, path, params) {
#render (res, path, params, usePersistentCache) {
return new Promise((resolve, reject) => {
this.environment.render(`${path}.njk`, params, (err, html) => {
if (err) return reject(err)
const template = `${path}.njk`
const cached = this.#persistentCaches.get(template)
if (usePersistentCache && cached) {
return resolve(cached)
}
this.environment.render(template, params, (err, html) => {
if (err) {
return reject(err)
}
if (usePersistentCache) {
this.#persistentCaches.set(template, html)
}
resolve(html)
})
}).then(html => {

View File

@ -242,24 +242,26 @@ safe.use('/api', api)
config.pages.push('cookiepolicy')
}
// Check for custom pages, otherwise fallback to Nunjucks templates
for (const page of config.pages) {
// FIXME: Have this update on-the-fly or don't use LiveDirectory
const customPage = liveDirectoryCustomPages.get(`${page}.html`)
if (customPage) {
safe.get(`/${page === 'home' ? '' : page}`, (req, res) => {
res.type('html').send(customPage.buffer)
})
} else if (page === 'home') {
safe.get('/', (req, res) => res.render(page, {
config, utils, versions: utils.versionStrings
}))
} else {
safe.get(`/${page}`, (req, res) => res.render(page, {
config, utils, versions: utils.versionStrings
}))
// Front-end pages middleware
// HTML files in customPages directory can also override any built-in pages,
// if they have matching names with the routes (e.g. home.html can override the homepage)
// Aside from that, due to using LiveDirectory,
// custom pages can be added/removed on the fly while lolisafe is running
safe.use((req, res, next) => {
if (req.method === 'GET' || req.method === 'HEAD') {
const page = req.path === '/' ? 'home' : req.path.substring(1)
const customPage = liveDirectoryCustomPages.get(`${page}.html`)
if (customPage) {
return res.type('html').send(customPage.buffer)
} else if (config.pages.includes(page)) {
// These rendered pages are persistently cached during production
return res.render(page, {
config, utils, versions: utils.versionStrings
}, !isDevMode)
}
}
}
return next()
})
// Init ServerStatic last if serving uploaded files with node
/* // TODO