add https to web service

This commit is contained in:
Patrick Nagurny 2015-09-09 16:39:21 -04:00
parent cd73763610
commit 5677964651
2 changed files with 142 additions and 5 deletions

View File

@ -1,6 +1,7 @@
'use strict';
var http = require('http');
var https = require('https');
var express = require('express');
var bodyParser = require('body-parser');
var socketio = require('socket.io');
@ -8,10 +9,13 @@ var BaseService = require('../service');
var inherits = require('util').inherits;
var index = require('../');
var log = index.log;
var fs = require('fs');
var WebService = function(options) {
var self = this;
this.node = options.node;
this.https = options.https;
this.httpsOptions = options.httpsOptions;
this.port = options.port || this.node.port || 3456;
this.node.on('ready', function() {
@ -24,14 +28,24 @@ var WebService = function(options) {
inherits(WebService, BaseService);
WebService.dependencies = [];
WebService.dependencies = ['bitcoind'];
WebService.prototype.start = function(callback) {
var self = this;
this.app = express();
this.app.use(bodyParser.json());
// If https options are not specified, default to https if bitcoind is using https
if(this.https === undefined && this.node.services.bitcoind.configuration.rpcssl) {
this.https = true;
}
if(this.https) {
this.deriveHttpsOptions();
this.server = https.createServer(this.httpsOptions, this.app);
} else {
this.server = http.createServer(this.app);
}
this.io = socketio.listen(this.server);
this.io.on('connection', this.socketHandler.bind(this));
@ -186,4 +200,28 @@ WebService.prototype.socketMessageHandler = function(message, socketCallback) {
}
};
WebService.prototype.deriveHttpsOptions = function() {
var options = {};
var keyFile;
var certFile;
if(this.httpsOptions) {
keyFile = this.httpsOptions.key;
certFile = this.httpsOptions.cert;
} else {
keyFile = this.node.services.bitcoind.configuration.rpcsslprivatekeyfile;
certFile = this.node.services.bitcoind.configuration.rpcsslcertificatechainfile;
}
if(!keyFile || !certFile) {
throw new Error('Missing https options');
}
options.key = fs.readFileSync(keyFile);
options.cert = fs.readFileSync(certFile);
this.httpsOptions = options;
};
module.exports = WebService;

View File

@ -2,17 +2,65 @@
var should = require('chai').should();
var sinon = require('sinon');
var WebService = require('../../lib/services/web');
var EventEmitter = require('events').EventEmitter;
var proxyquire = require('proxyquire');
var httpStub = {
createServer: sinon.spy()
};
var httpsStub = {
createServer: sinon.spy()
};
var fsStub = {
readFileSync: function(arg1) {
return arg1 + '-buffer';
}
};
var WebService = proxyquire('../../lib/services/web', {http: httpStub, https: httpsStub, fs: fsStub});
describe('WebService', function() {
var defaultNode = new EventEmitter();
describe('#start', function() {
it('should call the callback with no error', function(done) {
var web = new WebService({node: defaultNode});
beforeEach(function() {
httpStub.createServer.reset();
httpsStub.createServer.reset();
});
it('should create an http server if no options are specified and bitcoind is not configured for https', function(done) {
var node = new EventEmitter();
node.services = {
bitcoind: {
configuration: {
rpcssl: 0
}
}
};
var web = new WebService({node: node});
web.deriveHttpsOptions = sinon.spy();
web.start(function(err) {
should.not.exist(err);
httpStub.createServer.called.should.equal(true);
done();
});
});
it('should create an https server if no options are specified and bitcoind is configured for https', function(done) {
var node = new EventEmitter();
node.services = {
bitcoind: {
configuration: {
rpcssl: 1
}
}
};
var web = new WebService({node: node});
web.deriveHttpsOptions = sinon.spy();
web.start(function(err) {
should.not.exist(err);
httpsStub.createServer.called.should.equal(true);
done();
});
});
@ -291,4 +339,55 @@ describe('WebService', function() {
});
});
describe('#deriveHttpsOptions', function() {
it('should use the httpsOptions from the config if specified', function() {
var web = new WebService({
node: defaultNode,
https: true,
httpsOptions: {
key: 'key',
cert: 'cert'
}
});
web.deriveHttpsOptions();
web.httpsOptions.key.should.equal('key-buffer');
web.httpsOptions.cert.should.equal('cert-buffer');
});
it('should use bitcoind\'s https options if there is no config', function() {
var node = new EventEmitter();
node.services = {
bitcoind: {
configuration: {
rpcssl: 1,
rpcsslprivatekeyfile: 'rpckey',
rpcsslcertificatechainfile: 'rpccert'
}
}
};
var web = new WebService({
node: node
});
web.deriveHttpsOptions();
web.httpsOptions.key.should.equal('rpckey-buffer');
web.httpsOptions.cert.should.equal('rpccert-buffer');
});
it('should throw an error if https is specified but key or cert is not specified', function() {
var web = new WebService({
node: defaultNode,
https: true,
httpsOptions: {
key: 'key'
}
});
(function() {
web.deriveHttpsOptions();
}).should.throw('Missing https options');
});
});
});