reduced code duplication for proxying
This commit is contained in:
parent
d25ceadf4a
commit
df3a818914
|
@ -80,40 +80,16 @@ module.exports.create = function (deps, config) {
|
|||
}
|
||||
|
||||
function createTcpForwarder(mod) {
|
||||
var destination = mod.address.split(':');
|
||||
var connected = false;
|
||||
|
||||
return function (conn) {
|
||||
var newConn = deps.net.createConnection({
|
||||
port: destination[1]
|
||||
, host: destination[0] || '127.0.0.1'
|
||||
var newConnOpts = require('./domain-utils').separatePort(mod.address);
|
||||
|
||||
, remoteFamily: conn.remoteFamily
|
||||
, remoteAddress: conn.remoteAddress
|
||||
, remotePort: conn.remotePort
|
||||
}, function () {
|
||||
connected = true;
|
||||
|
||||
newConn.pipe(conn);
|
||||
conn.pipe(newConn);
|
||||
});
|
||||
|
||||
// Not sure how to effectively report this to the user or client, but we need to listen
|
||||
// for the event to prevent it from crashing us.
|
||||
newConn.on('error', function (err) {
|
||||
if (connected) {
|
||||
console.error('TCP forward remote error', err);
|
||||
conn.end();
|
||||
} else {
|
||||
console.log('TCP forward connection error', err);
|
||||
require('./proxy-err-resp').sendBadGateway(conn, err, config.debug);
|
||||
}
|
||||
});
|
||||
conn.on('error', function (err) {
|
||||
console.error('TCP forward client error', err);
|
||||
newConn.end();
|
||||
['remote', 'local'].forEach(function (end) {
|
||||
['Family', 'Address', 'Port'].forEach(function (name) {
|
||||
newConnOpts[end+name] = conn[end+name];
|
||||
});
|
||||
});
|
||||
|
||||
deps.proxy(conn, newConnOpts);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -275,7 +275,6 @@ module.exports.create = function (deps, conf, greenlockMiddleware) {
|
|||
return false;
|
||||
}
|
||||
|
||||
var connected = false;
|
||||
var newConnOpts = separatePort(mod.address);
|
||||
newConnOpts.servername = separatePort(headers.host).host;
|
||||
newConnOpts.data = opts.firstChunk;
|
||||
|
@ -284,28 +283,7 @@ module.exports.create = function (deps, conf, greenlockMiddleware) {
|
|||
newConnOpts.remoteAddress = opts.address || conn.remoteAddress;
|
||||
newConnOpts.remotePort = opts.port || conn.remotePort;
|
||||
|
||||
var newConn = deps.net.createConnection(newConnOpts, function () {
|
||||
connected = true;
|
||||
newConn.write(opts.firstChunk);
|
||||
newConn.pipe(conn);
|
||||
conn.pipe(newConn);
|
||||
});
|
||||
|
||||
// Not sure how to effectively report this to the user or client, but we need to listen
|
||||
// for the event to prevent it from crashing us.
|
||||
newConn.on('error', function (err) {
|
||||
if (connected) {
|
||||
console.error('HTTP proxy remote error', err);
|
||||
conn.end();
|
||||
} else {
|
||||
require('../proxy-err-resp').sendBadGateway(conn, err, conf.debug);
|
||||
}
|
||||
});
|
||||
conn.on('error', function (err) {
|
||||
console.error('HTTP proxy client error', err);
|
||||
newConn.end();
|
||||
});
|
||||
|
||||
deps.proxy(conn, newConnOpts, opts.firstChunk);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -186,49 +186,24 @@ module.exports.create = function (deps, config, netHandler) {
|
|||
});
|
||||
|
||||
function proxy(socket, opts, mod) {
|
||||
var destination = mod.address.split(':');
|
||||
var connected = false;
|
||||
var newConnOpts = require('../domain-utils').separatePort(mod.address);
|
||||
newConnOpts.servername = opts.servername;
|
||||
newConnOpts.data = opts.firstChunk;
|
||||
|
||||
var newConn = deps.net.createConnection({
|
||||
port: destination[1]
|
||||
, host: destination[0] || '127.0.0.1'
|
||||
newConnOpts.remoteFamily = opts.family || extractSocketProp(socket, 'remoteFamily');
|
||||
newConnOpts.remoteAddress = opts.address || extractSocketProp(socket, 'remoteAddress');
|
||||
newConnOpts.remotePort = opts.port || extractSocketProp(socket, 'remotePort');
|
||||
|
||||
, servername: opts.servername
|
||||
, data: opts.firstChunk
|
||||
, remoteFamily: opts.family || extractSocketProp(socket, 'remoteFamily')
|
||||
, remoteAddress: opts.address || extractSocketProp(socket, 'remoteAddress')
|
||||
, remotePort: opts.port || extractSocketProp(socket, 'remotePort')
|
||||
}, function () {
|
||||
connected = true;
|
||||
if (!opts.hyperPeek) {
|
||||
newConn.write(opts.firstChunk);
|
||||
}
|
||||
newConn.pipe(socket);
|
||||
socket.pipe(newConn);
|
||||
});
|
||||
|
||||
// Not sure how to effectively report this to the user or client, but we need to listen
|
||||
// for the event to prevent it from crashing us.
|
||||
newConn.on('error', function (err) {
|
||||
if (connected) {
|
||||
console.error('TLS proxy remote error', err);
|
||||
socket.end();
|
||||
deps.proxy(socket, newConnOpts, opts.firstChunk, function () {
|
||||
// This function is called in the event of a connection error and should decrypt
|
||||
// the socket so the proxy module can send a 502 HTTP response.
|
||||
var tlsOpts = localhostCerts.mergeTlsOptions('localhost.daplie.me', {isServer: true});
|
||||
if (opts.hyperPeek) {
|
||||
return new tls.TLSSocket(socket, tlsOpts);
|
||||
} else {
|
||||
console.log('TLS proxy connection error', err);
|
||||
var tlsOpts = localhostCerts.mergeTlsOptions('localhost.daplie.me', {isServer: true});
|
||||
var decrypted;
|
||||
if (opts.hyperPeek) {
|
||||
decrypted = new tls.TLSSocket(socket, tlsOpts);
|
||||
} else {
|
||||
decrypted = new tls.TLSSocket(wrapSocket(socket, opts), tlsOpts);
|
||||
}
|
||||
require('../proxy-err-resp').sendBadGateway(decrypted, err, config.debug);
|
||||
return new tls.TLSSocket(wrapSocket(socket, opts), tlsOpts);
|
||||
}
|
||||
});
|
||||
socket.on('error', function (err) {
|
||||
console.error('TLS proxy client error', err);
|
||||
newConn.end();
|
||||
});
|
||||
}
|
||||
|
||||
function terminate(socket, opts) {
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
'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);
|
||||
});
|
||||
|
||||
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);
|
||||
conn.end();
|
||||
} else {
|
||||
console.log('proxy connection error', err);
|
||||
if (decrypt) {
|
||||
sendBadGateway(decrypt(conn), err, config.debug);
|
||||
} else {
|
||||
sendBadGateway(conn, err, config.debug);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Listening for this largely to prevent uncaught exceptions.
|
||||
conn.on('error', function (err) {
|
||||
console.log('proxy client error', err);
|
||||
newConn.end();
|
||||
});
|
||||
};
|
||||
};
|
|
@ -1,32 +0,0 @@
|
|||
'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;
|
|
@ -9,5 +9,7 @@ process.on('message', function (conf) {
|
|||
// HTTP proxying connection creation is not something we currently control.
|
||||
, net: require('net')
|
||||
};
|
||||
deps.proxy = require('./proxy-conn').create(deps, conf);
|
||||
|
||||
require('./goldilocks.js').create(deps, conf);
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue