Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

loadfire

Package Overview
Dependencies
Maintainers
1
Versions
18
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

loadfire - npm Package Compare versions

Comparing version 0.0.1 to 1.0.0

lib/balancers/index.js

15

index.js
// Requires
var httpProxy = require('http-proxy');
var utils = require('./lib/utils');
var server = require('./lib/server');
var patterns = require('./lib/patterns');
var middleware = require('./lib/middleware');
var selectors = require('./lib/selectors/');
var balancers = require('./lib/balancers/');
var groupBalancer = require('./lib/groupbalancer');

@@ -21,5 +21,6 @@

exports.server = server;
exports.patterns = patterns;
exports.middleware = middleware;
exports.selectors = selectors;
exports.balancers = balancers;
exports.groupBalancer = groupBalancer;
exports.utils = utils;
// Requires
var _ = require('underscore');
var patterns = require('./patterns');

@@ -47,4 +46,10 @@ // Constants

var y = _.clone(x);
y.pattern = patterns.getPattern(x.pattern);
y.backends = that.resolveBackends(y.backends);
y.middleware = y.middleware || [];
// Bind methods to resource
_.bindAll(y);
return y;

@@ -54,2 +59,3 @@ });

};
ConfigLoader.prototype.resolve = function() {

@@ -60,3 +66,3 @@ // Resolve patterns and what not

var newConfig = _.clone(this.config);
// Update copied config

@@ -75,25 +81,2 @@ newConfig.resources = resources;

ConfigLoader.prototype.loadPatterns = function() {
var patternPaths = this.config.patternPaths || [];
// Dynamic importing
patternPaths.forEach(function(path) {
var mod = require(path);
var patterns = mod.PATTERNS;
// Skip if no patterns defined
if(_.isUndefined(patterns)) {
console.log('WARNING ', path, ' has not .PATTERNS attribute to laod');
return;
}
// Register each pattern
for(var key in patterns) {
patterns.register(key, patterns[key]);
}
});
return;
};
ConfigLoader.prototype.load = function() {

@@ -109,6 +92,2 @@ // Set defaults

// Load in patterns
// each pattern module should register it's own functions
this.loadPatterns();
// Resolve patterns etc ...

@@ -115,0 +94,0 @@ return this.resolve();

// Requires
var Q = require('q');
var _ = require('underscore');
var utils = require('./utils');
function GroupBalancer(resources) {
// Build our patterns
var patterns = resources.map(function(resource) {
var pattern = resource.pattern;
return new pattern(resource);
});
function GroupBalancer(config, resources) {
// Bind methods to resource
this.resources = resources;
this.patterns = patterns || [];
this.config = config;
// Bind methods
utils.bindMethods(this);
_.bindAll(this);
}
GroupBalancer.prototype.selectPattern = function(req) {
var filteredPatterns = this.patterns.filter(function(x) {
return x.shouldHandle(req);
GroupBalancer.prototype.selectResource = function(req) {
var resources = this.resources;
return Q.all(
// Array of booleans saying if the resource can handle
this.resources.map(function(resource) {
// Should handle ?
return Q.nfcall(resource.selector, req);
})
)
.then(function (results) {
// Associate resources with their respective results
return _.first(_.map(
_.filter(
_.zip(resources, results),
_.last
),
_.first
));
})
.then(function(resource) {
if(!resource) {
throw new Error("No resource can handle the request");
}
return resource;
});
};
// Error handler
if(filteredPatterns.length < 1) {
return undefined;
}
GroupBalancer.prototype.selectBackend = function(req, resource) {
return Q.nfcall(resource.balancer, resource.backends, req)
.then(function(backend) {
if(!backend) {
throw new Error("Balancer could not give a valid backend to route to");
}
return [backend, resource];
});
};
// Pick first
var handler = filteredPatterns[0];
return handler;
// selectResource then selectBackend
GroupBalancer.prototype.grabBackend = function(req) {
return this.selectResource(req)
.then(_.partial(this.selectBackend, req));
};
GroupBalancer.prototype.applyMiddleware = function(resource, req, res) {
// Apply a series of middleware
return _.map(resource.middleware, function(middleware) {
return Q.nfcall(middleware, req, res);
}).reduce(Q.when, Q());
};
GroupBalancer.prototype.handle = function(req, res, proxy) {
var handler = this.selectPattern(req);
var self = this;
console.log('Handle: ', req.headers.host+req.url);
// Pause request stream
req.pause();
// Handle no handler
if(_.isUndefined(handler)) {
res.write('ERROR: Loadfire does not know how to handle that request');
return this.grabBackend(req)
.spread(function(backend, resource) {
// Log
console.log('Handle: ', req.headers.host+req.url);
// Apply middleware
return self.applyMiddleware(resource, req, res)
.then(function() {
console.log('backend =', backend);
// Resume request
req.resume();
// Handle (actual proxying)
proxy.proxyRequest(req, res, _.clone(backend));
return backend;
});
})
.fail(function(err) {
console.log(err.stack);
res.write(err.stack);
res.write('\nERROR: Loadfire does not know how to handle that request\n');
res.end();
return;
}
// Handle
return handler.handle(req, res, proxy);
});
};
GroupBalancer.prototype.handleWs = function(req, socket, head) {
var handler = this.selectPattern(req);
return this.grabBackend(req)
.spread(function(backend, resource) {
// Log
console.log('handleWs: ', req.headers.host+req.url);
console.log('handleWs: ', req.headers.host+req.url);
// Build proxy
var proxy = new httpProxy.HttpProxy({
target: _.clone(backend)
});
// Buffer from socket
var buffer = httpProxy.buffer(socket);
// Handle no handler
if(_.isUndefined(handler)) {
// Actual proxying
proxy.proxyWebSocketRequest(req, socket, head, buffer);
return backend;
})
.fail(function(err) {
socket.write('ERROR: Loadfire does not know how to handle that request');
socket.close();
return;
}
});
};
// Handle
return handler.handleWs(req, socket, head);
// TCP Handler, just keep the connection alive
// do nothing special besides some logging
GroupBalancer.prototype.tcpConnectionHandler = function (connection) {
var remoteAddress = connection.remoteAddress,
remotePort = connection.remotePort,
start = Date.now();
var getSocketInfo = function () {
return JSON.stringify({
remoteAddress: remoteAddress,
remotePort: remotePort,
bytesWritten: connection.bytesWritten,
bytesRead: connection.bytesRead,
elapsed: (Date.now() - start) / 1000
});
};
connection.setKeepAlive(false);
connection.setTimeout(this.config.tcpTimeout * 1000);
connection.on('error', function (error) {
console.log('TCP error from ' + getSocketInfo() + '; Error: ' + JSON.stringify(error));
});
connection.on('timeout', function () {
console.log('TCP timeout from ' + getSocketInfo());
connection.destroy();
});
};

@@ -65,0 +156,0 @@

// Requires
var http = require('http');
var _ = require('underscore');
var httpProxy = require('http-proxy');
var utils = require('./utils');
var config = require('./config');
var GroupBalancer = require('./groupbalancer').GroupBalancer;
function Server(_config) {

@@ -13,3 +15,3 @@ // Validate and Resolve our configuration

// Get the group balancer
this.balancer = new GroupBalancer(this.config.resources);
this.balancer = new GroupBalancer(this.config, this.config.resources);

@@ -20,3 +22,3 @@ // Setup server and the different handlers

// Bind methods
utils.bindMethods(this);
_.bindAll(this);
}

@@ -30,6 +32,3 @@

// Handle TCP connections
var that = this;
this.server.on('connection', function() {
that.tcpConnectionHandler.apply(that, arguments);
});
this.server.on('connection', this.balancer.tcpConnectionHandler);

@@ -40,6 +39,7 @@ // Handle websocket upgrades

Server.prototype.run = function () {
// Server listen
Server.prototype.listen = function () {
var args = _.isEmpty(arguments) ? [this.config.port] : _.toArray(arguments);
// List on port
this.server.listen(this.config.port);
this.server.listen.apply(this.server, args);

@@ -49,35 +49,7 @@ return this;

// Alias
Server.prototype.run = Server.prototype.listen;
// TCP Handler, just keep the connection alive
// do nothing special besides some logging
Server.prototype.tcpConnectionHandler = function (connection) {
var remoteAddress = connection.remoteAddress,
remotePort = connection.remotePort,
start = Date.now();
var getSocketInfo = function () {
return JSON.stringify({
remoteAddress: remoteAddress,
remotePort: remotePort,
bytesWritten: connection.bytesWritten,
bytesRead: connection.bytesRead,
elapsed: (Date.now() - start) / 1000
});
};
connection.setKeepAlive(false);
connection.setTimeout(this.config.tcpTimeout * 1000);
connection.on('error', function (error) {
console.log('TCP error from ' + getSocketInfo() + '; Error: ' + JSON.stringify(error));
});
connection.on('timeout', function () {
console.log('TCP timeout from ' + getSocketInfo());
connection.destroy();
});
};
// Exports
module.exports.Server = Server;
{
"name" : "loadfire",
"version" : "0.0.1",
"version" : "1.0.0",
"description" : "A clean and simple load balancer",
"keywords": [
"loadfire",
"reverse",

@@ -24,8 +23,5 @@ "proxy",

"http-proxy" : "0.8.4",
"redis" : "0.7.x",
"lru-cache": "2.1.x",
"optimist": "0.3.x",
"underscore": "1.4.2",
"q": "0.8.9",
"async": "0.1.22"
"optimist": "0.3.0",
"underscore": "1.4.4",
"q": "0.9.6"
},

@@ -36,3 +32,3 @@ "scripts" : {

"engines" : {
"node" : "0.8.x"
"node" : ">=0.8.0"
},

@@ -42,7 +38,7 @@ "engineStrict": true,

"name" : "Aaron O'Mullan",
"email" : "aaron.omullan@gmail.com",
"url" : "http://friendco.de"
"email" : "aaron.omullan@friendco.de",
"url" : "https://friendco.de"
},
"maintainer" : [
"Aaron O'Mullan <aaron.omullan@gmail.com>"
"Aaron O'Mullan <aaron.omullan@friendco.de>"
],

@@ -49,0 +45,0 @@ "repository": {

@@ -35,3 +35,3 @@ var http = require('http');

// by default it should be the hostname to match
resource: 'localhost:8000',
selector: loadfire.selectors.host('localhost:8000'),

@@ -44,3 +44,3 @@ // List of backends to hit

// random, roundrobin, sticky
pattern: 'roundrobin'
balancer: loadfire.balancers.roundrobin
}

@@ -47,0 +47,0 @@ ],

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc