Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Add Spawn Proxy Server

  • Loading branch information...
commit 64fa95d9ec812aaeadfdd43cbe4e5713ea485538 1 parent ebfebca
@groundwater groundwater authored
Showing with 135 additions and 24 deletions.
  1. +7 −5 demo/server.js
  2. +70 −8 index.js
  3. +17 −11 package.json
  4. +41 −0 proxy.js
View
12 demo/server.js
@@ -1,7 +1,8 @@
#!/usr/bin/env node
+var http = require('http');
var env = process.env;
-console.log(env);
+
console.log("Starting Server");
console.log("Listening to Port", env.PORT);
console.log("Listening to Address", env.BIND);
@@ -10,7 +11,8 @@ console.log("Conncting to MySQL '%s' as '%s' with Password '%s'",
env.MYSQL_USER,
env.MYSQL_PASS);
-console.log("Server Active for %d Second",process.argv[2]/1000);
-setTimeout(function(){
- console.log("Server Shutting Down")
-},parseInt(process.argv[2]));
+http.createServer(function(req,res){
+ console.log("Ping");
+ res.write("PONG\n");
+ res.end();
+}).listen(process.env.PORT);
View
78 index.js
@@ -1,7 +1,7 @@
#!/usr/bin/env node
var program = require('commander');
-var colors = require('colors');
+var colors_ = require('colors');
var util = require('util');
var path = require('path');
var prog = require('child_process');
@@ -16,6 +16,7 @@ program.option('-j, --procfile <file>', 'load profile FILE','Procfile');
program.option('-e, --env <file>' ,'use FILE to load environment','.env');
program.option('-p, --port <port>' ,'start indexing ports at number PORT',5000);
program.option('-s, --showenvs' ,'show ENV variables on start',false);
+program.option('-x, --proxy <port>','start a load balancing proxy on PORT');
program.option('-a, --app <name>' ,'export upstart application as NAME','foreman');
program.option('-u, --user <name>' ,'export upstart user as NAME','root');
program.option('-o, --out <dir>' ,'export upstart files to DIR','.');
@@ -25,14 +26,16 @@ var killing = 0;
// Utilities //
-var colors_max = 5;
+var colors_max = 8;
var colors = [
function(x){return x.cyan},
function(x){return x.yellow},
function(x){return x.green},
function(x){return x.magenta},
function(x){return x.blue},
- function(x){return x.white}
+ function(x){return x.white},
+ function(x){return x.red},
+ function(x){return x.grey}
];
function fmt(){
@@ -71,15 +74,15 @@ function log(key,proc,string){
// Foreman Loggers //
function Alert(){
- console.log( fmt.apply(null,arguments).bold.green );
+ console.log( '[OKAY] '.green + fmt.apply(null,arguments).green );
}
function Warn(){
- console.warn( fmt.apply(null,arguments).bold.yellow );
+ console.warn( '[WARN] '.yellow + fmt.apply(null,arguments).yellow );
}
function Error(){
- console.error( fmt.apply(null,arguments).bold.red );
+ console.error( '[FAIL] '.red + fmt.apply(null,arguments).bold.red );
}
// Foreman Event Bus/Emitter //
@@ -88,6 +91,7 @@ var emitter = new events.EventEmitter();
emitter.once('killall',function(){
Error("Killing All Processes");
})
+emitter.setMaxListeners(50);
// Run a Specific Process
// - Key is a Process Name and Number
@@ -180,7 +184,7 @@ function start(procs,requirements,envs){
for(i=0;i<n;i++){
- var color_val = j+k % colors_max;
+ var color_val = (j+k) % colors_max;
if (!procs[key]){
Warn("Required Key '%s' Does Not Exist in Procfile Definition",key);
@@ -276,7 +280,7 @@ function loadEnvs(path){
function parseRequirements(req){
var requirements = {};
req.toString().split(',').forEach(function(item){
- var tup = item.trim().split('=',1);
+ var tup = item.trim().split('=');
var key = tup[0];
var val;
if(tup.length>1){
@@ -315,6 +319,60 @@ function calculatePadding(reqs){
return padding + 10;
}
+function startProxies(reqs,proc){
+
+ if(program.proxy){
+
+ var localhost = 'localhost';
+ var i=0;
+
+ var ports = program.proxy.split(',');
+ for(key in reqs){(function(key){
+
+ var j = i++;
+
+ var port = ports[j];
+
+ if(port<1024 && process.getuid()!=0)
+ return Error('Cannot Bind to Privileged Port %s Without Permission - Try \'sudo\'',port);
+
+ if(!port) return Warn('No Downstream Port Defined for \'%s\' Proxy',key);
+ if(!(key in proc)) return Warn('Proxy Not Started for Undefined Key \'%s\'',key);
+
+ var upstream_size = reqs[key];
+ var upstream_port = program.port + j*100;
+
+ var proxy = prog.fork(__dirname + '/proxy.js',[],{
+ env: {
+ HOST: localhost,
+ PORT: port,
+ UPSTREAM_HOST: localhost,
+ UPSTREAM_PORT: upstream_port,
+ UPSTREAM_SIZE: upstream_size,
+ SUDO_USER: process.env.SUDO_USER
+ }
+ });
+
+ Alert('Starting Proxy Server %s -> %d-%d',
+ port,
+ upstream_port,
+ upstream_port+upstream_size);
+
+ emitter.once('killall',function(){
+ Error('Killing Proxy Server on Port %s',port);
+ proxy.kill();
+ })
+
+ proxy.on('exit',function(){
+ emitter.emit('killall');
+ })
+
+ })(key)}
+
+ }
+
+}
+
// Kill All Child Processes on SIGINT
process.on('SIGINT',function userkill(){
Warn('Interrupted by User');
@@ -342,6 +400,10 @@ program
padding = calculatePadding(reqs);
+ startProxies(reqs,proc);
+
+ if(process.getuid()==0) process.setuid(process.env.SUDO_USER);
+
start(proc,reqs,envs);
});
View
28 package.json
@@ -6,25 +6,31 @@
"main": "index.js",
"author": "Jacob Groundwater",
"license": "BSD",
- "keywords": ["foreman","upstart","commandline","env"],
+ "keywords": [
+ "foreman",
+ "upstart",
+ "commandline",
+ "env"
+ ],
"bin": {
"nf": "index.js"
},
"dependencies": {
"colors": "~0.6.0-1",
"commander": "~1.0.5",
- "mu2": "~0.5.17"
+ "mu2": "~0.5.17",
+ "http-proxy": "~0.8.4"
},
- "repository" : {
- "type" : "git",
- "url" : "https://github.com/NodeFly/node-foreman.git"
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/NodeFly/node-foreman.git"
},
- "bugs": {
- "url" : "https://github.com/NodeFly/node-foreman/issues",
- "email" : "jacob@nodefly.com"
+ "bugs": {
+ "url": "https://github.com/NodeFly/node-foreman/issues",
+ "email": "jacob@nodefly.com"
},
- "engines" : {
- "node" : ">=0.6.9"
+ "engines": {
+ "node": ">=0.6.9"
},
"preferGlobal": true
-}
+}
View
41 proxy.js
@@ -0,0 +1,41 @@
+var http = require('http');
+var htproxy = require('http-proxy');
+
+var port = parseInt(process.env.PORT);
+var host = process.env.HOST;
+
+var upstream_host = process.env.UPSTREAM_HOST;
+var upstream_port = parseInt(process.env.UPSTREAM_PORT);
+var upstream_size = parseInt(process.env.UPSTREAM_SIZE);
+
+var addresses = [];
+for(i=0;i<upstream_size;i++){
+ addresses.push({
+ host: upstream_host,
+ port: upstream_port + i
+ });
+}
+
+// Proxy
+var proxy = new htproxy.RoutingProxy();
+
+// Hanle Error
+proxy.on('proxyError',function(err,req,res){
+ console.error("Proxy Error: ",err);
+ res.writeHead(500);
+ res.write("Upstream Proxy Error");
+ res.end();
+});
+
+// Main HTTP Server
+http.createServer(function (req, res) {
+
+ var target = addresses.shift();
+
+ proxy.proxyRequest(req, res, target);
+
+ addresses.push(target);
+
+}).listen(port,function(){
+ if(process.getuid()==0) process.setuid( process.env.SUDO_USER );
+})
Please sign in to comment.
Something went wrong with that request. Please try again.