UNPKG

cluster-service

Version:

Turns your single process code into a fault-resilient multi-process service with built-in REST & CLI support

174 lines (152 loc) 4.1 kB
var cservice = require("../cluster-service"), util = require("util"), http = require("http"), https = require("https"), querystring = require("querystring"), control = require("./control"), options = null, server = null; exports.init = function(o, cb) { options = o; if (options.ssl) { // HTTPS server = cservice.locals.http = https.createServer(options.ssl, processRequest) ; } else { // HTTP server = cservice.locals.http = http.createServer(processRequest) ; } server.on("error", cb); server.listen(options.port, options.host, cb); }; exports.close = function() { try { server.close(); } catch (ex) { } }; function processRequest(req, res) { var qsIdx, qs, question; try { cservice.log( "API: " + req.url.replace(/accessKey=.*/i, "accessKey={ACCESS_KEY}").data ); if (req.url.indexOf("/cli?") !== 0) { res.writeHead(404); res.end("Page Not Found"); return; } if (req.method !== "POST" && cservice.options.allowHttpGet !== true) { res.writeHead(405); res.end("Method Not Allowed"); return; } qsIdx = req.url.indexOf("?"); qs = querystring.parse(req.url.substr(qsIdx + 1)); if (!qs.accessKey || qs.accessKey !== options.accessKey) { res.writeHead(401); res.end("Not authorized"); return; } question = qs.cmd || ""; req.on('data', function (chunk) { question += chunk; }); req.on('end', function () { onCommand(req, res, question, qs.accessKey); }); } catch (ex) { cservice.error( "Woops, an ERROR!".error, util.inspect(ex, {depth: null}), util.inspect(ex.stack || new Error().stack, {depth: null}) ); } } function onCommand(req, res, question, accessKey) { var args = require("./util").getArgsFromQuestion(question, " "); var controlLevel; var isAuthorized; args = [args[0], function(err, result) { onCallback(req, res, err, result); }].concat(args.slice(1)); if (!cservice.locals.events[args[0]]) { cservice.error("Command " + (args[0] + "").cyan + " not found".error); res.writeHead(404); res.end("Not found. Try /help"); return; } controlLevel = control.levels.remote; if (req.connection.remoteAddress === "127.0.0.1") { controlLevel = control.levels.local; } isAuthorized = control.authorize(args[0], controlLevel, accessKey); if (!isAuthorized) { res.writeHead(401); res.end("Not authorized to execute '" + args[0] + "' remotely"); return; } try { cservice.trigger.apply(null, args); } catch (ex) { res.writeHead(400); res.end(JSON.stringify( { ex: ex, stack: ex.stack || new Error().stack, more: "Error. Try /help" } )); } } function onCallback(req, res, err, result) { var body; try { delete cservice.locals.reason; if (err) { // should do nothing if response already sent res.writeHead(400); res.end(err); } else { if (result) { try { body = JSON.stringify(result, function(key, val) { if (key[0] === "_") { return undefined; } else { return val; } }); res.writeHead( 200, { "Content-Type": "text/json; charset=UTF-8", "Content-Length": Buffer.byteLength(body) } ); res.end(body); } catch (ex) { err = util.inspect(ex, {depth: null}); res.writeHead(400); res.end(JSON.stringify({error: err})); cservice.error( "Woops, an ERROR!".error, err, util.inspect(ex.stack || new Error().stack, {depth: null}) ); } } else { res.writeHead(200); res.end("No data"); } } } catch (ex) { cservice.error( "Woops, an ERROR!".error, util.inspect(ex, {depth: null}), util.inspect(ex.stack || new Error().stack, {depth: null}) ); } }