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.
This commit is contained in:
parent
c6494d82fa
commit
613389019e
@ -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");
|
||||
|
||||
string strReply;
|
||||
|
||||
// singleton request
|
||||
if (valRequest.type() == obj_type) {
|
||||
jreq.parse(valRequest);
|
||||
|
||||
Value result = tableRPC.execute(jreq.strMethod, jreq.params);
|
||||
|
||||
// Send reply
|
||||
string strReply = JSONRPCReply(result, Value::null, jreq.id);
|
||||
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)
|
||||
|
Loading…
Reference in New Issue
Block a user