goldilocks.js/lib/proxy-conn.js

78 lines
2.1 KiB
JavaScript

'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;
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();
});
};
};