Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Added AutoIndex option when creating a Server instance #22

Closed
wants to merge 2 commits into from

4 participants

@Marak

Alexis -

I added the basic ability to create directory html listings of the current directories contents if AutoIndex is enabled and a request 404s.

Everything should already be working, so feel free to pull if you want.

  • Marak
@Marak

Any comments on this one @cloudhead?

Could I get a go or no go on this feature? I'd be glad to rewrite it if you hate my implementation, but if you don't want this feature in the lib I'm gonna have to continue to vendor a shit ton of node-statics, and I'm just sooooo lazy.

:-D

@Marak

Ping

@Sigfried

I don't get the slang above ("vendor a shit ton of node-statics"?), but I want this fix and I'm too dumb to understand how to get it since it doesn't seem to be in the node-static that I installed.

@phstc
Collaborator

Could you guys update the pull request? Unfortunately, It can't be automatically merged, since it is too old.

This pull request cannot be automatically merged.

Now, there is a test suite on the project, could you also add tests?

Cheers

@phstc phstc closed this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Apr 4, 2011
  1. @Marak
Commits on Jun 15, 2011
  1. @AvianFlu
This page is out of date. Refresh to see the latest.
Showing with 59 additions and 10 deletions.
  1. +9 −1 README.md
  2. +50 −9 lib/node-static.js
View
10 README.md
@@ -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`
View
59 lib/node-static.js
@@ -1,5 +1,4 @@
var fs = require('fs'),
- sys = require('sys'),
events = require('events'),
buffer = require('buffer'),
http = require('http'),
@@ -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') {
@@ -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);
@@ -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' });
@@ -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] }
@@ -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,
@@ -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,
@@ -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();
Something went wrong with that request. Please try again.