Skip to content

Instantly share code, notes, and snippets.

@hefangshi
Created April 21, 2015 08:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hefangshi/b864c03b35f18761ed7e to your computer and use it in GitHub Desktop.
Save hefangshi/b864c03b35f18761ed7e to your computer and use it in GitHub Desktop.
var request = require('request');
var http = require('http');
var cacheDir = __dirname + '/fileCache';
var fs = require('fs-extra');
var url = require('url');
var path = require('path');
var mime = require('mime');
mime.default_type = -1;
var server = http.createServer(function (req, resp) {
var urlparse = url.parse(req.url);
var modTime = req.headers['If-Modified-Since'] || req.headers['if-modified-since'];
if (urlparse.pathname === '/cleanCache') {
cleanAllCache(function () {
resp.writeHead(200);
resp.end('ok');
});
return;
}
if (urlparse.pathname.lastIndexOf('/') !== urlparse.pathname.length - 1) {
var lastPath = urlparse.pathname.split('/').pop();
var a = mime.lookup(lastPath);
console.log(lastPath, a);
if (a === -1) {
resp.writeHead(302, {
'Location': urlparse.pathname + '/'
});
resp.end();
return;
}
}
checkMod(urlparse.pathname, modTime, function (hasMod) {
if (!hasMod) {
resp.writeHead(304);
resp.end();
return;
}
getCache(urlparse.pathname, function (err, stream) {
if (err) {
var content = [];
var x = request({
url: 'http://fex-team.github.io' + urlparse.pathname,
method: req.method,
qs: urlparse.query
}, function (error, response, body) {
if (error) {
resp.statusCode = 500;
resp.end('remote fetch failed');
return;
}
//console.log(urlparse.pathname, response.statusCode);
if (response.statusCode === 200) {
setCache(urlparse.pathname, Buffer.concat(content), function (err) {
err && console.log('set cache err', err);
});
setCacheHeaders(urlparse.pathname, response.headers, function (err) {
err && console.log('set cache header err', err);
});
}
}).on('error', function (error) {
resp.statusCode = 500;
resp.end('remote fetch failed');
}).on('response', function (response) {
//console.log(urlparse.pathname, response.statusCode);
if (response.statusCode === 200) {
response.on('data', function (data) {
content.push(data);
});
}
});
delete req.headers['If-Modified-Since'];
delete req.headers['if-modified-since'];
delete req.headers.host;
req.pipe(x);
x.pipe(resp);
} else {
getCacheHeaders(urlparse.pathname, function (err, headers) {
if (err) {
cleanCache(urlparse.pathname);
resp.statusCode = 500;
resp.end('cache fetch failed');
return;
}
//console.log(urlparse.pathname, 'pipe cache');
headers['bae_cache'] = 1;
resp.writeHead(200, headers);
stream.pipe(resp);
});
}
});
});
});
server.listen(18080);
function cleanAllCache(cb) {
fs.remove(cacheDir, cb);
}
function cleanCache(url, cb) {
url = fixName(url);
var file = cacheDir + url;
fs.remove(file);
}
function checkMod(url, mod, cb) {
url = fixName(url);
var file = cacheDir + url;
fs.readJson(file + '.headers', function (err, headers) {
if (err) {
cb(true);
return;
}
var modTime = headers['Last-Modified'] || headers['last-modified'];
if (modTime === mod) {
cb(false);
} else {
cb(true);
}
});
}
function getCache(url, cb) {
url = fixName(url);
var file = cacheDir + url;
fs.stat(file, function (err, stats) {
if (err) return cb(true);
if (stats.isDirectory()) {
console.log(file + ' is directory');
cb(true);
} else {
cb(null, fs.createReadStream(file));
}
});
}
function setCache(url, content, cb) {
url = fixName(url);
var file = cacheDir + url;
fs.outputFile(file, content, cb);
}
function setCacheHeaders(url, headers, cb) {
url = fixName(url);
var file = cacheDir + url;
fs.outputJson(file + '.headers', headers, cb);
}
function getCacheHeaders(url, cb) {
url = fixName(url);
var file = cacheDir + url;
fs.readJson(file + '.headers', cb);
}
function fixName(url) {
if (url.lastIndexOf('/') === url.length - 1) {
return url + path.sep + 'index.html';
} else {
return url;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment