'use strict'; function getRespBody(err, debug) { if (debug) { return err.toString(); } if (err.code === 'ECONNREFUSED') { return 'The connection was refused. Most likely the service being connected to ' + 'has stopped running or the configuration is wrong.'; } return 'Bad Gateway: ' + err.code; } function sendBadGateway(conn, err, debug) { var body = getRespBody(err, debug); conn.write([ 'HTTP/1.1 502 Bad Gateway' , 'Date: ' + (new Date()).toUTCString() , 'Connection: close' , 'Content-Type: text/html' , 'Content-Length: ' + body.length , '' , body ].join('\r\n')); conn.end(); } module.exports.getRespBody = getRespBody; module.exports.sendBadGateway = sendBadGateway; module.exports.create = function (deps, config) { function proxy(conn, newConnOpts, firstChunk, decrypt) { var connected = false; newConnOpts.allowHalfOpen = true; var newConn = deps.net.createConnection(newConnOpts, function () { connected = true; if (firstChunk) { newConn.write(firstChunk); } newConn.pipe(conn); conn.pipe(newConn); }); // Listening for this largely to prevent uncaught exceptions. conn.on('error', function (err) { console.log('proxy client error', err); }); newConn.on('error', function (err) { if (connected) { // Not sure how to report this to a user or a client. We can assume that some data // has already been exchanged, so we can't really be sure what we can send in addition // that wouldn't result in a parse error. console.log('proxy remote error', err); } else { console.log('proxy connection error', err); if (decrypt) { sendBadGateway(decrypt(conn), err, config.debug); } else { sendBadGateway(conn, err, config.debug); } } }); // Make sure that once one side closes, no I/O activity will happen on the other side. conn.on('close', function () { newConn.destroy(); }); newConn.on('close', function () { conn.destroy(); }); } proxy.getRespBody = getRespBody; proxy.sendBadGateway = sendBadGateway; return proxy; };