Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added AutoIndex option when creating a Server instance #22

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
10 changes: 9 additions & 1 deletion README.md
Expand Up @@ -137,5 +137,13 @@ Sets response headers.

example: `{ 'X-Hello': 'World!' }`

> defaults to `{}`
> Defaults to `{}`

#### `AutoIndex` #

Automatically generates an html index page for directory listings

example: `{ 'AutoIndex': true }`

> Defaults to `false`

59 changes: 50 additions & 9 deletions lib/node-static.js
@@ -1,5 +1,4 @@
var fs = require('fs'),
sys = require('sys'),
events = require('events'),
buffer = require('buffer'),
http = require('http'),
Expand All @@ -26,6 +25,7 @@ this.Server = function (root, options) {

this.defaultHeaders = {};
this.options.headers = this.options.headers || {};
this.options.AutoIndex = this.options.AutoIndex || false;

if ('cache' in this.options) {
if (typeof(this.options.cache) === 'number') {
Expand Down Expand Up @@ -59,7 +59,13 @@ this.Server.prototype.serveDir = function (pathname, req, res, finish) {
} else {
// Stream a directory of files as a single file.
fs.readFile(path.join(pathname, 'index.json'), function (e, contents) {
if (e) { return finish(404, {}) }
if (e) {
if (that.options.AutoIndex) {
return that.serveAutoIndex(pathname, res, req, finish);
} else {
return finish(404, {});
}
}
var index = JSON.parse(contents);
exports.indexStore[pathname] = index;
streamFiles(index.files);
Expand Down Expand Up @@ -125,7 +131,6 @@ this.Server.prototype.servePath = function (pathname, status, headers, req, res,
promise = new(events.EventEmitter);

pathname = this.normalize(pathname);

// Only allow GET and HEAD requests
if (req.method !== 'GET' && req.method !== 'HEAD') {
finish(405, { 'Allow': 'GET, HEAD' });
Expand Down Expand Up @@ -179,7 +184,6 @@ this.Server.prototype.respond = function (pathname, status, _headers, files, sta
var mtime = Date.parse(stat.mtime),
key = pathname || files[0],
headers = {};

// Copy default headers
for (var k in this.options.headers) { headers[k] = this.options.headers[k] }

Expand Down Expand Up @@ -212,7 +216,9 @@ this.Server.prototype.respond = function (pathname, status, _headers, files, sta
finish(status, _headers);
} else {
this.stream(pathname, files, new(buffer.Buffer)(stat.size), res, function (e, buffer) {
if (e) { return finish(null, {}) }
if (e) {
return finish(200, {});
}
exports.store[key] = {
stat: stat,
buffer: buffer,
Expand All @@ -223,14 +229,49 @@ this.Server.prototype.respond = function (pathname, status, _headers, files, sta
}
}
};

this.Server.prototype.serveAutoIndex = function (dirPath, res, req, finish) {
var html,
self = this,
newPath;
html = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"\
"http://www.w3.org/TR/html4/loose.dtd">\
<html> \
<head> \
<title>Index of ' + dirPath +'</title> \
</head> \
<body> \
<h1>Index of ' + dirPath + '</h1>';
html += '<table>';
newPath = dirPath.replace(self.root, '');
if (newPath[newPath.length - 1] !== '/') {
newPath += '/';
}
fs.readdir(dirPath, function(err, result) {
if (err) { return finish(404, {})}
result.forEach(function(v, i) {
html += ('<tr><td>' + '<a href="' + newPath + v + '">' + v + '</a></td></tr>');
});
html += '</table>';
html += '\
<address>Node.js ' + process.version + ' <a href="https://github.com/cloudhead/node-static">node-static</a> server running @ ' + req.headers.host + '</address> \
</body></html>';
res.writeHead(200, { "Content-Type": "text/html" });
res.write(html);
res.end();
});
};
this.Server.prototype.stream = function (pathname, files, buffer, res, callback) {
(function streamFile(files, offset) {
var file = files.shift();

if (file) {
// Stream the file to the client
fs.createReadStream(path.join(pathname || '.', file), {
if (file[0] === '/') {
file = '/' + path.join(pathname || '.', file);;
}
else {
file = path.join(pathname || '.', file);
}
fs.createReadStream(file, {
flags: 'r',
encoding: 'binary',
mode: 0666,
Expand All @@ -243,7 +284,7 @@ this.Server.prototype.stream = function (pathname, files, buffer, res, callback)
streamFile(files, offset);
}).addListener('error', function (err) {
callback(err);
sys.error(err);
console.error(err);
});
} else {
res.end();
Expand Down