goldilocks.js/serve.js

152 lines
3.9 KiB
JavaScript
Executable File

#!/usr/bin/env node
'use strict';
var https = require('https');
var http = require('http');
var fs = require('fs');
var path = require('path');
function createInsecureServer(port, pubdir, opts) {
var server = http.createServer();
server.on('error', function (err) {
console.error(err);
process.exit(1);
});
server.on('request', require('redirect-https')({
port: port
}));
server.listen(opts.insecurePort, function () {
var msg = 'Serving ' + pubdir + ' at http://' + opts.servername;
var p = server.address().port;
if (80 !== p) {
msg += ':' + p;
}
console.info(msg);
});
}
function createServer(port, pubdir, content, opts) {
var server = https.createServer(opts);
var app = require('./app');
var directive = { public: pubdir, content: content };
if (opts.insecurePort) {
createInsecureServer(port, pubdir, opts);
}
server.on('error', function (err) {
console.error(err);
process.exit(1);
});
server.listen(port, function () {
var msg = 'Serving ' + pubdir + ' at https://' + opts.servername;
var p = server.address().port;
if (443 !== p) {
msg += ':' + p;
}
console.info(msg);
});
if ('function' === typeof app) {
app = app(directive);
} else if ('function' === typeof app.create) {
app = app.create(directive);
}
Promise.resolve(app).then(function (app) {
server.on('request', app);
});
}
module.exports.createServer = createServer;
function run() {
var minimist = require('minimist');
var argv = minimist(process.argv.slice(2));
var port = argv.p || argv.port || argv._[0] || 8443;
var pubdir = path.resolve(argv.d || argv._[1] || process.cwd());
var content = argv.c;
var letsencryptHost = argv['letsencrypt-certs'];
var cert = require('localhost.daplie.com-certificates');
var opts = {
key: cert.key
, cert: cert.cert
//, ca: cert.ca
, SNICallback: function (servername, cb) {
cb(null, require('tls').createSecureContext(opts));
return;
}
};
var peerCa;
if (letsencryptHost) {
argv.key = argv.key || '/etc/letsencrypt/live/' + letsencryptHost + '/privkey.pem';
argv.cert = argv.cert || '/etc/letsencrypt/live/' + letsencryptHost + '/fullchain.pem';
argv.root = argv.root || argv.chain || '/etc/letsencrypt/live/' + letsencryptHost + '/root.pem';
argv.servername = argv.servername || letsencryptHost;
argv['serve-root'] = argv['serve-root'] || argv['serve-chain'];
}
if (argv['serve-root'] && !argv.root) {
console.error("You must specify bath --root to use --serve-root");
return;
}
if (argv.key || argv.cert || argv.root) {
if (!argv.key || !argv.cert) {
console.error("You must specify bath --key and --cert, and optionally --root (required with serve-root)");
return;
}
if (!Array.isArray(argv.root)) {
argv.root = [argv.root];
}
opts.key = fs.readFileSync(argv.key);
opts.cert = fs.readFileSync(argv.cert);
// turn multiple-cert pemfile into array of cert strings
peerCa = argv.root.reduce(function (roots, fullpath) {
if (!fs.existsSync(fullpath)) {
return roots;
}
return roots.concat(fs.readFileSync(fullpath, 'ascii')
.split('-----END CERTIFICATE-----')
.filter(function (ca) {
return ca.trim();
}).map(function (ca) {
return (ca + '-----END CERTIFICATE-----').trim();
}));
}, []);
if (argv['serve-root']) {
content = opts.ca.join('\r\n');
}
// TODO * `--verify /path/to/root.pem` require peers to present certificates from said authority
if (argv.verify) {
opts.ca = peerCa;
opts.requestCert = true;
opts.rejectUnauthorized = true;
}
}
opts.servername = 'localhost.daplie.com';
if (argv.servername) {
opts.servername = argv.servername;
}
opts.insecurePort = argv.i || argv['insecure-port'];
createServer(port, pubdir, content, opts);
}
if (require.main === module) {
run();
}