http: add bitcoind-compatible json-rpc server.

This commit is contained in:
Christopher Jeffrey 2016-07-26 18:08:36 -07:00
parent e303ab4ee1
commit 91a1477aeb
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD
5 changed files with 1550 additions and 5 deletions

View File

@ -139,7 +139,9 @@ function Fullnode(options) {
port: this.options.httpPort || this.network.rpcPort,
host: this.options.httpHost || '0.0.0.0',
apiKey: this.options.apiKey,
walletAuth: this.options.walletAuth
walletAuth: this.options.walletAuth,
rpcUser: this.options.rpcUser,
rpcPassword: this.options.rpcPassword
});
}

1477
lib/bcoin/http/rpc.js Normal file

File diff suppressed because it is too large Load Diff

View File

@ -16,6 +16,7 @@ var http = require('./');
var HTTPBase = http.base;
var utils = require('../utils');
var assert = utils.assert;
var RPC; /*= require('./rpc'); - load lazily */
/**
* HTTPServer
@ -48,6 +49,9 @@ function HTTPServer(options) {
this.logger = options.logger || this.node.logger;
this.loaded = false;
this.apiKey = options.apiKey;
this.rpcUser = options.rpcUser;
this.rpcPassword = options.rpcPassword;
this.rpc = null;
if (this.apiKey) {
if (typeof this.apiKey === 'string') {
@ -126,8 +130,15 @@ HTTPServer.prototype._init = function _init() {
});
this.use(function(req, res, next, send) {
var params = utils.merge({}, req.params, req.query, req.body);
var options = {};
var params, options;
if (req.method === 'POST'
&& req.pathname === '/') {
return next();
}
params = utils.merge({}, req.params, req.query, req.body);
options = {};
self.logger.debug('Params:');
self.logger.debug(params);
@ -280,6 +291,42 @@ HTTPServer.prototype._init = function _init() {
return new bcoin.script(script);
}
// JSON RPC
this.post('/', function(req, res, next, send) {
if (req.body.method && req.body.params) {
if (self.rpcUser) {
if (!textCmp(req.username, self.rpcUser)
|| !textCmp(req.password, self.rpcPassword)) {
res.setHeader('WWW-Authenticate', 'Basic realm="rpc"');
send(401, { error: 'Bad auth.' });
return;
}
}
if (!self.rpc) {
RPC = require('./rpc');
self.rpc = new RPC(self.node);
}
return self.rpc.execute(req.body, function(err, json) {
if (err) {
return send(400, {
result: null,
error: err.message,
id: req.body.id
});
}
send(200, {
result: json,
error: null,
id: req.body.id
});
});
}
next(new Error('Method not found.'));
});
this.get('/', function(req, res, next, send) {
send(200, {
version: constants.USER_VERSION,
@ -1072,6 +1119,23 @@ ClientSocket.prototype.destroy = function() {
this.socket.disconnect();
};
/*
* Helpers
*/
function textCmp(a, b) {
if (!a)
return false;
if (!b)
return false;
a = new Buffer(a, 'utf8');
b = new Buffer(b, 'utf8');
return utils.ccmp(a, b);
}
/*
* Expose
*/

View File

@ -745,7 +745,7 @@ regtest.minRate = 10000;
regtest.maxRate = 40000;
regtest.selfConnect = false;
regtest.selfConnect = true;
regtest.requestMempool = true;

View File

@ -83,7 +83,9 @@ function SPVNode(options) {
port: this.options.httpPort || this.network.rpcPort,
host: this.options.httpHost || '0.0.0.0',
apiKey: this.options.apiKey,
walletAuth: this.options.walletAuth
walletAuth: this.options.walletAuth,
rpcUser: this.options.rpcUser,
rpcPassword: this.options.rpcPassword
});
}