Skip to content

Commit a64a2b7

Browse files
pinheadmzryanofsky
authored andcommitted
rpc: refactor single/batch requests
Simplify the request handling flow so that errors and results only come from JSONRPCExec()
1 parent df6e375 commit a64a2b7

File tree

3 files changed

+24
-35
lines changed

3 files changed

+24
-35
lines changed

src/httprpc.cpp

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ static bool HTTPReq_JSONRPC(const std::any& context, HTTPRequest* req)
185185
// Set the URI
186186
jreq.URI = req->GetURI();
187187

188-
std::string strReply;
188+
UniValue reply;
189189
bool user_has_whitelist = g_rpc_whitelist.count(jreq.authUser);
190190
if (!user_has_whitelist && g_rpc_whitelist_default) {
191191
LogPrintf("RPC User %s not allowed to call any methods\n", jreq.authUser);
@@ -200,13 +200,12 @@ static bool HTTPReq_JSONRPC(const std::any& context, HTTPRequest* req)
200200
req->WriteReply(HTTP_FORBIDDEN);
201201
return false;
202202
}
203-
UniValue result = tableRPC.execute(jreq);
204203

205-
// Send reply
206-
strReply = JSONRPCReplyObj(std::move(result), NullUniValue, jreq.id).write() + "\n";
204+
reply = JSONRPCExec(jreq);
207205

208206
// array of requests
209207
} else if (valRequest.isArray()) {
208+
// Check authorization for each request's method
210209
if (user_has_whitelist) {
211210
for (unsigned int reqIdx = 0; reqIdx < valRequest.size(); reqIdx++) {
212211
if (!valRequest[reqIdx].isObject()) {
@@ -223,13 +222,26 @@ static bool HTTPReq_JSONRPC(const std::any& context, HTTPRequest* req)
223222
}
224223
}
225224
}
226-
strReply = JSONRPCExecBatch(jreq, valRequest.get_array());
225+
226+
// Execute each request
227+
reply = UniValue::VARR;
228+
for (size_t i{0}; i < valRequest.size(); ++i) {
229+
// Batches include errors in the batch response, they do not throw
230+
try {
231+
jreq.parse(valRequest[i]);
232+
reply.push_back(JSONRPCExec(jreq));
233+
} catch (UniValue& e) {
234+
reply.push_back(JSONRPCReplyObj(NullUniValue, std::move(e), jreq.id));
235+
} catch (const std::exception& e) {
236+
reply.push_back(JSONRPCReplyObj(NullUniValue, JSONRPCError(RPC_PARSE_ERROR, e.what()), jreq.id));
237+
}
238+
}
227239
}
228240
else
229241
throw JSONRPCError(RPC_PARSE_ERROR, "Top-level object parse error");
230242

231243
req->WriteHeader("Content-Type", "application/json");
232-
req->WriteReply(HTTP_OK, strReply);
244+
req->WriteReply(HTTP_OK, reply.write() + "\n");
233245
} catch (UniValue& e) {
234246
JSONErrorReply(req, std::move(e), jreq.id);
235247
return false;

src/rpc/server.cpp

Lines changed: 5 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -358,36 +358,13 @@ bool IsDeprecatedRPCEnabled(const std::string& method)
358358
return find(enabled_methods.begin(), enabled_methods.end(), method) != enabled_methods.end();
359359
}
360360

361-
static UniValue JSONRPCExecOne(JSONRPCRequest jreq, const UniValue& req)
361+
UniValue JSONRPCExec(const JSONRPCRequest& jreq)
362362
{
363-
UniValue rpc_result(UniValue::VOBJ);
363+
// Might throw exception. Single requests will throw and send HTTP error codes
364+
// but inside a batch, we just include the error object and return HTTP 200
365+
UniValue result = tableRPC.execute(jreq);
364366

365-
try {
366-
jreq.parse(req);
367-
368-
UniValue result = tableRPC.execute(jreq);
369-
rpc_result = JSONRPCReplyObj(std::move(result), NullUniValue, jreq.id);
370-
}
371-
catch (UniValue& e)
372-
{
373-
rpc_result = JSONRPCReplyObj(NullUniValue, std::move(e), jreq.id);
374-
}
375-
catch (const std::exception& e)
376-
{
377-
rpc_result = JSONRPCReplyObj(NullUniValue,
378-
JSONRPCError(RPC_PARSE_ERROR, e.what()), jreq.id);
379-
}
380-
381-
return rpc_result;
382-
}
383-
384-
std::string JSONRPCExecBatch(const JSONRPCRequest& jreq, const UniValue& vReq)
385-
{
386-
UniValue ret(UniValue::VARR);
387-
for (unsigned int reqIdx = 0; reqIdx < vReq.size(); reqIdx++)
388-
ret.push_back(JSONRPCExecOne(jreq, vReq[reqIdx]));
389-
390-
return ret.write() + "\n";
367+
return JSONRPCReplyObj(std::move(result), NullUniValue, jreq.id);
391368
}
392369

393370
/**

src/rpc/server.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ extern CRPCTable tableRPC;
181181
void StartRPC();
182182
void InterruptRPC();
183183
void StopRPC();
184-
std::string JSONRPCExecBatch(const JSONRPCRequest& jreq, const UniValue& vReq);
184+
UniValue JSONRPCExec(const JSONRPCRequest& jreq);
185185

186186
// Drop witness when serializing for RPC?
187187
bool RPCSerializationWithoutWitness();

0 commit comments

Comments
 (0)