static bool HTTPReq_JSONRPC(HTTPRequest* req, const std::string &) { // JSONRPC handles only POST if (req->GetRequestMethod() != HTTPRequest::POST) { req->WriteReply(HTTP_BAD_METHOD, "JSONRPC server handles only POST requests"); return false; } // Check authorization std::pair<bool, std::string> authHeader = req->GetHeader("authorization"); if (!authHeader.first) { req->WriteReply(HTTP_UNAUTHORIZED); return false; } if (!RPCAuthorized(authHeader.second)) { LogPrintf("ThreadRPCServer incorrect password attempt from %s\n", req->GetPeer().ToString()); /* Deter brute-forcing If this results in a DoS the user really shouldn't have their RPC port exposed. */ MilliSleep(250); req->WriteReply(HTTP_UNAUTHORIZED); return false; } JSONRequest jreq; try { // Parse request UniValue valRequest; if (!valRequest.read(req->ReadBody())) throw JSONRPCError(RPC_PARSE_ERROR, "Parse error"); std::string strReply; // singleton request if (valRequest.isObject()) { jreq.parse(valRequest); UniValue result = tableRPC.execute(jreq.strMethod, jreq.params); // Send reply strReply = JSONRPCReply(result, NullUniValue, jreq.id); // array of requests } else if (valRequest.isArray()) strReply = JSONRPCExecBatch(valRequest.get_array()); else throw JSONRPCError(RPC_PARSE_ERROR, "Top-level object parse error"); req->WriteHeader("Content-Type", "application/json"); req->WriteReply(HTTP_OK, strReply); } catch (const UniValue& objError) { JSONErrorReply(req, objError, jreq.id); return false; } catch (const std::exception& e) { JSONErrorReply(req, JSONRPCError(RPC_PARSE_ERROR, e.what()), jreq.id); return false; } return true; }
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(RPC_PARSE_ERROR, e.what()), jreq.id); } return rpc_result; }
static UniValue JSONRPCExecOne(const UniValue& req) { UniValue rpc_result(UniValue::VOBJ); JSONRequest jreq; try { jreq.parse(req); UniValue result = tableRPC.execute(jreq.strMethod, jreq.params); rpc_result = JSONRPCReplyObj(result, NullUniValue, jreq.id); } catch (const UniValue& objError) { rpc_result = JSONRPCReplyObj(NullUniValue, objError, jreq.id); } catch (const std::exception& e) { rpc_result = JSONRPCReplyObj(NullUniValue, JSONRPCError(RPC_PARSE_ERROR, e.what()), jreq.id); } return rpc_result; }
void ServiceConnection(AcceptedConnection *conn) { bool fRun = true; while (fRun && !ShutdownRequested()) { int nProto = 0; map<string, string> mapHeaders; string strRequest, strMethod, strURI; // Read HTTP request line if (!ReadHTTPRequestLine(conn->stream(), nProto, strMethod, strURI)) break; // Read HTTP message headers and body ReadHTTPMessage(conn->stream(), mapHeaders, strRequest, nProto); if (strURI != "/") { conn->stream() << HTTPReply(HTTP_NOT_FOUND, "", false) << flush; break; } // // Check authorization // if (mapHeaders.count("authorization") == 0) // { // conn->stream() << HTTPReply(HTTP_UNAUTHORIZED, "", false) << flush; // break; // } // if (!HTTPAuthorized(mapHeaders)) // { // LogPrint("INFO","ThreadRPCServer incorrect password attempt from %s\n", conn->peer_address_to_string()); // /* Deter brute-forcing short passwords. // If this results in a DoS the user really // shouldn't have their RPC port exposed. */ // if (SysCfg().GetArg("-rpcpassword", "").size() < 20) // MilliSleep(250); // // conn->stream() << HTTPReply(HTTP_UNAUTHORIZED, "", false) << flush; // break; // } if (mapHeaders["connection"] == "close") fRun = false; JSONRequest jreq; try { // Parse request Value valRequest; if (!read_string(strRequest, valRequest)) throw JSONRPCError(RPC_PARSE_ERROR, "Parse error"); string strReply; // singleton request if (valRequest.type() == obj_type) { jreq.parse(valRequest); 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(RPC_PARSE_ERROR, "Top-level object parse error"); conn->stream() << HTTPReply(HTTP_OK, strReply, fRun) << flush; } catch (Object& objError) { ErrorReply(conn->stream(), objError, jreq.id); break; } catch (std::exception& e) { ErrorReply(conn->stream(), JSONRPCError(RPC_PARSE_ERROR, e.what()), jreq.id); break; } } }