Skip to content

Instantly share code, notes, and snippets.

@jbalogh
Created November 9, 2010 18:27
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save jbalogh/669539 to your computer and use it in GitHub Desktop.
Save jbalogh/669539 to your computer and use it in GitHub Desktop.
node.js duplex proxy for load testing with production traffic
/* A node.js proxy that forwards requests to two upstream servers, but only
* returns the response from one. Might be useful for load testing with
* production traffic.
*/
var http = require('http');
/* The request is forwarded to both proxies, but only the response from proxy1
* is returned.
*/
var proxy1 = [8001, 'localhost'],
proxy2 = [8002, 'localhost'];
var server = function(request, response) {
var p1 = http.createClient(proxy1[0], proxy1[1]),
p2 = http.createClient(proxy2[0], proxy2[1]),
r1 = p1.request(request.method, request.url, request.headers),
r2 = p2.request(request.method, request.url, request.headers),
start = new(Date), p1Time, p2Time;
/* Write request data to both proxies. */
request.on('data', function(chunk) {
r1.write(chunk, 'binary');
r2.write(chunk, 'binary');
});
/* Send the primary response back to the client. */
r1.on('response', function(proxy_response) {
response.writeHead(proxy_response.statusCode, proxy_response.headers);
proxy_response.on('data', function(chunk) {
response.write(chunk, 'binary');
});
proxy_response.on('end', function() {
response.end();
p1Time = new(Date) - start;
status();
});
});
/* Only track the timing for the duplicate request. */
r2.on('response', function(proxy_response) {
proxy_response.on('end', function() {
p2Time = new(Date) - start;
status();
});
});
/* Log response times once both requests are complete. */
var status = function() {
if (p1Time && p2Time) {
console.log(request.method + ' "' + request.url + '" ' +
'p1: ' + p1Time / 1000 + '; p2: ' + p2Time / 1000);
}
}
/* 500 response if something goes wrong with the proxy1. */
var error = function(err) {
response.writeHead(500, {'content-type': 'text/plain'});
if (request.method !== 'HEAD') {
response.write('Internal Server Error');
}
response.end();
};
/* Log issues with the proxy2. */
var busted = function(err) {
console.log('Error in proxy 2:\n' + JSON.stringify(err));
};
/* Oh joy, error handling. */
p1.on('error', error), p2.on('error', busted);
r1.on('error', error), r2.on('error', busted);
r1.end(), r2.end();
};
http.createServer(server).listen(8000);
console.log('running on :8000');
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment