mirror of
https://github.com/dashpay/dash.git
synced 2024-12-28 13:32:47 +01:00
Merge pull request #1512 from jgarzik/json-batch
Support JSON-RPC 2.0 request batches
This commit is contained in:
commit
c729dbb6d2
@ -2552,7 +2552,7 @@ string JSONRPCRequest(const string& strMethod, const Array& params, const Value&
|
|||||||
return write_string(Value(request), false) + "\n";
|
return write_string(Value(request), false) + "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
string JSONRPCReply(const Value& result, const Value& error, const Value& id)
|
Object JSONRPCReplyObj(const Value& result, const Value& error, const Value& id)
|
||||||
{
|
{
|
||||||
Object reply;
|
Object reply;
|
||||||
if (error.type() != null_type)
|
if (error.type() != null_type)
|
||||||
@ -2561,6 +2561,12 @@ string JSONRPCReply(const Value& result, const Value& error, const Value& id)
|
|||||||
reply.push_back(Pair("result", result));
|
reply.push_back(Pair("result", result));
|
||||||
reply.push_back(Pair("error", error));
|
reply.push_back(Pair("error", error));
|
||||||
reply.push_back(Pair("id", id));
|
reply.push_back(Pair("id", id));
|
||||||
|
return reply;
|
||||||
|
}
|
||||||
|
|
||||||
|
string JSONRPCReply(const Value& result, const Value& error, const Value& id)
|
||||||
|
{
|
||||||
|
Object reply = JSONRPCReplyObj(result, error, id);
|
||||||
return write_string(Value(reply), false) + "\n";
|
return write_string(Value(reply), false) + "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2905,6 +2911,80 @@ void ThreadRPCServer2(void* parg)
|
|||||||
StopRequests();
|
StopRequests();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class JSONRequest
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Value id;
|
||||||
|
string strMethod;
|
||||||
|
Array params;
|
||||||
|
|
||||||
|
JSONRequest() { id = Value::null; }
|
||||||
|
void parse(const Value& valRequest);
|
||||||
|
};
|
||||||
|
|
||||||
|
void JSONRequest::parse(const Value& valRequest)
|
||||||
|
{
|
||||||
|
// Parse request
|
||||||
|
if (valRequest.type() != obj_type)
|
||||||
|
throw JSONRPCError(-32600, "Invalid Request object");
|
||||||
|
const Object& request = valRequest.get_obj();
|
||||||
|
|
||||||
|
// Parse id now so errors from here on will have the id
|
||||||
|
id = find_value(request, "id");
|
||||||
|
|
||||||
|
// Parse method
|
||||||
|
Value valMethod = find_value(request, "method");
|
||||||
|
if (valMethod.type() == null_type)
|
||||||
|
throw JSONRPCError(-32600, "Missing method");
|
||||||
|
if (valMethod.type() != str_type)
|
||||||
|
throw JSONRPCError(-32600, "Method must be a string");
|
||||||
|
strMethod = valMethod.get_str();
|
||||||
|
if (strMethod != "getwork" && strMethod != "getmemorypool")
|
||||||
|
printf("ThreadRPCServer method=%s\n", strMethod.c_str());
|
||||||
|
|
||||||
|
// Parse params
|
||||||
|
Value valParams = find_value(request, "params");
|
||||||
|
if (valParams.type() == array_type)
|
||||||
|
params = valParams.get_array();
|
||||||
|
else if (valParams.type() == null_type)
|
||||||
|
params = Array();
|
||||||
|
else
|
||||||
|
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)
|
||||||
@ -2954,52 +3034,41 @@ void ThreadRPCServer3(void* parg)
|
|||||||
if (mapHeaders["connection"] == "close")
|
if (mapHeaders["connection"] == "close")
|
||||||
fRun = false;
|
fRun = false;
|
||||||
|
|
||||||
Value id = Value::null;
|
JSONRequest jreq;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// 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");
|
||||||
const Object& request = valRequest.get_obj();
|
|
||||||
|
|
||||||
// Parse id now so errors from here on will have the id
|
string strReply;
|
||||||
id = find_value(request, "id");
|
|
||||||
|
|
||||||
// Parse method
|
// singleton request
|
||||||
Value valMethod = find_value(request, "method");
|
if (valRequest.type() == obj_type) {
|
||||||
if (valMethod.type() == null_type)
|
jreq.parse(valRequest);
|
||||||
throw JSONRPCError(-32600, "Missing method");
|
|
||||||
if (valMethod.type() != str_type)
|
|
||||||
throw JSONRPCError(-32600, "Method must be a string");
|
|
||||||
string strMethod = valMethod.get_str();
|
|
||||||
if (strMethod != "getwork" && strMethod != "getmemorypool")
|
|
||||||
printf("ThreadRPCServer method=%s\n", strMethod.c_str());
|
|
||||||
|
|
||||||
// Parse params
|
Value result = tableRPC.execute(jreq.strMethod, jreq.params);
|
||||||
Value valParams = find_value(request, "params");
|
|
||||||
Array params;
|
// Send reply
|
||||||
if (valParams.type() == array_type)
|
strReply = JSONRPCReply(result, Value::null, jreq.id);
|
||||||
params = valParams.get_array();
|
|
||||||
else if (valParams.type() == null_type)
|
// array of requests
|
||||||
params = Array();
|
} else if (valRequest.type() == array_type)
|
||||||
|
strReply = JSONRPCExecBatch(valRequest.get_array());
|
||||||
else
|
else
|
||||||
throw JSONRPCError(-32600, "Params must be an array");
|
throw JSONRPCError(-32700, "Top-level object parse error");
|
||||||
|
|
||||||
Value result = tableRPC.execute(strMethod, params);
|
|
||||||
|
|
||||||
// Send reply
|
|
||||||
string strReply = JSONRPCReply(result, Value::null, id);
|
|
||||||
conn->stream() << HTTPReply(200, strReply, fRun) << std::flush;
|
conn->stream() << HTTPReply(200, strReply, fRun) << std::flush;
|
||||||
}
|
}
|
||||||
catch (Object& objError)
|
catch (Object& objError)
|
||||||
{
|
{
|
||||||
ErrorReply(conn->stream(), objError, id);
|
ErrorReply(conn->stream(), objError, jreq.id);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
catch (std::exception& e)
|
catch (std::exception& e)
|
||||||
{
|
{
|
||||||
ErrorReply(conn->stream(), JSONRPCError(-32700, e.what()), id);
|
ErrorReply(conn->stream(), JSONRPCError(-32700, e.what()), jreq.id);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user