serve-static
serve-static copied to clipboard
Extensions vs Directory
When we have a directory named like a file, extensions should win over redirect. Let's assume this listing:
/news.html
/news/latest.html
/news/index.html
and we set the extensions
options to ['html']
.
Right now /news
is redirected to /news/
and serves /news/index.html
But it should serve /news.html
– only if that file is missing, it should redirect to the directory. Whereas /news/
should always go for the directory (index).
I achieved this by changing the sendFile
method like follows, but there are probably better ways to achieve the same.
SendStream.prototype.sendFile = function sendFile (path) {
var i = 0
var self = this
var onExtensionsFailed
debug('stat "%s"', path)
fs.stat(path, function onstat (err, stat) {
if (err && err.code === 'ENOENT' && !extname(path) && path[path.length - 1] !== sep) {
// not found, check extensions
return next(err)
}
if (err) return self.onStatError(err)
if (stat.isDirectory()) {
onExtensionsFailed = function() {
self.redirect(path)
}
if (self._extensions.length > 0 && path[path.length - 1] !== sep) {
return next()
} else {
return self.redirect(path)
}
}
self.emit('file', path, stat)
self.send(path, stat)
})
function next (err) {
if (self._extensions.length <= i) {
if (onExtensionsFailed) {
return onExtensionsFailed()
}
return err
? self.onStatError(err)
: self.error(404)
}
var p = path + '.' + self._extensions[i++]
debug('stat "%s"', p)
fs.stat(p, function (err, stat) {
if (err) return next(err)
if (stat.isDirectory()) return next()
self.emit('file', p, stat)
self.send(p, stat)
})
}
}
Does this make sense? (I am by the way trying to achieve the same kind of handling like Netlify does when serving static files).
Yes I face the same issue when wanting to prerender
|--posts
|----posts1.html
|----posts2.html
|--posts.html
But I digress, the solutions are always there, either use index.html
folders (gruesome), or in the next rule check the posts.html manually... or route the posts differently. But I guess it would have been a blessing for it to work out of the box with
{extensions: ['html'], redirect: false }