From b025f5c2411d4d99af1fbcf942aab4a8e451de87 Mon Sep 17 00:00:00 2001 From: Christopher Jeffrey Date: Wed, 14 Dec 2016 07:05:24 -0800 Subject: [PATCH] http: allow batched rpc calls. --- lib/http/server.js | 107 +++++++++++++++++++++++++++++++-------------- 1 file changed, 73 insertions(+), 34 deletions(-) diff --git a/lib/http/server.js b/lib/http/server.js index c8e48d3a..0afa86c1 100644 --- a/lib/http/server.js +++ b/lib/http/server.js @@ -203,10 +203,6 @@ HTTPServer.prototype._init = function _init() { var i, params, options, censored, output, address; if (req.method === 'POST' && req.pathname === '/') { - enforce(typeof req.body.method === 'string', 'Method must be a string.'); - if (!req.body.params) - req.body.params = []; - enforce(Array.isArray(req.body.params), 'Params must be an array.'); req.options = {}; return next(); } @@ -541,50 +537,93 @@ HTTPServer.prototype._init = function _init() { // JSON RPC this.post('/', con(function* (req, res, send, next) { - var json; + var out = []; + var cmds = req.body; + var array = true; + var i, cmd, json; if (!this.rpc) { RPC = require('./rpc'); this.rpc = new RPC(this.node); } - this.logger.debug('RPC call for %s:', req.pathname); - this.logger.debug(req.body); - - if (req.body.method === 'getwork') { - res.setHeader('X-Long-Polling', '/?longpoll=1'); - if (req.query.longpoll) - req.body.method = 'getworklp'; + if (!Array.isArray(cmds)) { + cmds = [cmds]; + array = false; } - try { - json = yield this.rpc.execute(req.body); - } catch (err) { - this.logger.error(err); + for (i = 0; i < cmds.length; i++) { + cmd = cmds[i]; - if (err.type === 'RPCError') { - return send(400, { - result: err.message, - error: null, - id: req.body.id - }); + enforce(cmd && typeof cmd === 'object', 'Command must be an object.'); + enforce(typeof cmd.method === 'string', 'Method must be a string.'); + + if (!cmd.params) + cmd.params = []; + + enforce(Array.isArray(cmd.params), 'Params must be an array.'); + + if (!cmd.id) + cmd.id = 0; + + enforce(typeof cmd.id === 'number', 'ID must be a number.'); + } + + this.logger.debug('Handling %d RPC calls.', cmds.length); + + for (i = 0; i < cmds.length; i++) { + cmd = cmds[i]; + + if (cmd.method === 'getwork') { + res.setHeader('X-Long-Polling', '/?longpoll=1'); + if (req.query.longpoll) + cmd.method = 'getworklp'; } - return send(500, { - result: null, - error: { - message: err.message, - code: 1 - }, - id: req.body.id + this.logger.debug(cmd); + + try { + json = yield this.rpc.execute(cmd); + } catch (err) { + this.logger.error(err); + + if (err.type === 'RPCError') { + out.push({ + result: null, + error: { + message: err.message, + code: -1 + }, + id: cmd.id + }); + continue; + } + + out.push({ + result: null, + error: { + message: err.message, + code: 1 + }, + id: cmd.id + }); + + continue; + } + + out.push({ + result: json != null ? json : null, + error: null, + id: cmd.id }); } - send(200, { - result: json != null ? json : null, - error: null, - id: req.body.id - }); + if (!array) { + send(200, out[0]); + return; + } + + send(200, out); })); this.get('/', function(req, res, send, next) {