Browse Source

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.
0.8
Jeff Garzik 13 years ago committed by Jeff Garzik
parent
commit
613389019e
  1. 54
      src/bitcoinrpc.cpp

54
src/bitcoinrpc.cpp

@ -2952,6 +2952,39 @@ void JSONRequest::parse(const Value& valRequest)
throw JSONRPCError(-32600, "Params must be an array"); 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; static CCriticalSection cs_THREAD_RPCHANDLER;
void ThreadRPCServer3(void* parg) void ThreadRPCServer3(void* parg)
@ -3006,15 +3039,26 @@ void ThreadRPCServer3(void* parg)
{ {
// Parse request // Parse request
Value valRequest; Value valRequest;
if (!read_string(strRequest, valRequest) || valRequest.type() != obj_type) if (!read_string(strRequest, valRequest))
throw JSONRPCError(-32700, "Parse error"); 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
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");
// Send reply
string strReply = JSONRPCReply(result, Value::null, jreq.id);
conn->stream() << HTTPReply(200, strReply, fRun) << std::flush; conn->stream() << HTTPReply(200, strReply, fRun) << std::flush;
} }
catch (Object& objError) catch (Object& objError)

Loading…
Cancel
Save