lots of work on the request pipeline
[nodejs-repoproxy.git] / lib / router.js
index 96ca844..71fddb1 100644 (file)
 var url = require("url");
 var fs = require("fs");
 var cache = require("./cache.js");
+var path = require("path");
 
 exports.routeRequest = function(req, res) {
-       // first, strip a /pub/ off the front if it exists
-       var originalurl = url.parse(req.url);
-       var range = 0;
-               
-       thisurl = originalurl.pathname.replace(/^\/pub/, "");
-       
-       console.log("pathname now: ", thisurl);
-       
-       //if(thisurl.pathname == "") thisurl.pathname = "/";
-       
-       var reqpath = global.repoproxy.cacheDir + "/" + thisurl;
-       
-       console.log("request on '%s'", reqpath);
-
-       // see what we're dealing with
-       fs.stat(reqpath, function(err, stat) {
-               console.log("err is ", err);
-               console.log("stat is ", stat);
-               console.log("fs.stats is ", fs.stats);
-               
-               if(err == null) {
-                       if(stat.isDirectory()) {
-                               if(originalurl.pathname.charAt(originalurl.pathname.length-1) != "/") {
-                                       // redirect to url + "/"
-                                       res.writeHead("302", { "Location": originalurl.pathname+"/" });
-                                       res.end();
-                               } else {
-                                       writeDirectoryListing(reqpath, originalurl.pathname, res);
-                               }
+       // first, unify the request
+       var thisQuery = unifyRequest(req, res, function(unified) {
+               if(unified.exists) {
+                       if(unified.isFile) {
+                               cache.serviceFile(unified);
+                       } else if(unified.isDirectory) {
+                               cache.serviceDirectory(unified);
                        } else {
-                               if(stat.isFile()) {
-                                       cache.serviceFile(reqpath, res, range);
-                               }
+                               console.log("ERROR: something went majorly wrong with something, ", unified);
                        }
                } else {
-                       // go upstream..
-                       cache.serviceFile(reqpath, res, range);
+                       // it doesnt exist yet, so we send it to the cache service
+                       console.log("file doesnt exist, upstream we go: ", unified);
+                       cache.upstreamRequest(unified, function(err) {
+                               if(err == null) {
+                                       cache.watchAndService(unfied);
+                               } // if upstream sends anything other then a 200, cache.upstreamRequest will handle it (i.e. 302, 404, etc)
+                       });
                }
-       });     
+       });
 }
 
-function writeDirectoryListing(reqpath, requesturi, res) {
-       res.write("<html><h1>Directory listing for " + requesturi + "</h1><hr><pre>");
-       if(requesturi != "/") res.write("<a href=\"..\">Parent</a>\n\n");
-       fs.readdir(reqpath, function(err, files) {
-               console.log("doing directory listing on: ", reqpath);
+function unifyRequest(req, res, callback, testing) {
+       var unified = new Object();
+       var originalurl = url.parse(req.url);
+       
+       // create the base unified object
+       unified.a = req;
+       unified.b = res;
+
+       // create the request url
+       // remove /pub if it exists
+       unified.requestFor = originalurl.pathname.replace(/^\/pub/, "");
+       unified.originalReq = originalurl.pathname;
+       
+       // create the full file path by spanning the cachedir
+       unified.fullFilePath = (global.repoproxy.cacheDir + "/" + originalurl.pathname.replace(/^\/pub/, "")).replace(/\/+/g, "/");
+       
+       // determine if the request is for a directory
+       if(unified.requestFor.match(/\/$/) != null) {
+               unified.isDirectoryRequest = true;
+               unified.fullPathDirName = unified.fullFilePath;
+       } else {
+               unified.isDirectoryRequest = false;
+               unified.fullPathDirName = path.dirname(unified.fullFilePath);
+       }
+       
+       // determine the topPath, subpath etc.
+       var spl = unified.requestFor.split("/");
+       unified.topPath = spl[1];
+       unified.subPath = "";
+       if(spl.length > 2) {
+               for(var i=2; i < spl.length; i++) {
+                       if(unified.subPath == "") unified.subPath = spl[i];
+                       else unified.subPath += "/" + spl[i];
+               }
+       } else {
+               unified.subPath = null;
+       }
+       
+       
+       fs.stat(unified.fullFilePath, function(err, stats) {
                if(err == null) {
+                       unified.exists = true;
+                       if(stats.isDirectory() && !unified.isDirectoryRequest) {
+                               //send a 302 and call it a day
+                               res.writeHead("302", { 'Location': unified.originalReq+"/" });
+                               res.end();
+                               
+                               // TODO: remove this after testing
+                               if(testing) callback(null);
+                               return 302;
+                       }
                        
-                       // TODO: make this work asynchronously...
-                       if(files.length == 0) {
-                               res.write("Empty Directory....\b");
+                       if(stats.isDirectory()) {
+                               unified.isDirectory = true;
+                               unified.isFile = false;
+                       } else if(stats.isFile()) {
+                               unified.isDirectory = false;
+                               unified.isFile = true;                          
                        } else {
-                               for(var i=0; i<files.length; i++) {
-                                       // avoiding statSync is too hard for now, will fix later TODO: fix this sync bit
-                                       var stats = fs.statSync(reqpath+"/"+files[i]);
-                                       
-                                       if(stats.isDirectory()) {
-                                               
-                                               res.write("Directory: <a href=\""+files[i]+"/\">"+files[i]+"/</a>\n");
-                                       } else if(stats.isFile()) {
-                                               var padlength = 80 - (files[i].length) - stats.size.toString().length;
-                                               var padding = "";
-                                               if(padlength > 0) {
-                                                       padding = new Array(padlength).join(" ");
-                                               }
-                                               res.write("File:      <a href=\""+files[i]+"\">"+files[i]+"</a>"+padding+stats.size+" bytes\n");
-                                       }
-                               }
+                               unified.isDirectory = false;
+                               unified.isFile = false;
                        }
-                       res.write("<hr></pre>");
-                       res.end();
                } else {
-                       res.write("we have entered bizaro world...\n");
-                       res.write("</pre>");
-                       res.end();
+                       unified.exists = false;
                }
+               
+               callback(unified);
        });
-}
\ No newline at end of file
+       
+       return 0;
+}
+
+exports.unifyRequest = unifyRequest;
\ No newline at end of file