happner
Version:
distributed application engine with evented storage and mesh services
195 lines (157 loc) • 4.83 kB
JavaScript
var PORT = 55000
, SPLASH = __dirname + '/index.htm'
, LOADER_PATH = {match: new RegExp('^/app'), path: __dirname + '/app'}
, PROXY = {}
, __loadProgress = 0
, __progressLog = []
, __messageLog = []
, __config = {}
, __connections = {}
, __listening = false
, http = require('http')
, httpRequest = require('request')
, path = require('path')
;
function LoaderProgress(config) {
if (!config)
config = {};
if (config.port)
PORT = config.port;
if (config.proxy) {
PROXY.target = config.proxy;
}
if (config.loaderPath) {
LOADER_PATH = config.loaderPath;
}
if (!config.splash)
config.splash = __dirname + '/index.htm';
SPLASH = config.splash;
__progressLog = [];
__messageLog = [];
__config = config;
__connections = {};
__listening = false;
}
function _catchStreamError(err, res) {
res.writeHead(404, {"Content-Type": "text/plain"});
res.write("404 Not Found: " + err + "\n");
res.end();
return;
}
function _matchPathRoute(url) {
if (!url.match(LOADER_PATH.match)) return false;
var targetFilename = url.replace(LOADER_PATH.match, LOADER_PATH.path);
return path.normalize(targetFilename);
};
LoaderProgress.prototype.listen = function (callback) {
this.__progressServer = http.createServer(function (req, res) {
if (req.url.indexOf('/loader.htm') == 0) {
var fileStream = require('fs').createReadStream(SPLASH);
fileStream.on('error', function (err) {
_catchStreamError(err, res)
});
return fileStream.pipe(res);
}
var targetFile = _matchPathRoute(req.url);
if (targetFile) {
var fileStream = require('fs').createReadStream(targetFile);
fileStream.on('error', function (err) {
_catchStreamError(err, res)
});
return fileStream.pipe(res);
}
if (req.url == '/log') {
res.setHeader('Content-type', 'application/json');
res.write(JSON.stringify(__messageLog));
return res.end();
}
if (req.url == '/log.json') {
res.setHeader('Content-disposition', 'attachment; filename=log.json');
res.setHeader('Content-type', 'application/json');
res.write(JSON.stringify(__messageLog), 'binary');
return res.end();
}
if (req.url == '/progress') {
res.write(JSON.stringify(__progressLog));
return res.end();
}
if (req.url == '/config') {
res.write(JSON.stringify(__config));
return res.end();
}
if (req.url == '/ping') {
res.write(JSON.stringify({"happner-loader %": __loadProgress}));
return res.end();
}
// By Default we do not want to proxy, so we relocated to the loader
if (PROXY.target === null || PROXY.target === undefined) {
var fileStream = require('fs').createReadStream(SPLASH);
fileStream.on('error', function (err) {
_catchStreamError(err, res)
});
return fileStream.pipe(res);
}
// Try Proxy to the target url
var request = httpRequest({
url: PROXY.target + req.url,
method: req.method,
headers: req.headers,
followRedirect: false
});
req.pipe(request, {end: true})
.on('error', function (err) {
res.writeHead(502);
res.write("Loader Proxy Error:" + err.code);
return res.end();
})
.on('response', function (response) {
if (response.statusCode == 404) {
// If the Proxy server doesn't know about the page, serve
// up the splash screen.
var fileStream = require('fs').createReadStream(SPLASH);
fileStream.on('error', function (err) {
_catchStreamError(err, res)
});
return fileStream.pipe(res);
} else {
res.writeHead(response.statusCode, response.headers);
response.pipe(res)
}
})
});
this.__progressServer.on('connection', function (conn) {
var key = conn.remoteAddress + ':' + conn.remotePort;
__connections[key] = conn;
conn.on('close', function () {
delete __connections[key];
});
});
this.__progressServer.on('listening', function () {
__listening = true;
callback();
});
this.__progressServer.on('error', function (e) {
callback(e);
});
try {
this.__progressServer.listen(PORT);
} catch (e) {
callback(e);
}
};
LoaderProgress.prototype.progress = function (log, progress, error) {
__loadProgress = progress;
__progressLog.push({"log": log, "progress": progress, error: error});
};
LoaderProgress.prototype.log = function (message) {
__messageLog.push(message);
};
LoaderProgress.prototype.stop = function () {
if (__listening) {
for (var key in __connections) {
__connections[key].destroy();
}
this.__progressServer.close();
}
};
module.exports = LoaderProgress;