v2.4.1: allow two function listeners and return server.unecrypted for error listening

This commit is contained in:
AJ ONeal 2018-08-17 20:43:32 -06:00
parent 6f960b1a2a
commit 38de3e9d1c
4 changed files with 61 additions and 18 deletions

View File

@ -330,6 +330,15 @@ var server = glx.listen(80, 443, function () {
});
```
Note: You shouldn't be using the plain HTTP server for anything except, potentially, for error handling
on the listen event (if the default print-and-quit behavior doesn't work for your use case).
If you need to do that, here's how:
```
var plainServer = server.unencrypted;
plainServer.on('error', function (err) { ... });
```
The Automatic Certificate Issuance is initiated via SNI (`httpsOptions.SNICallback`).
For security, domain validation MUST have an approval callback in *production*.

View File

@ -29,7 +29,7 @@ module.exports.create = function (opts) {
console.error(e.code + ": '" + e.address + ":" + e.port + "'");
}
function _listenHttp(plainPort, sayAnything) {
function _listenHttp(plainPort) {
if (!plainPort) { plainPort = 80; }
var p = plainPort;
var validHttpPort = (parseInt(p, 10) >= 0);
@ -39,10 +39,7 @@ module.exports.create = function (opts) {
);
var promise = new PromiseA(function (resolve) {
plainServer.listen(p, function () {
if (sayAnything) {
console.info("Success! Bound to port '" + p + "' to handle ACME challenges and redirect to https");
}
resolve();
resolve(plainServer);
}).on('error', function (e) {
if (plainServer.listenerCount('error') < 2) {
console.warn("Did not successfully create http server and bind to port '" + p + "':");
@ -55,18 +52,21 @@ module.exports.create = function (opts) {
return promise;
}
function _listenHttps(port, sayAnything) {
function _listenHttps(port) {
if (!port) { port = 443; }
var p = port;
var validHttpsPort = (parseInt(p, 10) >= 0);
var httpType;
if (!validHttpsPort) { console.warn("'" + p + "' doesn't seem to be a valid port number for https"); }
var https;
try {
https = require('spdy');
greenlock.tlsOptions.spdy = { protocols: [ 'h2', 'http/1.1' ], plain: false };
httpType = 'http2 (spdy/h2)';
} catch(e) {
https = require('https');
httpType = 'https';
}
var server = https.createServer(
greenlock.tlsOptions
@ -79,11 +79,9 @@ module.exports.create = function (opts) {
}
})
);
server.type = httpType;
var promise = new PromiseA(function (resolve) {
server.listen(p, function () {
if (sayAnything) {
console.info("Success! Serving https on port '" + p + "'");
}
resolve(server);
}).on('error', function (e) {
if (server.listenerCount('error') < 2) {
@ -103,21 +101,44 @@ module.exports.create = function (opts) {
res.end("Hello, World!\nWith Love,\nGreenlock for Express.js");
};
opts.listen = function (plainPort, port, fn) {
opts.listen = function (plainPort, port, fn1, fn2) {
var promises = [];
var server;
var plainServer;
promises.push(_listenHttp(plainPort, !fn));
var fn;
var fnPlain;
if (fn2) {
fn = fn2;
fnPlain = fn1;
} else {
fn = fn1;
}
promises.push(_listenHttp(plainPort, !fnPlain));
promises.push(_listenHttps(port, !fn));
server = promises[1].server;
plainServer = promises[0].server;
PromiseA.all(promises).then(function () {
// Report h2/https status
if ('function' === typeof fn) {
fn.apply(server);
} else if (server.listenerCount('listening') < 2) {
console.info("Success! Serving " + server.type + " on port '" + server.address().port + "'");
}
// Report plain http status
if ('function' === typeof fnPlain) {
fnPlain.apply(plainServer);
} else if (!fn && plainServer.listenerCount('listening') < 2) {
console.info("Success! Bound to port '" + plainServer.address().port
+ "' to handle ACME challenges and redirect to " + server.type);
}
return server;
});
server.unencrypted = plainServer;
return server;
};

View File

@ -1,6 +1,6 @@
{
"name": "greenlock-express",
"version": "2.4.0",
"version": "2.4.1",
"description": "Free SSL and managed or automatic HTTPS for node.js with Express, Koa, Connect, Hapi, and all other middleware systems.",
"main": "index.js",
"homepage": "https://git.coolaj86.com/coolaj86/greenlock-express.js",

View File

@ -16,7 +16,9 @@ var greenlock = Greenlock.create({
var server1 = greenlock.listen(5080, 5443);
server1.on('listening', function () {
console.log("### THREE 3333 - All is well server1", this.address());
server1.close();
setTimeout(function () {
// so that the address() object doesn't disappear
}, 10);
});
setTimeout(function () {
var server2 = greenlock.listen(6080, 6443, function () {
@ -32,10 +34,21 @@ setTimeout(function () {
});
}, 1000);
var server3 = greenlock.listen(7080, 22, function () {
// ignore
var server3 = greenlock.listen(22, 22, function () {
console.error("Error: expected to get an error when launching plain server on port 22");
}, function () {
console.error("Error: expected to get an error when launching " + server3.type + " server on port 22");
});
server3.unencrypted.on('error', function () {
console.log("Success: caught expected (plain) error");
});
server3.on('error', function () {
console.log("Success: caught expected error");
server3.close();
console.log("Success: caught expected " + server3.type + " error");
//server3.close();
});
var server4 = greenlock.listen(7080, 7443, function () {
console.log('Success: server4: plain');
}, function () {
console.log('Success: server4: ' + server4.type);
});