From b1566c5abfcced84ec4f426f33330deea33e9ca8 Mon Sep 17 00:00:00 2001 From: Bobby Wibowo Date: Sun, 31 Jul 2022 14:08:13 +0700 Subject: [PATCH] refactor: ServeLiveDirectory ensure forward slashes path refactored init method ensure internal res.type is set before attempting to call external setHeaders function, to allow overrides --- controllers/middlewares/ServeLiveDirectory.js | 51 +++++++++++++++---- lolisafe.js | 11 ++-- 2 files changed, 47 insertions(+), 15 deletions(-) diff --git a/controllers/middlewares/ServeLiveDirectory.js b/controllers/middlewares/ServeLiveDirectory.js index 2985023..51b91c3 100644 --- a/controllers/middlewares/ServeLiveDirectory.js +++ b/controllers/middlewares/ServeLiveDirectory.js @@ -1,3 +1,18 @@ +/* + * ServeLiveDirectory is a middleware wrapper for LiveDirectory library. + * + * It is mainly intended to add Conditional GETs support, + * which involves handling cache-related headers such as + * If-Match, If-Unmodified-Since, ETag, etc. + * + * LiveDirectory monitors and caches all the files in the configure directory into memory, + * which allows very fast lookups, thus allowing multiple instances of this middleware + * to be used together, if needed. + * + * However, due to the fact that it caches all the files into memory, + * this may not be the best choice in an environment where memory space is a premium. + */ + const LiveDirectory = require('live-directory') const serveUtils = require('./../utils/serveUtils') @@ -6,15 +21,17 @@ class ServeLiveDirectory { #options - constructor (instanceOptions = {}, options = {}) { - if (!instanceOptions.ignore) { - instanceOptions.ignore = path => { - // ignore dot files - return path.startsWith('.') - } + constructor (directory, options = {}) { + if (!directory || typeof directory !== 'string') { + throw new TypeError('Root directory must be set') } - this.instance = new LiveDirectory(instanceOptions) + this.directory = serveUtils.forwardSlashes(directory) + + // Ensure does not end with a forward slash + if (this.directory.endsWith('/')) { + this.directory = this.directory.slice(0, -1) + } if (options.etag === undefined) { options.etag = true @@ -28,6 +45,20 @@ class ServeLiveDirectory { throw new TypeError('Middleware option setHeaders must be a function') } + const instanceOptions = Object.assign({}, options.instanceOptions) + instanceOptions.path = this.directory + + delete options.instanceOptions + + if (!instanceOptions.ignore) { + instanceOptions.ignore = path => { + // ignore dot files + return path.startsWith('.') + } + } + + this.instance = new LiveDirectory(instanceOptions) + this.#options = options } @@ -39,12 +70,12 @@ class ServeLiveDirectory { */ handler (req, res, file) { - // set header fields - this.#setHeaders(req, res, file) - // set content-type res.type(file.extension) + // set header fields + this.#setHeaders(req, res, file) + // conditional GET support if (serveUtils.isConditionalGET(req)) { if (serveUtils.isPreconditionFailure(req, res)) { diff --git a/lolisafe.js b/lolisafe.js index 65042e5..55f4e0d 100644 --- a/lolisafe.js +++ b/lolisafe.js @@ -190,12 +190,12 @@ if (config.cacheControl) { // Init LiveDirectory middlewares for static assets // Static assets in /public directory -const serveLiveDirectoryPublicInstance = new ServeLiveDirectory({ path: paths.public }, { +const serveLiveDirectoryPublicInstance = new ServeLiveDirectory(paths.public, { setHeaders: setHeadersForStaticAssets }) safe.use(serveLiveDirectoryPublicInstance.middleware) // Static assets in /dist directory -const serveLiveDirectoryDistInstance = new ServeLiveDirectory({ path: paths.dist }, { +const serveLiveDirectoryDistInstance = new ServeLiveDirectory(paths.dist, { setHeaders: setHeadersForStaticAssets }) safe.use(serveLiveDirectoryDistInstance.middleware) @@ -231,9 +231,10 @@ safe.use('/api', api) } } - const serveLiveDirectoryCustomPagesInstance = new ServeLiveDirectory({ - path: paths.customPages, - keep: ['.html'] + const serveLiveDirectoryCustomPagesInstance = new ServeLiveDirectory(paths.customPages, { + instanceOptions: { + keep: ['.html'] + } }) // Cookie Policy