mirror of
https://github.com/BobbyWibowo/lolisafe.git
synced 2025-02-23 05:39:05 +00:00
fix: ServeStatic
init setContentDisposition and setContentType functions immediately as private functions to reduce complexity so instead check for the required map/store before using them also fixed content-type override ending up with duplicate headers
This commit is contained in:
parent
21ec4a7479
commit
323c107f64
@ -31,8 +31,6 @@ class ServeStatic {
|
|||||||
directory
|
directory
|
||||||
contentDispositionStore
|
contentDispositionStore
|
||||||
contentTypesMaps
|
contentTypesMaps
|
||||||
setContentDisposition
|
|
||||||
setContentType
|
|
||||||
|
|
||||||
#options
|
#options
|
||||||
|
|
||||||
@ -70,7 +68,7 @@ class ServeStatic {
|
|||||||
throw new TypeError('Middleware option setHeaders must be a function')
|
throw new TypeError('Middleware option setHeaders must be a function')
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init Content-Type overrides
|
// Init Content-Type overrides map if required
|
||||||
if (typeof options.overrideContentTypes === 'object') {
|
if (typeof options.overrideContentTypes === 'object') {
|
||||||
this.contentTypesMaps = new Map()
|
this.contentTypesMaps = new Map()
|
||||||
|
|
||||||
@ -85,23 +83,13 @@ class ServeStatic {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (this.contentTypesMaps.size) {
|
if (this.contentTypesMaps.size) {
|
||||||
this.setContentType = (req, res) => {
|
logger.debug(`Inititated Content-Type overrides map for ${this.contentTypesMaps.size} extension(s).`)
|
||||||
// Do only if accessing files from uploads' root directory (i.e. not thumbs, etc.)
|
|
||||||
if (req.path.indexOf('/', 1) === -1) {
|
|
||||||
const name = req.path.substring(1)
|
|
||||||
const extname = utils.extname(name).substring(1)
|
|
||||||
const contentType = this.contentTypesMaps.get(extname)
|
|
||||||
if (contentType) {
|
|
||||||
res.header('Content-Type', contentType)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
this.contentTypesMaps = undefined
|
this.contentTypesMaps = undefined
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init Content-Disposition store and setHeaders function if required
|
// Init Content-Disposition store if required
|
||||||
if (options.setContentDisposition) {
|
if (options.setContentDisposition) {
|
||||||
this.contentDispositionStore = new SimpleDataStore(
|
this.contentDispositionStore = new SimpleDataStore(
|
||||||
options.contentDispositionOptions || {
|
options.contentDispositionOptions || {
|
||||||
@ -110,32 +98,6 @@ class ServeStatic {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
this.setContentDisposition = async (req, res) => {
|
|
||||||
// Do only if accessing files from uploads' root directory (i.e. not thumbs, etc.)
|
|
||||||
if (req.path.indexOf('/', 1) !== -1) return
|
|
||||||
const name = req.path.substring(1)
|
|
||||||
try {
|
|
||||||
let original = this.contentDispositionStore.get(name)
|
|
||||||
if (original === undefined) {
|
|
||||||
this.contentDispositionStore.hold(name)
|
|
||||||
original = await utils.db.table('files')
|
|
||||||
.where('name', name)
|
|
||||||
.select('original')
|
|
||||||
.first()
|
|
||||||
.then(_file => {
|
|
||||||
this.contentDispositionStore.set(name, _file.original)
|
|
||||||
return _file.original
|
|
||||||
})
|
|
||||||
}
|
|
||||||
if (original) {
|
|
||||||
res.header('Content-Disposition', contentDisposition(original, { type: 'inline' }))
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
this.contentDispositionStore.delete(name)
|
|
||||||
logger.error(error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.debug('Inititated SimpleDataStore for Content-Disposition: ' +
|
logger.debug('Inititated SimpleDataStore for Content-Disposition: ' +
|
||||||
`{ limit: ${this.contentDispositionStore.limit}, strategy: "${this.contentDispositionStore.strategy}" }`)
|
`{ limit: ${this.contentDispositionStore.limit}, strategy: "${this.contentDispositionStore.strategy}" }`)
|
||||||
}
|
}
|
||||||
@ -194,8 +156,8 @@ class ServeStatic {
|
|||||||
|
|
||||||
// Only set Content-Disposition on initial GET request
|
// Only set Content-Disposition on initial GET request
|
||||||
// Skip for subsequent requests on non-zero start byte (e.g. streaming)
|
// Skip for subsequent requests on non-zero start byte (e.g. streaming)
|
||||||
if (result.options.start === 0 && this.setContentDisposition) {
|
if (result.options.start === 0 && this.contentDispositionStore) {
|
||||||
await this.setContentDisposition(req, res)
|
await this.#setContentDisposition(req, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result.length === 0) {
|
if (result.length === 0) {
|
||||||
@ -205,10 +167,52 @@ class ServeStatic {
|
|||||||
return this.#stream(req, res, fullPath, result)
|
return this.#stream(req, res, fullPath, result)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async #setContentDisposition (req, res) {
|
||||||
|
// Do only if accessing files from uploads' root directory (i.e. not thumbs, etc.)
|
||||||
|
if (req.path.indexOf('/', 1) !== -1) return
|
||||||
|
|
||||||
|
// Encapsulate within try-catch block because we do not want these to throw
|
||||||
|
const name = req.path.substring(1)
|
||||||
|
try {
|
||||||
|
let original = this.contentDispositionStore.get(name)
|
||||||
|
if (original === undefined) {
|
||||||
|
this.contentDispositionStore.hold(name)
|
||||||
|
original = await utils.db.table('files')
|
||||||
|
.where('name', name)
|
||||||
|
.select('original')
|
||||||
|
.first()
|
||||||
|
.then(_file => {
|
||||||
|
this.contentDispositionStore.set(name, _file.original)
|
||||||
|
return _file.original
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if (original) {
|
||||||
|
res.header('Content-Disposition', contentDisposition(original, { type: 'inline' }))
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
this.contentDispositionStore.delete(name)
|
||||||
|
logger.error(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async #setContentType (req, res) {
|
||||||
|
// Do only if accessing files from uploads' root directory (i.e. not thumbs, etc.)
|
||||||
|
if (req.path.indexOf('/', 1) !== -1) return
|
||||||
|
|
||||||
|
const name = req.path.substring(1)
|
||||||
|
const extname = utils.extname(name).substring(1)
|
||||||
|
const contentType = this.contentTypesMaps.get(extname)
|
||||||
|
if (contentType) {
|
||||||
|
// NOTE: Use lowercase key because the header initially set
|
||||||
|
// with Response.type() is also lowercase
|
||||||
|
res.header('content-type', contentType)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async #setHeaders (req, res, stat) {
|
async #setHeaders (req, res, stat) {
|
||||||
// Override Content-Type if required
|
// Override Content-Type if required
|
||||||
if (this.setContentType) {
|
if (this.contentTypesMaps) {
|
||||||
this.setContentType(req, res)
|
this.#setContentType(req, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Always do external setHeaders function first,
|
// Always do external setHeaders function first,
|
||||||
|
Loading…
Reference in New Issue
Block a user