├── .gitignore ├── Procfile ├── package.json └── server.js /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules -------------------------------------------------------------------------------- /Procfile: -------------------------------------------------------------------------------- 1 | web: node server.js -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "wiki-proxy", 3 | "version": "0.0.0", 4 | "private": true, 5 | "dependencies": { 6 | "lru-cache": "~2.5.0" 7 | }, 8 | "engines": { 9 | "node": "0.10.x" 10 | } 11 | } -------------------------------------------------------------------------------- /server.js: -------------------------------------------------------------------------------- 1 | var http = require("http"); 2 | var https = require("https"); 3 | var LRU = require("lru-cache"); 4 | 5 | var port = process.env.PORT || 3000; 6 | 7 | var cache = LRU({ 8 | max: 1024 * 1024 * 5, // 10MB 9 | length: function(n) { return typeof n === "number" ? 4 : n.length }, 10 | maxAge: 1000 * 60 * 5 // 5m 11 | }); 12 | 13 | http.createServer(function (req, res) { 14 | var path = req.url; 15 | if(path.indexOf("..") >= 0) return res.end(""); 16 | var cacheEntry = cache.get(path); 17 | res.statusCode = 200; 18 | res.setHeader("Content-Type", "text/plain"); 19 | res.setHeader("Access-Control-Allow-Origin", "*"); 20 | res.setHeader("Access-Control-Allow-Methods", "GET"); 21 | res.setHeader("Access-Control-Max-Age", "86400"); 22 | res.setHeader("Cache-Control", "max-age=300, public"); 23 | if(cacheEntry) { 24 | res.setHeader("X-Was-Cached", "Yes"); 25 | if(typeof cacheEntry === "number") { 26 | res.statusCode = cacheEntry; 27 | res.end(cacheEntry + " Cached"); 28 | } else { 29 | res.end(cacheEntry); 30 | } 31 | return; 32 | } 33 | console.log("Downloading request to " + path); 34 | https.get("https://raw.githubusercontent.com/wiki" + path + ".md", function(rawRes) { 35 | if(rawRes.statusCode === 200) { 36 | var result = []; 37 | rawRes.on("data", function(d) { result.push(d); }); 38 | rawRes.on("end", function() { 39 | result = Buffer.concat(result); 40 | cache.set(path, result); 41 | }); 42 | rawRes.pipe(res); 43 | } else { 44 | res.statusCode = rawRes.statusCode; 45 | cache.set(path, rawRes.statusCode); 46 | rawRes.pipe(res); 47 | } 48 | }).on("error", function(err) { 49 | try { 50 | res.statusCode = 500; 51 | cache.set(path, 500); 52 | res.end(); 53 | } catch(e) { 54 | console.error(e); 55 | } 56 | }); 57 | }).listen(port, function() { 58 | console.log('Server running at ' + port); 59 | }); 60 | --------------------------------------------------------------------------------