| 194 | } |
| 195 | |
| 196 | void JSONRPCRequest::parse(const UniValue& valRequest) |
| 197 | { |
| 198 | // Parse request |
| 199 | if (!valRequest.isObject()) |
| 200 | throw JSONRPCError(RPC_INVALID_REQUEST, "Invalid Request object"); |
| 201 | const UniValue& request = valRequest.get_obj(); |
| 202 | |
| 203 | // Parse id now so errors from here on will have the id |
| 204 | if (request.exists("id")) { |
| 205 | id = request.find_value("id"); |
| 206 | } else { |
| 207 | id = std::nullopt; |
| 208 | } |
| 209 | |
| 210 | // Check for JSON-RPC 2.0 (default 1.1) |
| 211 | m_json_version = JSONRPCVersion::V1_LEGACY; |
| 212 | const UniValue& jsonrpc_version = request.find_value("jsonrpc"); |
| 213 | if (!jsonrpc_version.isNull()) { |
| 214 | if (!jsonrpc_version.isStr()) { |
| 215 | throw JSONRPCError(RPC_INVALID_REQUEST, "jsonrpc field must be a string"); |
| 216 | } |
| 217 | // The "jsonrpc" key was added in the 2.0 spec, but some older documentation |
| 218 | // incorrectly included {"jsonrpc":"1.0"} in a request object, so we |
| 219 | // maintain that for backwards compatibility. |
| 220 | if (jsonrpc_version.get_str() == "1.0") { |
| 221 | m_json_version = JSONRPCVersion::V1_LEGACY; |
| 222 | } else if (jsonrpc_version.get_str() == "2.0") { |
| 223 | m_json_version = JSONRPCVersion::V2; |
| 224 | } else { |
| 225 | throw JSONRPCError(RPC_INVALID_REQUEST, "JSON-RPC version not supported"); |
| 226 | } |
| 227 | } |
| 228 | |
| 229 | // Parse method |
| 230 | const UniValue& valMethod{request.find_value("method")}; |
| 231 | if (valMethod.isNull()) |
| 232 | throw JSONRPCError(RPC_INVALID_REQUEST, "Missing method"); |
| 233 | if (!valMethod.isStr()) |
| 234 | throw JSONRPCError(RPC_INVALID_REQUEST, "Method must be a string"); |
| 235 | strMethod = valMethod.get_str(); |
| 236 | const std::string log_id{id && !id->isNull() ? SanitizeString(id->getValStr()) : ""}; |
| 237 | if (fLogIPs) |
| 238 | LogDebug(BCLog::RPC, "ThreadRPCServer method=%s user=%s peeraddr=%s id=%s", SanitizeString(strMethod), |
| 239 | this->authUser, this->peerAddr, log_id); |
| 240 | else |
| 241 | LogDebug(BCLog::RPC, "ThreadRPCServer method=%s user=%s id=%s", SanitizeString(strMethod), this->authUser, |
| 242 | log_id); |
| 243 | |
| 244 | // Parse params |
| 245 | const UniValue& valParams{request.find_value("params")}; |
| 246 | if (valParams.isArray() || valParams.isObject()) |
| 247 | params = valParams; |
| 248 | else if (valParams.isNull()) |
| 249 | params = UniValue(UniValue::VARR); |
| 250 | else |
| 251 | throw JSONRPCError(RPC_INVALID_REQUEST, "Params must be an array or object"); |
| 252 | } |
no test coverage detected