From 019ec2b990bf7caaed044087f4bd4fb257fda75a Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Tue, 24 Oct 2017 16:04:44 -0600 Subject: [PATCH] add option to serve directories --- README.md | 13 +++++++- lib/modules/http.js | 80 ++++++++++++++++++++++++++++++++++++--------- 2 files changed, 77 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 277f941..c2d41fe 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/lib/modules/http.js b/lib/modules/http.js index 636b6bc..738cdf0 100644 --- a/lib/modules/http.js +++ b/lib/modules/http.js @@ -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