HTTPS support (fix #16).

This commit is contained in:
Julien Fontanet 2013-10-21 16:52:44 +02:00
parent 302d9cb321
commit c8a47d7b99
3 changed files with 134 additions and 42 deletions

View File

@ -1,5 +1,10 @@
# Configuration of XO-Server's web server. # Configuration of XO-Server's HTTP server.
http: http:
# Is HTTP enabled?
#
# Default: true
#enabled: false
# Address on which the server is listening on. # Address on which the server is listening on.
# #
# Sets it to '127.0.0.1' to listen only on the local host. # Sets it to '127.0.0.1' to listen only on the local host.
@ -12,6 +17,34 @@ http:
# Default: 80 # Default: 80
#port: 8080 #port: 8080
# Configuration of XO-Server's HTTPS server.
https:
# Is HTTPS enabled?
#
# Default: false
#enabled: true
# Address on which the server is listening on.
#
# Sets it to '127.0.0.1' to listen only on the local host.
#
# Default: 0.0.0.0 (all addresses)
#host: '127.0.0.1'
# Port on which the server is listening on.
#
# Default: 443
#port: 8081
# File containing the certificate (PEM format).
#certificate: './certificate.pem'
# File containing the private key (PEM format).
#
# If the key is encrypted, the passphrase will be asked at server
# startup.
#key: './key.pem'
# Configuration of the Redis server. # Configuration of the Redis server.
redis: redis:
# Syntax: tcp://[db[:password]@]hostname[:port] # Syntax: tcp://[db[:password]@]hostname[:port]

View File

@ -1,8 +1,8 @@
var _ = require('underscore'); var _ = require('underscore');
var connect = require('connect'); var connect = require('connect');
var fs = require('fs');
var Q = require('q'); var Q = require('q');
var Session = require('./session'); var Session = require('./session');
var tcp = require('net');
var WSServer = require('ws').Server; var WSServer = require('ws').Server;
//-------------------------------------- //--------------------------------------
@ -12,7 +12,7 @@ var xo = require('./xo')();
var Api = require('./api'); var Api = require('./api');
var api = new Api(xo); var api = new Api(xo);
var http_serv; var http_servers = [];
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
@ -85,16 +85,18 @@ function json_api_call(session, message)
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
xo.on('started', function () { xo.on('started', function () {
http_serv.on('request', connect() http_servers.forEach(function (http_server) {
// Compresses reponses using GZip. http_server.on('request', connect()
.use(connect.compress()) // Compresses reponses using GZip.
.use(connect.compress())
// Caches the responses in memory. // Caches the responses in memory.
//.use(connect.staticCache()) //.use(connect.staticCache())
// Serve static files. // Serve static files.
.use(connect.static(__dirname +'/../public/http')) .use(connect.static(__dirname +'/../public/http'))
); );
});
}); });
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
@ -113,12 +115,8 @@ xo.on('started', function () {
// @todo Avoid Base64 encoding and directly use binary streams. // @todo Avoid Base64 encoding and directly use binary streams.
// xo.on('started', function () { // xo.on('started', function () {
// var server = new WSServer({ // function on_connection(socket)
// 'server': http_serv, // {
// 'path': '/websockify',
// });
// server.on('connection', function (socket) {
// // Parses the first message which SHOULD contains the host and // // Parses the first message which SHOULD contains the host and
// // port of the host to connect to. // // port of the host to connect to.
// socket.once('message', function (message) { // socket.once('message', function (message) {
@ -160,6 +158,14 @@ xo.on('started', function () {
// socket.on('error', function () { // socket.on('error', function () {
// socket.close(); // socket.close();
// }); // });
// }
// http_servers.forEach(function (http_server) {
// new WSServer({
// 'server': http_server,
// 'path': '/websockify',
// })
// .on('connection', on_connection);
// }); // });
// }); // });
@ -168,12 +174,8 @@ xo.on('started', function () {
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
xo.on('started', function () { xo.on('started', function () {
var server = new WSServer({ function on_connection(socket)
'server': http_serv, {
'path': '/api/',
});
server.on('connection', function (socket) {
var session = new Session(xo); var session = new Session(xo);
session.once('close', function () { session.once('close', function () {
socket.close(); socket.close();
@ -193,6 +195,13 @@ xo.on('started', function () {
socket.once('close', function () { socket.once('close', function () {
session.close(); session.close();
}); });
}
http_servers.forEach(function (http_server) {
new WSServer({
'server': http_server,
'path': '/api/',
}).on('connection', on_connection);
}); });
}); });
@ -323,20 +332,36 @@ var cfg = {
// Defaults values. // Defaults values.
cfg.merge({ cfg.merge({
'http': { 'http': {
'enabled': true,
'host': '0.0.0.0', 'host': '0.0.0.0',
'port': 80, 'port': 80,
}, },
'https': {
'enabled': false,
'host': '0.0.0.0',
'port': 443,
'certificate': './certificate.pem',
'key': './key.pem',
},
'redis': { 'redis': {
'uri': 'tcp://127.0.0.1:6379', 'uri': 'tcp://127.0.0.1:6379',
}, },
}); });
Q.ninvoke(require('fs'), 'readFile', __dirname +'/../config/local.yaml', {'encoding': 'utf8'}).then(function (data) { function read_file(file)
data = require('js-yaml').safeLoad(data); {
cfg.merge(data); return Q.ninvoke(fs, 'readFile', file, {'encoding': 'utf-8'});
}).fail(function (e) { }
console.error('[Warning] Reading config file: '+ e);
}).then(function () { read_file(__dirname +'/../config/local.yaml').then(
function (data) {
data = require('js-yaml').safeLoad(data);
cfg.merge(data);
},
function (e) {
console.error('[Warning] Reading config file: '+ e);
}
).then(function () {
if (cfg.get('users')) if (cfg.get('users'))
{ {
console.warn('[Warn] Users in config file are no longer supported.'); console.warn('[Warn] Users in config file are no longer supported.');
@ -346,12 +371,46 @@ Q.ninvoke(require('fs'), 'readFile', __dirname +'/../config/local.yaml', {'encod
console.warn('[Warn] Servers in config file are no longer supported.'); console.warn('[Warn] Servers in config file are no longer supported.');
} }
var host = cfg.get('http', 'host'); if (cfg.get('http', 'enabled'))
var port = cfg.get('http', 'port'); {
http_serv = require('http').createServer().listen(port, host).on('listening', function () { var host = cfg.get('http', 'host');
console.info('XO-Server Web server is listening on port '+ host +':'+ port +'.'); var port = cfg.get('http', 'port');
});
http_servers.push(
require('http').createServer().listen(port, host)
.on('listening', function () {
console.info(
'XO-Server HTTP server is listening on %s:%s',
host, port
);
})
);
}
if (cfg.get('https', 'enabled'))
{
return Q.all([
read_file(cfg.get('https', 'certificate')),
read_file(cfg.get('https', 'key')),
]).spread(function (certificate, key) {
var host = cfg.get('https', 'host');
var port = cfg.get('https', 'port');
http_servers.push(
require('https').createServer({
'cert': certificate,
'key': key,
}).listen(port, host)
.on('listening', function () {
console.info(
'XO-Server HTTPS server is listening on %s:%s',
host, port
);
})
);
});
}
}).then(function () {
xo.start(cfg); xo.start(cfg);
}).done(); }).done();

View File

@ -32,17 +32,17 @@ Xapi.prototype.call = function (method) {
return Q.ninvoke(self.xmlrpc, 'methodCall', method, params); return Q.ninvoke(self.xmlrpc, 'methodCall', method, params);
}).then(function (value) { }).then(function (value) {
if ('Success' !== value.Status) if (!value.Status)
{ {
if ('Failure' === value.Status) return value;
{
throw value.ErrorDescription;
}
throw value;
} }
return value.Value; if ('Success' === value.Status)
{
return value.Value;
}
throw value.ErrorDescription || value;
}).fail(function (error) { }).fail(function (error) {
// Gets the error code for transport errors and XAPI errors. // Gets the error code for transport errors and XAPI errors.