Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

initial commit

  • Loading branch information...
commit 432e93bc163f2ebf7a9add8c0a526e8c916d55de 0 parents
@indutny authored
Showing with 2 additions and 0 deletions.
  1. +1 −0  balancer
  2. +1 −0  config.json
1  balancer
@@ -0,0 +1 @@
+#!/usr/bin/env node var http = require('http'), net = require('net'), sys = require('sys'), fs = require('fs'), Buffer = require('buffer').Buffer, argv = process.argv.slice(2), CRLF = '\r\n'; fs.readFile(argv[1] || './config.json', function(err, data) { if (err) throw Error('Could not open config file'); try { data = JSON.parse(data.length ? data.toString() : ''); } catch (e) { throw Error('Invalid config format: ' + e.toString()); } if (!data.servers || !data.servers instanceof Array || !data.servers.length) { throw Error('servers is undeclared, or not array, or empty in config file'); } for (var i = 0, len = data.servers.length; i < len; i++) { data.servers[i][2] = data.servers[i][0] + (data.servers[i][1] - 80 == 0 ? '' : ':' + data.servers[i][1]); } start(data, data.spray && new RegExp(data.spray[0], data.spray[1])); }); function start(config, spray) { var addr = argv[0] ? argv[0].split(':', 2) : ['127.0.0.1', 80], servers = config.servers, serverslen = servers.length; var server = http.createServer(function(request, response) { var id, server; // Spray between id = Math.floor(Math.random() * serverslen); server = servers[id]; request.headers.host = server[2]; try { var remote_request = http.createClient(server[1], server[0]) .request(request.method, request.url, request.headers); remote_request.addListener('response', function(remote_response) { // Pass headers response.writeHead(remote_response.statusCode, remote_response.headers); // Pass every chunk remote_response.addListener('data', function(chunk) { response.write(chunk, 'binary'); }); // And close connection remote_response.addListener('end', function() { response.end(); }); }); // Pass every chunk to server request.addListener('data', function(chunk) { remote_request.write(chunk, 'binary'); }); // End sync request.addListener('end', function() { remote_request.end(); }); } catch(e) { response.writeHead(500); response.end('Server error, try refreshing page'); } }); function init_socket(socket, server) { socket.setTimeout(0); socket.setNoDelay(true); if (server) { socket.setKeepAlive(true, 0); } else { socket.setEncoding('utf8'); } } // Websocket proxy server.on('upgrade', function(request, socket, head) { if (request.method !== 'GET' || request.headers.upgrade.toLowerCase() !== 'websocket') { socket.end(); socket.destroy(); return; } init_socket(socket); // Simpliest hashing var ip = request.socket.remoteAddress.split('.'), id = (ip[0] * 65536 + ip[1] * 256 + ip[2]) % serverslen, server = servers[id]; try { var remote_socket = new net.Stream(); remote_socket.connect(server[1], server[0]); init_socket(remote_socket, true); var data = 'GET ' + request.url + ' HTTP/1.1' + CRLF + 'Upgrade: WebSocket' + CRLF + 'Connection: Upgrade' + CRLF + 'Host: ' + server[2] + CRLF + 'Origin: http://' + server[2] + CRLF + 'Sec-WebSocket-Key1: ' + request.headers['sec-websocket-key1'] + CRLF + 'Sec-WebSocket-Key2: ' + request.headers['sec-websocket-key2'] + CRLF + CRLF; remote_socket.on('connect', function() { var handshake = true; remote_socket.on('data', function(data) { if (handshake) { // Replace host and origin var sdata = data.toString(); sdata = sdata .substr(0, sdata.search(CRLF + CRLF)); data = data.slice(Buffer.byteLength(sdata), data.length); sdata = sdata .replace(server[2], addr[2]) .replace(server[2], addr[2]); socket.write(sdata); socket.write(data); handshake = false; } else { socket.write(data); } }); socket.on('data', function(data) { remote_socket.write(data); }); remote_socket.write(data); remote_socket.write(head); }); remote_socket.on('end', function() { socket.end(); socket.destroy(); }); socket.on('end', function() { remote_socket.end(); remote_socket.destroy(); }); } catch (e) { socket.end(); socket.destroy(); } }); server.listen((addr[1] - 0) || 80, addr[0]); addr[2] = addr[0] + (addr[1] - 80 == 0 ? '' : ':' + addr[1]); sys.puts('Node-balancer listening on ' + addr[2]); process.on('uncaughtException', function(e) { sys.puts(e); }); }
1  config.json
@@ -0,0 +1 @@
+{
Please sign in to comment.
Something went wrong with that request. Please try again.