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) {
|
function createTcpForwarder(mod) {
|
||||||
var destination = mod.address.split(':');
|
|
||||||
var connected = false;
|
|
||||||
|
|
||||||
return function (conn) {
|
return function (conn) {
|
||||||
var newConn = deps.net.createConnection({
|
var newConnOpts = require('./domain-utils').separatePort(mod.address);
|
||||||
port: destination[1]
|
|
||||||
, host: destination[0] || '127.0.0.1'
|
|
||||||
|
|
||||||
, remoteFamily: conn.remoteFamily
|
['remote', 'local'].forEach(function (end) {
|
||||||
, remoteAddress: conn.remoteAddress
|
['Family', 'Address', 'Port'].forEach(function (name) {
|
||||||
, remotePort: conn.remotePort
|
newConnOpts[end+name] = conn[end+name];
|
||||||
}, 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();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
deps.proxy(conn, newConnOpts);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -275,7 +275,6 @@ module.exports.create = function (deps, conf, greenlockMiddleware) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var connected = false;
|
|
||||||
var newConnOpts = separatePort(mod.address);
|
var newConnOpts = separatePort(mod.address);
|
||||||
newConnOpts.servername = separatePort(headers.host).host;
|
newConnOpts.servername = separatePort(headers.host).host;
|
||||||
newConnOpts.data = opts.firstChunk;
|
newConnOpts.data = opts.firstChunk;
|
||||||
|
@ -284,28 +283,7 @@ module.exports.create = function (deps, conf, greenlockMiddleware) {
|
||||||
newConnOpts.remoteAddress = opts.address || conn.remoteAddress;
|
newConnOpts.remoteAddress = opts.address || conn.remoteAddress;
|
||||||
newConnOpts.remotePort = opts.port || conn.remotePort;
|
newConnOpts.remotePort = opts.port || conn.remotePort;
|
||||||
|
|
||||||
var newConn = deps.net.createConnection(newConnOpts, function () {
|
deps.proxy(conn, newConnOpts, opts.firstChunk);
|
||||||
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();
|
|
||||||
});
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -186,48 +186,23 @@ module.exports.create = function (deps, config, netHandler) {
|
||||||
});
|
});
|
||||||
|
|
||||||
function proxy(socket, opts, mod) {
|
function proxy(socket, opts, mod) {
|
||||||
var destination = mod.address.split(':');
|
var newConnOpts = require('../domain-utils').separatePort(mod.address);
|
||||||
var connected = false;
|
newConnOpts.servername = opts.servername;
|
||||||
|
newConnOpts.data = opts.firstChunk;
|
||||||
|
|
||||||
var newConn = deps.net.createConnection({
|
newConnOpts.remoteFamily = opts.family || extractSocketProp(socket, 'remoteFamily');
|
||||||
port: destination[1]
|
newConnOpts.remoteAddress = opts.address || extractSocketProp(socket, 'remoteAddress');
|
||||||
, host: destination[0] || '127.0.0.1'
|
newConnOpts.remotePort = opts.port || extractSocketProp(socket, 'remotePort');
|
||||||
|
|
||||||
, servername: opts.servername
|
deps.proxy(socket, newConnOpts, opts.firstChunk, function () {
|
||||||
, data: opts.firstChunk
|
// This function is called in the event of a connection error and should decrypt
|
||||||
, remoteFamily: opts.family || extractSocketProp(socket, 'remoteFamily')
|
// the socket so the proxy module can send a 502 HTTP response.
|
||||||
, 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();
|
|
||||||
} else {
|
|
||||||
console.log('TLS proxy connection error', err);
|
|
||||||
var tlsOpts = localhostCerts.mergeTlsOptions('localhost.daplie.me', {isServer: true});
|
var tlsOpts = localhostCerts.mergeTlsOptions('localhost.daplie.me', {isServer: true});
|
||||||
var decrypted;
|
|
||||||
if (opts.hyperPeek) {
|
if (opts.hyperPeek) {
|
||||||
decrypted = new tls.TLSSocket(socket, tlsOpts);
|
return new tls.TLSSocket(socket, tlsOpts);
|
||||||
} else {
|
} else {
|
||||||
decrypted = new tls.TLSSocket(wrapSocket(socket, opts), tlsOpts);
|
return new tls.TLSSocket(wrapSocket(socket, opts), tlsOpts);
|
||||||
}
|
}
|
||||||
require('../proxy-err-resp').sendBadGateway(decrypted, err, config.debug);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
socket.on('error', function (err) {
|
|
||||||
console.error('TLS proxy client error', err);
|
|
||||||
newConn.end();
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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.
|
// HTTP proxying connection creation is not something we currently control.
|
||||||
, net: require('net')
|
, net: require('net')
|
||||||
};
|
};
|
||||||
|
deps.proxy = require('./proxy-conn').create(deps, conf);
|
||||||
|
|
||||||
require('./goldilocks.js').create(deps, conf);
|
require('./goldilocks.js').create(deps, conf);
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue