Skip to content

Instantly share code, notes, and snippets.

@drorm
Created December 4, 2012 20:07
Show Gist options
  • Save drorm/4208144 to your computer and use it in GitHub Desktop.
Save drorm/4208144 to your computer and use it in GitHub Desktop.
Meteor Proxy server
"use strict";
var httpProxy = require('http-proxy'),
http = require('http'),
accesslog = require('access-log'),
addresses;
var LISTENPORT = 80; //port we're listening to the outside world
var METEORPORT = 3000; //port meteor is run on the guests
var MINIP = 10; //Minimum IP address we can use. Smaller numbers are for admin purposes
var MYDOMAIN = 'devwik.com';
var LOCAL_SUBNET = '10.0.3.';
var currentMaxNumber = MINIP;
var devwikCollection;
var proxyServer = null;
var devwikDb = null
// routing hash
addresses = {
/*
'foo.devwik.com:3180': {
host: '10.0.3.3',
port: METEORPORT
},
*/
'www.devwik.com': {
host: 'localhost',
port: 3000
},
//This is our testing server
'test.devwik.com': {
host: 'localhost',
port: 4000
},
'default': {
host: 'localhost',//by default go the devwik's main page if we don't match something we know.
port: METEORPORT //TODO: do we want to send them to a 404 Not found.?
}
};
var mongo = require('mongodb'),
Server = mongo.Server,
Db = mongo.Db;
//var server = new Server('localhost', 27017, {safe:true});
var server = new Server('localhost', 27017);
//var db = new Db('devwik', server, {safe:true});
var db = new Db('devwik', server);
var devwikUsersHash;
db.open(function(err, db) {
if(err) {
throw(err);
} else {
devwikDb = db;
loadUsers();
}
});
//load the devwik Users first.
function loadUsers(callBack) {
//load the Devwik Users first and insert them into a hash
devwikUsersHash = new Object();
devwikDb.collection('DevwikUsers', function(err, devwikUsers) {
if(err) {
throw(err);
} else {
devwikCollection = devwikUsers;
var stream = devwikUsers.find({}).stream();
stream.on("data", function(devwikUser) {
var userNumber = devwikUser.userNumber;
//console.log(" id:" + devwikUser.meteorId + " userNumber:" + userNumber + " port:" + devwikUser.port + " app:" + devwikUser.currentApp + " editor:" + devwikUser.editorType);
if(userNumber && (userNumber > currentMaxNumber)) { //find out what's the current highest number used
currentMaxNumber = userNumber;
}
devwikUsersHash[devwikUser.meteorId] = devwikUser; //set it up for each lookup by id
});
stream.on("end", function() {
loadMeteorUsers();
if (callBack) {
callBack();
}
});
}
});
}
//load the Meteor Users next.
function loadMeteorUsers() {
devwikDb.collection('users', function(err, users) {
if(err) {
throw(err);
} else {
var stream = users.find({},{sort: {createdAt: 1}}).stream();
stream.on("data", function(user) {
/*construct something like:
'foo.devwik.com': {
host: '10.0.3.23',
port: METEORPORT
},
*/
var devwikUser = devwikUsersHash[user._id];
if (!devwikUser) {
console.log('###Error. User:' + user.username + ' does not exist in devwikUser');
return;
}
var userNumber = devwikUser.userNumber;
if (!userNumber) { //user doesn't currently have a number assigned
currentMaxNumber++;
userNumber = currentMaxNumber;//give them the next number
console.log('Setting:' + user.username + " to:" + userNumber);
//And update it in the db for future use an also to inform the app
//TODO: race condition. Need to make sure that this is single threaded
devwikCollection.update({meteorId:user._id},{$set: {userNumber: userNumber}});
}
var vhost = new Object();
var subDomain = user.username + '.' + MYDOMAIN;
vhost.host = LOCAL_SUBNET + (userNumber);
vhost.port = METEORPORT;
addresses[subDomain] = vhost;
//console.log(" name:" + user.username + " id" + user._id);
//console.log(vhost);
});
stream.on("end", function() {
if (!proxyServer) {
runProxy();//first time
}
});
}
});
}
console.log('Starting, pid:' + process.pid);
function runProxy() {
proxyServer = httpProxy.createServer(function (request, response, proxy) {
var target;
// accesslog(request, response);
//
var buffer = httpProxy.buffer(request);
// if we have a host in the routing hash we proxy to it
// otherwise we proxy to default host
target = (addresses[request.headers.host]) ? addresses[request.headers.host] : addresses.default;
target.buffer = buffer;
proxy.proxyRequest(request, response, target);
}).listen(LISTENPORT);
console.log(addresses);
proxyServer.proxy.on('proxyError', function (err, req, res) {
res.writeHead(500, {
'Content-Type': 'text/html'
});
res.write('<html>\n');
res.write('<body>\n');
res.end("<h1> Not available </h1> Sorry, it looks like you've reached a site that is currently unavailable. <br/> Try later or check out <a href='http://www.devwik.com'>our home page at http://www.devwik.com'</a>.</body></html>");
res.end("</body> </html>");
});
}
http.createServer(function (request, response) {
request.on("end", function () {
//Called after the user is handled
var callBack = function() {
response.writeHead(200, {
'Content-Type': 'text/plain'
});
response.end('OK');
console.log('reload');
console.log(addresses);
};
// Send data and end response.
});
loadUsers(callback);
}).listen(9999);
-----------------------------------------------------------------
/*
* Contact the prox to let it know to check for a new user.
* 1. It will: find the user in the db
* 2. Assign them a unique ID TODO: you need to create a unique index
* 3. Update the db with the unique ID
* 4. Associate the IP address with the user name/sub domain such as joe.devwik.com
*/
Devwik.notifyProxy = function notifyProxy(callback) {
var options = {
host: 'localhost',
port: 9999,
path: '/',
method: 'GET'
};
var req = http.request(options, function(res) {
console.log('STATUS: ' + res.statusCode);
console.log('HEADERS: ' + JSON.stringify(res.headers));
res.setEncoding('utf8');
res.on('data', function (chunk) {
console.log('BODY: ' + chunk);
callback(chunk);
});
});
req.on('error', function(e) {
console.log('problem with request: ' + e.message);
});
// write data to request body
req.write('data\n');
req.write('data\n');
req.end();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment