started splitting http handling into multiple servers

This commit is contained in:
tigerbot 2017-05-17 19:16:45 -06:00
parent 47bcdcf2a6
commit 27e818f41a
2 changed files with 46 additions and 65 deletions

View File

@ -59,6 +59,6 @@ module.exports.create = function (deps, conf) {
] ]
}); });
/* device, addresses, cwd, http */ var app = require('../app.js')(deps, conf, opts);
return require('../app.js')(deps, conf, opts); return require('http').createServer(app);
}; };

View File

@ -4,7 +4,6 @@ module.exports.create = function (deps, conf, greenlockMiddleware) {
var PromiseA = require('bluebird'); var PromiseA = require('bluebird');
var express = require('express'); var express = require('express');
var app = express(); var app = express();
var adminApp = require('./admin').create(deps, conf);
var domainMatches = require('../domain-utils').match; var domainMatches = require('../domain-utils').match;
var separatePort = require('../domain-utils').separatePort; var separatePort = require('../domain-utils').separatePort;
@ -80,16 +79,28 @@ module.exports.create = function (deps, conf, greenlockMiddleware) {
}); });
} }
function verifyHost(fullHost) { // We handle both HTTPS and HTTP traffic on the same ports, and we want to redirect
var host = separatePort(fullHost).host; // any unencrypted requests to the same port they came from unless it came in on
// the default HTTP port, in which case there wont be a port specified in the host.
var redirecters = {};
var ipv4Re = /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/;
var ipv6Re = /^\[[0-9a-fA-F:]+\]$/;
function redirectHttps(req, res) {
var host = separatePort(req.headers.host);
if (host === 'localhost') { if (!redirecters[host.port]) {
return fullHost.replace(host, 'localhost.daplie.me'); redirecters[host.port] = require('redirect-https')({ port: host.port });
} }
// localhost and IP addresses cannot have real SSL certs (and don't contain any useful
// info for redirection either), so we direct some hosts to either localhost.daplie.me
// or the "primary domain" ie the first manually specified domain.
if (host.host === 'localhost') {
req.headers.host = 'localhost.daplie.me' + (host.port ? ':'+host.port : '');
}
// Test for IPv4 and IPv6 addresses. These patterns will match some invalid addresses, // Test for IPv4 and IPv6 addresses. These patterns will match some invalid addresses,
// but since those still won't be valid domains that won't really be a problem. // but since those still won't be valid domains that won't really be a problem.
if (/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(host) || /^\[[0-9a-fA-F:]+\]$/.test(host)) { if (ipv4Re.test(host.host) || ipv6Re.test(host.host)) {
if (!conf.http.primaryDomain) { if (!conf.http.primaryDomain) {
(conf.http.modules || []).some(function (mod) { (conf.http.modules || []).some(function (mod) {
return mod.domains.some(function (domain) { return mod.domains.some(function (domain) {
@ -100,48 +111,12 @@ module.exports.create = function (deps, conf, greenlockMiddleware) {
}); });
}); });
} }
return fullHost.replace(host, conf.http.primaryDomain || host); if (conf.http.primaryDomain) {
req.headers.host = conf.http.primaryDomain + (host.port ? ':'+host.port : '');
}
} }
return fullHost; redirecters[host.port](req, res);
}
// We handle both HTTPS and HTTP traffic on the same ports, and we want to redirect
// any unencrypted requests to the same port they came from unless it came in on
// the default HTTP port, in which case there wont be a port specified in the host.
var redirecters = {};
function redirectHttps(req, res, next) {
if (conf.http.allowInsecure) {
next();
return;
}
var port = separatePort(req.headers.host).port;
if (!redirecters[port]) {
redirecters[port] = require('redirect-https')({
port: port
, trustProxy: conf.http.trustProxy
});
}
// localhost and IP addresses cannot have real SSL certs (and don't contain any useful
// info for redirection either), so we direct some hosts to either localhost.daplie.me
// or the "primary domain" ie the first manually specified domain.
req.headers.host = verifyHost(req.headers.host);
redirecters[port](req, res, next);
}
function handleAdmin(req, res, next) {
var admin = adminDomains.some(function (re) {
return re.test(req.headers.host);
});
if (admin) {
adminApp(req, res);
} else {
next();
}
} }
function respond404(req, res) { function respond404(req, res) {
@ -206,10 +181,6 @@ module.exports.create = function (deps, conf, greenlockMiddleware) {
}; };
} }
app.use(greenlockMiddleware);
app.use(redirectHttps);
app.use(handleAdmin);
(conf.http.modules || []).forEach(function (mod) { (conf.http.modules || []).forEach(function (mod) {
if (mod.name === 'redirect') { if (mod.name === 'redirect') {
app.use(createRedirectRoute(mod)); app.use(createRedirectRoute(mod));
@ -217,7 +188,7 @@ module.exports.create = function (deps, conf, greenlockMiddleware) {
else if (mod.name === 'static') { else if (mod.name === 'static') {
app.use(createStaticRoute(mod)); app.use(createStaticRoute(mod));
} }
else { else if (mod.name !== 'proxy') {
console.warn('unknown HTTP module', mod); console.warn('unknown HTTP module', mod);
} }
}); });
@ -226,7 +197,7 @@ module.exports.create = function (deps, conf, greenlockMiddleware) {
var server = require('http').createServer(app); var server = require('http').createServer(app);
function handleHttp(conn, opts) { function emitConnection(server, conn, opts) {
server.emit('connection', conn); server.emit('connection', conn);
// We need to put back whatever data we read off to determine the connection was HTTP // We need to put back whatever data we read off to determine the connection was HTTP
@ -240,15 +211,21 @@ module.exports.create = function (deps, conf, greenlockMiddleware) {
return true; return true;
} }
var acmeServer;
function checkACME(conn, opts, headers) { function checkACME(conn, opts, headers) {
if (headers.url.indexOf('/.well-known/acme-challenge/') !== 0) { if (headers.url.indexOf('/.well-known/acme-challenge/') !== 0) {
return false; return false;
} }
return handleHttp(conn, opts); if (!acmeServer) {
acmeServer = require('http').createServer(greenlockMiddleware);
}
return emitConnection(acmeServer, conn, opts);
} }
function checkRedirect(conn, opts, headers) {
var httpsRedirectServer;
function checkHttps(conn, opts, headers) {
if (conf.http.allowInsecure || conn.encrypted) { if (conf.http.allowInsecure || conn.encrypted) {
return false; return false;
} }
@ -256,16 +233,23 @@ module.exports.create = function (deps, conf, greenlockMiddleware) {
return false; return false;
} }
return handleHttp(conn, opts); if (!httpsRedirectServer) {
httpsRedirectServer = require('http').createServer(redirectHttps);
}
return emitConnection(httpsRedirectServer, conn, opts);
} }
var adminServer;
function checkAdmin(conn, opts, headers) { function checkAdmin(conn, opts, headers) {
var admin = adminDomains.some(function (re) { var admin = adminDomains.some(function (re) {
return re.test(headers.host); return re.test(headers.host);
}); });
if (admin) { if (admin) {
return handleHttp(conn, opts); if (!adminServer) {
adminServer = require('./admin').create(deps, conf);
}
return emitConnection(adminServer, conn, opts);
} }
return false; return false;
} }
@ -316,7 +300,7 @@ module.exports.create = function (deps, conf, greenlockMiddleware) {
parseHeaders(conn, opts) parseHeaders(conn, opts)
.then(function (headers) { .then(function (headers) {
if (checkACME(conn, opts, headers)) { return; } if (checkACME(conn, opts, headers)) { return; }
if (checkRedirect(conn, opts, headers)) { return; } if (checkHttps(conn, opts, headers)) { return; }
if (checkAdmin(conn, opts, headers)) { return; } if (checkAdmin(conn, opts, headers)) { return; }
var handled = (conf.http.modules || []).some(function (mod) { var handled = (conf.http.modules || []).some(function (mod) {
@ -328,10 +312,7 @@ module.exports.create = function (deps, conf, greenlockMiddleware) {
return; return;
} }
server.emit('connection', conn); emitConnection(server, conn, opts);
process.nextTick(function () {
conn.unshift(opts.firstChunk);
});
}) })
; ;
} }