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 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/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 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: Example config:
@ -455,7 +467,6 @@ TODO
* http - nowww module * http - nowww module
* http - Allow match styles of `www.*`, `*`, and `*.example.com` equally * http - Allow match styles of `www.*`, `*`, and `*.example.com` equally
* http - redirect based on domain name (not just path) * 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 - 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 * tcp - if destination host is omitted default to localhost, if dst port is missing, default to src
* sys - handle SIGHUP * sys - handle SIGHUP

View File

@ -354,30 +354,76 @@ module.exports.create = function (deps, conf, greenlockMiddleware) {
var staticServer; var staticServer;
var staticHandlers = {}; var staticHandlers = {};
function serveStatic(req, res) { var indexHandlers = {};
function serveStatic(modOpts, req, res) {
var rootDir = req.connection.rootDir; var rootDir = req.connection.rootDir;
if (!staticHandlers[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) { staticHandlers[rootDir](req, res, function (err) {
if (err) { function doFinal() {
res.statusCode = err.statusCode; if (err) {
} else { res.statusCode = err.statusCode;
res.statusCode = 404; } else {
} res.statusCode = 404;
res.setHeader('Content-Type', 'text/html'); }
res.setHeader('Content-Type', 'text/html');
if (res.statusCode === 404) { if (res.statusCode === 404) {
res.end('File Not Found'); res.end('File Not Found');
} else { } else {
res.end(require('http').STATUS_CODES[res.statusCode]); 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) { function checkStatic(modOpts, conn, opts, headers) {
var rootDir = mod.root.replace(':hostname', separatePort(headers.host).host); var rootDir = modOpts.root.replace(':hostname', separatePort(headers.host).host);
return statAsync(rootDir) return statAsync(rootDir)
.then(function (stats) { .then(function (stats) {
if (!stats || !stats.isDirectory()) { if (!stats || !stats.isDirectory()) {
@ -385,7 +431,9 @@ module.exports.create = function (deps, conf, greenlockMiddleware) {
} }
if (!staticServer) { if (!staticServer) {
staticServer = require('http').createServer(serveStatic); staticServer = require('http').createServer(function (req, res) {
serveStatic(modOpts, req, res);
});
} }
conn.rootDir = rootDir; conn.rootDir = rootDir;
return emitConnection(staticServer, conn, opts); 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 = { var moduleChecks = {
proxy: checkProxy proxy: checkProxy
, redirect: checkRedirect , redirect: checkRedirect