diff --git a/lib/node.js b/lib/node.js index ef8a90aa..908f0978 100644 --- a/lib/node.js +++ b/lib/node.js @@ -32,6 +32,8 @@ function Node(config) { $.checkState(config.datadir, 'Node config expects "datadir"'); this.datadir = config.datadir; this.port = config.port; + this.https = config.https; + this.httpsOptions = config.httpsOptions; this._setNetwork(config); diff --git a/lib/scaffold/create.js b/lib/scaffold/create.js index b698e6a9..12491b92 100644 --- a/lib/scaffold/create.js +++ b/lib/scaffold/create.js @@ -25,8 +25,6 @@ var BASE_PACKAGE = { } }; -var BASE_BITCOIN_CONFIG = 'whitelist=127.0.0.1\n' + 'txindex=1\n'; - /** * Will create a directory and bitcoin.conf file for Bitcoin. * @param {String} dataDir - The absolute path @@ -38,12 +36,9 @@ function createBitcoinDirectory(datadir, done) { throw err; } - try { - fs.writeFileSync(datadir + '/bitcoin.conf', BASE_BITCOIN_CONFIG); - } catch(e) { - done(e); - } done(); + + // Don't create the configuration yet }); } diff --git a/lib/services/bitcoind.js b/lib/services/bitcoind.js index 5cd3319f..2eca3cb4 100644 --- a/lib/services/bitcoind.js +++ b/lib/services/bitcoind.js @@ -46,7 +46,13 @@ Bitcoin.prototype._loadConfiguration = function() { } if (!fs.existsSync(configPath)) { - fs.writeFileSync(configPath, Bitcoin.DEFAULT_CONFIG); + var defaultConfig = Bitcoin.DEFAULT_CONFIG; + if(this.node.https && this.node.httpsOptions) { + defaultConfig += 'rpcssl=1\n'; + defaultConfig += 'rpcsslprivatekeyfile=' + this.node.httpsOptions.key + '\n'; + defaultConfig += 'rpcsslcertificatechainfile=' + this.node.httpsOptions.cert + '\n'; + } + fs.writeFileSync(configPath, defaultConfig); } var file = fs.readFileSync(configPath); diff --git a/lib/services/web.js b/lib/services/web.js index b5b2bca5..28372953 100644 --- a/lib/services/web.js +++ b/lib/services/web.js @@ -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.node.https; + this.httpsOptions = options.httpsOptions || this.node.httpsOptions; this.port = options.port || this.node.port || 3456; this.node.on('ready', function() { @@ -31,7 +35,12 @@ WebService.prototype.start = function(callback) { this.app = express(); this.app.use(bodyParser.json()); - this.server = http.createServer(this.app); + if(this.https) { + this.transformHttpsOptions(); + 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 +195,15 @@ WebService.prototype.socketMessageHandler = function(message, socketCallback) { } }; +WebService.prototype.transformHttpsOptions = function() { + if(!this.httpsOptions || !this.httpsOptions.key || !this.httpsOptions.cert) { + throw new Error('Missing https options'); + } + + this.httpsOptions = { + key: fs.readFileSync(this.httpsOptions.key), + cert: fs.readFileSync(this.httpsOptions.cert) + }; +}; + module.exports = WebService; diff --git a/test/scaffold/create.integration.js b/test/scaffold/create.integration.js index ffa01224..10378806 100644 --- a/test/scaffold/create.integration.js +++ b/test/scaffold/create.integration.js @@ -70,11 +70,9 @@ describe('#create', function() { var configPath = testDir + '/mynode/bitcore-node.json'; var packagePath = testDir + '/mynode/package.json'; - var bitcoinConfig = testDir + '/mynode/data/bitcoin.conf'; should.equal(fs.existsSync(configPath), true); should.equal(fs.existsSync(packagePath), true); - should.equal(fs.existsSync(bitcoinConfig), true); var config = JSON.parse(fs.readFileSync(configPath)); config.services.should.deep.equal(['bitcoind', 'db', 'address', 'web']); @@ -103,26 +101,6 @@ describe('#create', function() { }); - it('will not create bitcoin.conf if it already exists', function() { - - create({ - cwd: testDir, - dirname: 'mynode2', - name: 'My Node 2', - isGlobal: false, - datadir: '../.bitcoin' - }, function(err) { - if (err) { - throw err; - } - - var bitcoinConfig = testDir + '/.bitcoin/bitcoin.conf'; - should.equal(fs.existsSync(bitcoinConfig), false); - - }); - - }); - it('will not create a package.json if globally installed', function() { create({ diff --git a/test/services/bitcoind.unit.js b/test/services/bitcoind.unit.js index 0704c1ce..87633edc 100644 --- a/test/services/bitcoind.unit.js +++ b/test/services/bitcoind.unit.js @@ -75,6 +75,36 @@ describe('Bitcoin Service', function() { bitcoind._loadConfiguration({datadir: './test'}); }).should.throw('Txindex option'); }); + it('should set https options if node https options are set', function() { + var writeFileSync = function(path, config) { + config.should.equal('whitelist=127.0.0.1\ntxindex=1\nrpcssl=1\nrpcsslprivatekeyfile=key.pem\nrpcsslcertificatechainfile=cert.pem\n'); + }; + var TestBitcoin = proxyquire('../../lib/services/bitcoind', { + fs: { + writeFileSync: writeFileSync, + readFileSync: readFileSync, + existsSync: sinon.stub().returns(false) + }, + mkdirp: { + sync: sinon.stub() + } + }); + var config = { + node: { + datadir: 'testdir', + network: { + name: 'regtest' + }, + https: true, + httpsOptions: { + key: 'key.pem', + cert: 'cert.pem' + } + } + }; + var bitcoind = new TestBitcoin(config); + bitcoind._loadConfiguration({datadir: process.env.HOME + '/.bitcoin'}); + }); describe('reindex', function() { var log = require('../../lib/').log; var stub; diff --git a/test/services/web.unit.js b/test/services/web.unit.js index b0c34eaf..736bed2d 100644 --- a/test/services/web.unit.js +++ b/test/services/web.unit.js @@ -2,17 +2,64 @@ 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 fakeSocketListener = new EventEmitter(); +var fakeSocket = new EventEmitter(); + +fakeSocket.on('test/event1', function(data) { + data.should.equal('testdata'); + done(); +}); + +fakeSocketListener.emit('connection', fakeSocket); + +fakeSocket.emit('subscribe', 'test/event1'); + + + +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) { + beforeEach(function() { + httpStub.createServer.reset(); + httpsStub.createServer.reset(); + }); + it('should create an http server if no options are specified and node is not configured for https', function(done) { var web = new WebService({node: defaultNode}); + 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 node is configured for https', function(done) { + var node = new EventEmitter(); + node.https = true; + + var web = new WebService({node: node}); + web.transformHttpsOptions = sinon.spy(); + web.start(function(err) { + should.not.exist(err); + httpsStub.createServer.called.should.equal(true); done(); }); }); @@ -291,4 +338,34 @@ describe('WebService', function() { }); }); + describe('#deriveHttpsOptions', function() { + it('should read key and cert from files specified', function() { + var web = new WebService({ + node: defaultNode, + https: true, + httpsOptions: { + key: 'key', + cert: 'cert' + } + }); + + web.transformHttpsOptions(); + web.httpsOptions.key.should.equal('key-buffer'); + web.httpsOptions.cert.should.equal('cert-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.transformHttpsOptions(); + }).should.throw('Missing https options'); + }); + }); + }); \ No newline at end of file