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.

  • Participants
  • Parent commits dc7b173

Comments (0)

Files changed (5)

File 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;

File 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");

File filelookup.js

 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);
             }

File 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;
 
 

File resource-tree.js

 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;