Skip to content

Commit

Permalink
balancer: [http] add support for fuzzy hostname matching. Closes #6
Browse files Browse the repository at this point in the history
  • Loading branch information
logicalparadox committed Sep 22, 2013
1 parent 6d467d5 commit 8595a33
Showing 1 changed file with 135 additions and 4 deletions.
139 changes: 135 additions & 4 deletions lib/carbon/balancers/http.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,88 @@

/*!
* Module dependencies
*/

var debug = require('sherlock')('carbon:balancer:http');
var inherits = require('util').inherits;

/*!
* Internal constructors
*/

var Base = require('./_base');

module.exports = HttpBalancer;
/*!
* Primary exports
*/

module.exports = HTTPBalancer;

function HttpBalancer(app, opts) {
/**
* ### HTTPBalancer
*
* Balancer specifically tuned for HTTP/WS requests.
*
* @param {Application} app
* @param {Object} options
* @api public
*/

function HTTPBalancer(app, opts) {
Base.call(this, app, 'http', opts);
var store = this._balancerStore;
store.set('hostnames', []);
}

inherits(HttpBalancer, Base);
/*!
* Inherits from Base
*/

inherits(HTTPBalancer, Base);

/**
* #### .host(name[, name, ...])
*
* Add a host to test again incoming request.
*
* @param {String} hostname ...
* @return this
* @api public
*/

HTTPBalancer.prototype.host = function() {
var args = [].slice.call(arguments);
var hostnames = this.get('hostnames');

args.forEach(function(host) {
host = hostNormalize(host);
host.name = hostParse(host.name);
debug('(host) add: %s %d', host.name.toString(), host.port);
hostnames.push(host);
});

return this;
};

/*!
* Handle hook again base.
*
* @param {Request} request
* @param {Response} response
* @param {Function} next
* @api private
*/

HttpBalancer.prototype._handle = function(req, res, next) {
HTTPBalancer.prototype._handle = function(req, res, next) {
debug('(handle)');
var host = req.headers.host;
var hostnames = this.get('hostnames');
var port = this.get('port');

if (hostnames.length && !hostMatches(hostnames, host)) {
debug('(handle) no host match: %s', host);
return next();
}

this.shards.next(function(err, shard) {
if (err || !shard) return next();
Expand All @@ -27,6 +95,69 @@ HttpBalancer.prototype._handle = function(req, res, next) {
});
};


/*!
* Normalize a host string.
*
* @param {String} hostname string
* @returns{String} normalized
* @api private
*/

function hostNormalize(host) {
if (!host || host.length === 0) return null;
var parts = host.split(':');
return { name: parts[0], port: (parseFloat(parts[1]) || 80) };
}

/*!
* Convert hostname to regexp for testing.
*
* @param {String|RegExp} host query
* @return {RegExp} testable
* @api private
*/

function hostParse(name) {
if (name instanceof RegExp) return name;
name = name.replace(/\*/g, '(.*)');
return new RegExp('^' + name + '$', 'i');
}

/*!
* Test a raw host string again against
* an array of hostname regexp to see if
* it matches any.
*
* @param {Array} hostnames
* @param {String} host to test
* @return {Boolean} match
* @api private
*/

function hostMatches(hostnames, host) {
host = hostNormalize(host);
if (!host) return false;

var match = false;
var i = 0;
var re;

for (; i < hostnames.length; i++) {
re = hostnames[i].name;
if (!! host.name.match(re)) {
match = true;
break;
}
}

return match;
}

/*!
* Scratch
*/

var stats = {};

stats.request = function(proxy, shard) {
Expand Down

0 comments on commit 8595a33

Please sign in to comment.