Commits

Magnus Hoff committed 991ce7e

Added DirectoryResource and updated FileLookup to be able to serve out directory listings and in any case not crash on directory urls. Thanks, Michael Mortensen.

Comments (0)

Files changed (5)

directoryresource.js

+var fs = require('fs');
+var verifyNew = require('./util').verifyNew;
+var Resource = require('./resource').Resource;
+
+
+function DirectoryResource(fullpath) {
+    verifyNew(this, this.constructor.name);
+	Resource.call(this);
+
+	this.http_GET = function(req, res) {
+		if (req.url.slice(-1) !== '/') {
+			res.writeHead(500, {'Content-Type': 'text/plain'});
+			res.end("DirectoryResource served from URL without trailing /");
+			return;
+		}
+
+		fs.readdir(fullpath, function(err, files) {
+			if (err) {
+				res.writeHead(500, {'Content-Type': 'text/plain'});
+				res.end('Failed to list directory.');
+			} else {
+				res.writeHead(200, {'Content-Type': 'text/html'});
+				res.write('<!DOCTYPE html>\n<html><body><ul>');
+				files.forEach(function (relpath, index) {
+					res.write('<li><a href="'+relpath+'">'+relpath+'</a></li>');
+				});
+				res.end('</ul></body></html>');
+			}
+		});
+	};
+}
+
+
+exports.DirectoryResource = DirectoryResource;

example-directory.js

 
 var resource_tree = require("./resource-tree");
 
-resource_tree.createServer(new resource_tree.FileLookup(".")).listen(8080);
+// To enable naive directory listing:
+var directoryResourceFactory = function (fullpath) { return new resource_tree.DirectoryResource(fullpath); };
+
+resource_tree.createServer(new resource_tree.FileLookup(".", directoryResourceFactory)).listen(8080);
 
 console.log("Now you can GET everything in the current directory under http://127.0.0.1:8080/\n");
 
 console.log("For example:");
+console.log("  * http://127.0.0.1:8080/");
 console.log("  * http://127.0.0.1:8080/example-directory.js");
 console.log("  * http://127.0.0.1:8080/README.md");
 var fs = require('fs');
 var verifyNew = require('./util').verifyNew;
 var Lookup = require('./lookup').Lookup;
+var DirectoryResource = require('./directoryresource').DirectoryResource;
 var FileResource = require('./fileresource').FileResource;
+var redirect = require('./redirectresource');
 
 
-function FileLookup(root) {
+function FileLookup(root, directoryResourceFactory, fileResourceFactory) {
     verifyNew(this, this.constructor.name);
     Lookup.call(this);
 
+    directoryResourceFactory = directoryResourceFactory || function (fullpath) { return null; };
+    fileResourceFactory = fileResourceFactory || function (fullpath) { return new FileResource(fullpath); };
+
     this.lookup = function(reqpath, callback) {
+        if (reqpath.split('/').indexOf('..') !== -1) {
+            callback(null);
+            return;
+        }
+
         var fullpath = path.join(root, reqpath);
+
         fs.exists(fullpath, function(exists) {
             if (exists) {
-                callback(new FileResource(fullpath));
+                fs.stat(fullpath, function(err, stats) {
+                    if (stats.isDirectory()) {
+                        if (reqpath.slice(-1) === '/') {
+                            callback(directoryResourceFactory(fullpath));
+                        } else {
+                            var targetUrl = reqpath.slice(reqpath.lastIndexOf('/') + 1) + '/';
+                            callback(new redirect.RedirectResource(redirect.TEMPORARY_REDIRECT, targetUrl));
+                        }
+                    } else {
+                        callback(fileResourceFactory(fullpath));
+                    }
+                });
             } else {
                 callback(null);
             }

permanentredirectresource.js

 var verifyNew = require('./util').verifyNew;
-var RedirectResource = require('./redirectresource').RedirectResource;
+var redirect = require('./redirectresource');
 
 
 function PermanentRedirectResource(relativeTargetUrl) {
     verifyNew(this, this.constructor.name);
-    RedirectResource.call(this, RedirectResource.MOVED_PERMANENTLY, relativeTargetUrl);
+    redirect.RedirectResource.call(this, redirect.RedirectResource.MOVED_PERMANENTLY, relativeTargetUrl);
 
     console.log("DEPRECATED: PermanentRedirectResource is deprecated in favor of " +
         "'new RedirectResource(RedirectResource.MOVED_PERMANENTLY, targetUrl)'");
 }
-PermanentRedirectResource.prototype = new RedirectResource();
+PermanentRedirectResource.prototype = new redirect.RedirectResource();
 PermanentRedirectResource.constructor = PermanentRedirectResource;
 
 
 exports.FileLookup = require('./filelookup').FileLookup;
 exports.DirectLookup = require('./directlookup').DirectLookup;
 exports.OneLevelLookup = require('./onelevellookup').OneLevelLookup;
+exports.SerialLookup = require('./seriallookup').SerialLookup;
 
 exports.Resource = require('./resource').Resource;
 exports.FileResource = require('./fileresource').FileResource;
+exports.DirectoryResource = require('./directoryresource').DirectoryResource;
+exports.RedirectResource = require('./redirectresource').RedirectResource;
 exports.PermanentRedirectResource = require('./permanentredirectresource').PermanentRedirectResource;
 
 exports.handleRequest = handleRequest;