Merge pull request #213 from pnagurny/feature/https
Add https to web service
This commit is contained in:
commit
c5dfc26b28
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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({
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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');
|
||||
});
|
||||
});
|
||||
|
||||
});
|
Loading…
Reference in New Issue