8a7dca251eb82398749e9e10a27e69b27afc5cb2
[nodejs-repoproxy.git] / lib / router.js
1 var url = require("url");
2 var fs = require("fs");
3 var cache = require("./cache.js");
4 var path = require("path");
5
6 exports.routeRequest = function(req, res) {
7         // first, unify the request
8         var thisQuery = unifyRequest(req, res, function(unified) {
9                 if(unified.requestFor == "/favicon.ico") {
10                         unified.b.writeHead(404, {"Content-Type": "text/plain"});
11                         unified.b.write("404 Not Found\n");
12                 } else if(unified.exists) {
13                         if(unified.isFile) {
14                                 cache.serviceFile(unified);
15                         } else if(unified.isDirectory) {
16                                 cache.serviceDirectory(unified);
17                         } else {
18                                 console.log("ERROR: something went majorly wrong with something, ", unified);
19                         }
20                 } else {
21                         // it doesnt exist yet, so we send it to the cache service
22                         console.log("file doesnt exist, upstream we go: ", unified);
23                         cache.upstreamRequest(unified, function(err) {
24                                 if(err == null) {
25                                         cache.watchAndService(unfied);
26                                 } // if upstream sends anything other then a 200, cache.upstreamRequest will handle it (i.e. 302, 404, etc)
27                         });
28                 }
29         });
30 }
31
32 function unifyRequest(req, res, callback, testing) {
33         var unified = new Object();
34         var originalurl = url.parse(req.url);
35         
36         // create the base unified object
37         unified.a = req;
38         unified.b = res;
39
40         // create the request url
41         // remove /pub if it exists
42         unified.requestFor = originalurl.pathname.replace(/^\/pub/, "");
43         unified.originalReq = originalurl.pathname;
44         
45         // create the full file path by spanning the cachedir
46         unified.fullFilePath = (global.repoproxy.cacheDir + "/" + originalurl.pathname.replace(/^\/pub/, "")).replace(/\/+/g, "/");
47         
48         // determine the topPath, subpath etc.
49         var spl = unified.requestFor.split("/");
50         unified.topPath = spl[1];
51         unified.topFullPath = (global.repoproxy.cacheDir + "/" + spl[1]).replace(/\/+/g, "/");
52         unified.subPath = "";
53         if(spl.length > 2) {
54                 for(var i=2; i < spl.length; i++) {
55                         if(unified.subPath == "") unified.subPath = spl[i];
56                         else unified.subPath += "/" + spl[i];
57                 }
58         } else {
59                 unified.subPath = null;
60         }
61         
62         // determine if the request is for a directory
63         if(unified.requestFor.match(/\/$/) != null) {
64                 unified.isDirectoryRequest = true;
65                 unified.fullPathDirName = unified.fullFilePath;
66                 unified.subPathDirName = unified.subPath;
67         } else {
68                 unified.isDirectoryRequest = false;
69                 unified.fullPathDirName = path.dirname(unified.fullFilePath);
70                 unified.subPathDirName = path.dirname(unified.subPath);
71         }
72         
73         
74         fs.stat(unified.fullFilePath, function(err, stats) {
75                 if(err == null) {
76                         unified.exists = true;
77                         if(stats.isDirectory() && !unified.isDirectoryRequest) {
78                                 //send a 302 and call it a day
79                                 res.writeHead("302", { 'Location': unified.originalReq+"/" });
80                                 res.end();
81                                 
82                                 // TODO: remove this after testing
83                                 if(testing) callback(null);
84                                 return 302;
85                         }
86                         
87                         if(stats.isDirectory()) {
88                                 unified.isDirectory = true;
89                                 unified.isFile = false;
90                         } else if(stats.isFile()) {
91                                 unified.isDirectory = false;
92                                 unified.isFile = true;                          
93                         } else {
94                                 unified.isDirectory = false;
95                                 unified.isFile = false;
96                         }
97                 } else {
98                         unified.exists = false;
99                 }
100                 
101                 callback(unified);
102         });
103         
104         return 0;
105 }
106
107 exports.unifyRequest = unifyRequest;