add option to serve directories

This commit is contained in:
AJ ONeal 2017-10-24 16:04:44 -06:00
parent 5e48a2ed5e
commit 019ec2b990
2 changed files with 77 additions and 16 deletions

View File

@ -106,6 +106,18 @@ root The path to serve as a string.
The template variable `:hostname` represents the HTTP Host header without port information
ex: `root: /srv/www/example.com` would load the example.com folder for any domain listed
ex: `root: /srv/www/:hostname` would load `/srv/www/example.com` if so indicated by the Host header
index Set to `false` to disable the default behavior of loading `index.html` in directories
ex: `false`
dotfiles Set to `allow` to load dotfiles rather than ignoring them
ex: `"allow"`
redirect Set to `false` to disable the default behavior of ensuring that directory paths end in '/'
ex: `false`
indexes An array of directories which should be have indexes served rather than blocked
ex: `[ '/' ]` will allow all directories indexes to be served
```
Example config:
@ -455,7 +467,6 @@ TODO
* http - nowww module
* http - Allow match styles of `www.*`, `*`, and `*.example.com` equally
* http - redirect based on domain name (not just path)
* http.static - indexes: true
* tcp - bind should be able to specify localhost, uniquelocal, private, or ip
* tcp - if destination host is omitted default to localhost, if dst port is missing, default to src
* sys - handle SIGHUP

View File

@ -354,30 +354,76 @@ module.exports.create = function (deps, conf, greenlockMiddleware) {
var staticServer;
var staticHandlers = {};
function serveStatic(req, res) {
var indexHandlers = {};
function serveStatic(modOpts, req, res) {
var rootDir = req.connection.rootDir;
if (!staticHandlers[rootDir]) {
staticHandlers[rootDir] = require('express').static(rootDir, { fallthrough: false });
staticHandlers[rootDir] = require('express').static(rootDir, {
dotfiles: modOpts.dotfiles
, fallthrough: false
, redirect: modOpts.redirect
, index: modOpts.index
});
}
staticHandlers[rootDir](req, res, function (err) {
if (err) {
res.statusCode = err.statusCode;
} else {
res.statusCode = 404;
}
res.setHeader('Content-Type', 'text/html');
function doFinal() {
if (err) {
res.statusCode = err.statusCode;
} else {
res.statusCode = 404;
}
res.setHeader('Content-Type', 'text/html');
if (res.statusCode === 404) {
res.end('File Not Found');
} else {
res.end(require('http').STATUS_CODES[res.statusCode]);
if (res.statusCode === 404) {
res.end('File Not Found');
} else {
res.end(require('http').STATUS_CODES[res.statusCode]);
}
}
var handlerHandle = rootDir
+ (modOpts.hidden||'')
+ (modOpts.icons||'')
+ (modOpts.stylesheet||'')
+ (modOpts.template||'')
+ (modOpts.view||'')
;
if (!modOpts.indexes || ('*' !== modOpts.indexes[0] && !modOpts.indexes.some(function (pathname) {
if (req.url === pathname) {
return true;
}
if (0 === req.url.replace(/\/?$/, '/').indexOf(pathname.replace(/\/?$/, '/'))) {
return true;
}
}))) {
doFinal();
return;
}
if (!indexHandlers[handlerHandle]) {
// https://www.npmjs.com/package/serve-index
indexHandlers[handlerHandle] = require('serve-index')(rootDir, {
hidden: modOpts.hidden
, icons: modOpts.icons
, stylesheet: modOpts.stylesheet
, template: modOpts.template
, view: modOpts.view
});
}
indexHandlers[handlerHandle](req, res, function (_err) {
err = _err || err;
doFinal();
});
});
}
function checkStatic(mod, conn, opts, headers) {
var rootDir = mod.root.replace(':hostname', separatePort(headers.host).host);
function checkStatic(modOpts, conn, opts, headers) {
var rootDir = modOpts.root.replace(':hostname', separatePort(headers.host).host);
return statAsync(rootDir)
.then(function (stats) {
if (!stats || !stats.isDirectory()) {
@ -385,7 +431,9 @@ module.exports.create = function (deps, conf, greenlockMiddleware) {
}
if (!staticServer) {
staticServer = require('http').createServer(serveStatic);
staticServer = require('http').createServer(function (req, res) {
serveStatic(modOpts, req, res);
});
}
conn.rootDir = rootDir;
return emitConnection(staticServer, conn, opts);
@ -399,6 +447,8 @@ module.exports.create = function (deps, conf, greenlockMiddleware) {
;
}
// The function signature is as follows
// function module(moduleOptions, tcpConnection, connectionOptions, headers) { ... }
var moduleChecks = {
proxy: checkProxy
, redirect: checkRedirect