2017-05-17 20:06:24 +00:00
|
|
|
'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) {
|
|
|
|
return function proxy(conn, newConnOpts, firstChunk, decrypt) {
|
|
|
|
var connected = false;
|
|
|
|
var newConn = deps.net.createConnection(newConnOpts, function () {
|
|
|
|
connected = true;
|
|
|
|
|
|
|
|
if (firstChunk) {
|
|
|
|
newConn.write(firstChunk);
|
|
|
|
}
|
|
|
|
|
|
|
|
newConn.pipe(conn);
|
|
|
|
conn.pipe(newConn);
|
|
|
|
});
|
|
|
|
|
2017-05-18 20:14:44 +00:00
|
|
|
// Listening for this largely to prevent uncaught exceptions.
|
|
|
|
conn.on('error', function (err) {
|
|
|
|
console.log('proxy client error', err);
|
|
|
|
});
|
2017-05-17 20:06:24 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2017-05-18 20:14:44 +00:00
|
|
|
// 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();
|
2017-05-17 20:06:24 +00:00
|
|
|
});
|
|
|
|
};
|
|
|
|
};
|