From dfef2b862fdc25b5d2b8a088114c4df8a6731e8b Mon Sep 17 00:00:00 2001 From: Alex Kocharin Date: Sat, 28 Mar 2015 17:20:58 +0300 Subject: [PATCH] add a possibility to listen on multiple ports --- lib/cli.js | 125 +++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 93 insertions(+), 32 deletions(-) diff --git a/lib/cli.js b/lib/cli.js index 033891ea3..1d2627e88 100644 --- a/lib/cli.js +++ b/lib/cli.js @@ -25,6 +25,7 @@ var http = require('http') var https = require('https') var YAML = require('js-yaml') var Path = require('path') +var URL = require('url') var server = require('./index') var pkg_file = '../package.yaml' var pkg = YAML.safeLoad(fs.readFileSync(__dirname+'/'+ pkg_file, 'utf8')) @@ -60,55 +61,115 @@ try { afterConfigLoad() -function get_hostport() { +function get_listen_addresses() { // command line || config file || default - var hostport = commander.listen || String(config.listen || '') || '4873' + var addresses - hostport = hostport.split(':') - if (hostport.length < 2) { - hostport = [ undefined, hostport[0] ] + if (commander.listen) { + addresses = [ commander.listen ] + } else if (Array.isArray(config.listen)) { + addresses = config.listen + } else if (config.listen) { + addresses = [ config.listen ] + } else { + addresses = [ '4873' ] } - if (hostport[0] == null) { - hostport[0] = 'localhost' - } - return hostport + + addresses = addresses.map(function(addr) { + // + // Allow: + // + // - https:localhost:1234 - protocol + host + port + // - localhost:1234 - host + port + // - 1234 - port + // - http::1234 - protocol + port + // - https://localhost:443/ - full url + // + var m = /^((https?):(\/\/)?)?(([^\/:]+):)?(\d+)\/?$/.exec(addr) + + if (!m) { + logger.logger.warn({ addr: addr }, + 'invalid address - @{addr}, we expect a port (e.g. "4873"),' + + ' host:port (e.g. "localhost:4873") or full url' + + ' (e.g. "http://localhost:4873/")') + return + } + + return { + proto: m[2] || 'http', + host: m[5] || 'localhost', + port: m[6] || '4873', + } + }).filter(Boolean) + + return addresses } function afterConfigLoad() { if (!config.self_path) config.self_path = Path.resolve(config_path) if (!config.https) config.https = { enable: false }; - var hostport = get_hostport() - var app = server(config); - var webServer; + var app = server(config) - if (config.https.enable === true) { // https - try { - webServer = https.createServer({ + get_listen_addresses().forEach(function(addr) { + var webServer + + if (addr.proto === 'https') { // https + if (!config.https || !config.https.key || !config.https.cert) { + var conf_path = function(file) { + if (!file) return config_path + return Path.resolve(Path.dirname(config_path), file) + } + + logger.logger.fatal([ + 'You need to specify "https.key" and "https.cert" to run https server', + '', + // commands are borrowed from node.js docs + 'To quickly create self-signed certificate, use:', + ' $ openssl genrsa -out ' + conf_path('sinopia-key.pem') + ' 2048', + ' $ openssl req -new -sha256 -key ' + conf_path('sinopia-key.pem') + ' -out ' + conf_path('sinopia-csr.pem'), + ' $ openssl x509 -req -in ' + conf_path('sinopia-csr.pem') + ' -signkey ' + conf_path('sinopia-key.pem') + ' -out ' + conf_path('sinopia-cert.pem'), + '', + 'And then add to config file (' + conf_path() + '):', + ' https:', + ' key: sinopia-key.pem', + ' cert: sinopia-cert.pem', + ].join('\n')) + process.exit(2) + } + + try { + webServer = https.createServer({ secureProtocol: 'SSLv23_method', // disable insecure SSLv2 and SSLv3 secureOptions: constants.SSL_OP_NO_SSLv2 | constants.SSL_OP_NO_SSLv3, key: fs.readFileSync(config.https.key), cert: fs.readFileSync(config.https.cert) - }, app); - } catch (err) { // catch errors related to certificate loading - logger.logger.fatal({err: err}, 'cannot create server: @{err.message}') - process.exit(2) + }, app) + } catch (err) { // catch errors related to certificate loading + logger.logger.fatal({ err: err }, 'cannot create server: @{err.message}') + process.exit(2) + } + } else { // http + webServer = http.createServer(app); } - } else { // http - webServer = http.createServer(app); - } - webServer - .listen(hostport[1], hostport[0]) - .on('error', function(err) { - logger.logger.fatal({ err: err }, 'cannot create server: @{err.message}') - process.exit(2) - }) + webServer + .listen(addr.port, addr.host) + .on('error', function(err) { + logger.logger.fatal({ err: err }, 'cannot create server: @{err.message}') + process.exit(2) + }) - logger.logger.warn({ - addr: (config.https.enable === true ? 'https' : 'http') + '://'+hostport[0]+':'+hostport[1]+'/', - version: 'Sinopia/'+pkg.version, - }, 'http address - @{addr}') + logger.logger.warn({ + addr: URL.format({ + protocol: addr.proto, + hostname: addr.host, + port: addr.port, + pathname: '/', + }), + version: 'Sinopia/'+pkg.version, + }, 'http address - @{addr}') + }) // undocumented stuff for tests if (typeof(process.send) === 'function') {