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