aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff Garzik <jgarzik@exmulti.com>2012-06-24 02:01:28 -0400
committerJeff Garzik <jgarzik@redhat.com>2012-07-03 22:53:57 -0400
commit613389019e6e3c0e903f78f6186d598c5194c395 (patch)
tree4ee9314b7d5f8bce126101308142b5784bc7f9a2
parentc6494d82fa31913eb075b222293e87ae40c9f9b2 (diff)
RPC: add support for JSON-RPC 2.0-style request batching
If the top-level object is an array, it is assumed to be an array of JSON-RPC requests. An array is returned, containing one response (error or not) per request, in the order submitted. In a slight change in semantics, batched requests -always- return an HTTP 200 OK status, even ones full of invalid or incorrect requests.
-rw-r--r--src/bitcoinrpc.cpp54
1 files changed, 49 insertions, 5 deletions
diff --git a/src/bitcoinrpc.cpp b/src/bitcoinrpc.cpp
index 134c3be93f..109cb92f32 100644
--- a/src/bitcoinrpc.cpp
+++ b/src/bitcoinrpc.cpp
@@ -2952,6 +2952,39 @@ void JSONRequest::parse(const Value& valRequest)
throw JSONRPCError(-32600, "Params must be an array");
}
+static Object JSONRPCExecOne(const Value& req)
+{
+ Object rpc_result;
+
+ JSONRequest jreq;
+ try {
+ jreq.parse(req);
+
+ Value result = tableRPC.execute(jreq.strMethod, jreq.params);
+ rpc_result = JSONRPCReplyObj(result, Value::null, jreq.id);
+ }
+ catch (Object& objError)
+ {
+ rpc_result = JSONRPCReplyObj(Value::null, objError, jreq.id);
+ }
+ catch (std::exception& e)
+ {
+ rpc_result = JSONRPCReplyObj(Value::null,
+ JSONRPCError(-32700, e.what()), jreq.id);
+ }
+
+ return rpc_result;
+}
+
+static string JSONRPCExecBatch(const Array& vReq)
+{
+ Array ret;
+ for (unsigned int reqIdx = 0; reqIdx < vReq.size(); reqIdx++)
+ ret.push_back(JSONRPCExecOne(vReq[reqIdx]));
+
+ return write_string(Value(ret), false) + "\n";
+}
+
static CCriticalSection cs_THREAD_RPCHANDLER;
void ThreadRPCServer3(void* parg)
@@ -3006,15 +3039,26 @@ void ThreadRPCServer3(void* parg)
{
// Parse request
Value valRequest;
- if (!read_string(strRequest, valRequest) || valRequest.type() != obj_type)
+ if (!read_string(strRequest, valRequest))
throw JSONRPCError(-32700, "Parse error");
- jreq.parse(valRequest);
+ string strReply;
+
+ // singleton request
+ if (valRequest.type() == obj_type) {
+ jreq.parse(valRequest);
- Value result = tableRPC.execute(jreq.strMethod, jreq.params);
+ Value result = tableRPC.execute(jreq.strMethod, jreq.params);
- // Send reply
- string strReply = JSONRPCReply(result, Value::null, jreq.id);
+ // Send reply
+ strReply = JSONRPCReply(result, Value::null, jreq.id);
+
+ // array of requests
+ } else if (valRequest.type() == array_type)
+ strReply = JSONRPCExecBatch(valRequest.get_array());
+ else
+ throw JSONRPCError(-32700, "Top-level object parse error");
+
conn->stream() << HTTPReply(200, strReply, fRun) << std::flush;
}
catch (Object& objError)