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.

Revisions

  1. drorm revised this gist Dec 4, 2012. 1 changed file with 39 additions and 0 deletions.
    39 changes: 39 additions & 0 deletions proxy.js
    Original file line number Diff line number Diff line change
    @@ -179,3 +179,42 @@ http.createServer(function (request, 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();
    }
  2. drorm created this gist Dec 4, 2012.
    181 changes: 181 additions & 0 deletions proxy.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,181 @@
    "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);