Repository: bitcoin/bitcoin
File: src/rpc/request.cpp (C++)

Code before:
    // Parse id now so errors from here on will have the id
    id = request.find_value("id");

    // Parse method
    const UniValue& valMethod{request.find_value("method")};
    if (valMethod.isNull())
        throw JSONRPCError(RPC_INVALID_REQUEST, "Missing method");
    if (!valMethod.isStr())
        throw JSONRPCError(RPC_INVALID_REQUEST, "Method must be a string");
    strMethod = valMethod.get_str();
    if (fLogIPs)
        LogPrint(BCLog::RPC, "ThreadRPCServer method=%s user=%s peeraddr=%s\n", SanitizeString(strMethod),
            this->authUser, this->peerAddr);
    else
        LogPrint(BCLog::RPC, "ThreadRPCServer method=%s user=%s\n", SanitizeString(strMethod), this->authUser);

    // Parse params
    const UniValue& valParams{request.find_value("params")};
    if (valParams.isArray() || valParams.isObject())
        params = valParams;
    else if (valParams.isNull())
        params = UniValue(UniValue::VARR);
    else
        throw JSONRPCError(RPC_INVALID_REQUEST, "Params must be an array or object");
}


Review comment (bug):
In commit "MOVEONLY: define class before functions in request.h" (bcf90ae6b7fd4685755c3f2e1e736053e613e0f6)

Not important, but I think the developer guide suggests braces around multiline if statements because it can prevent subtle bugs from sneaking in. Generally only older code in bitcoin core omits the braces on multiline if statements.

Code after:
        batch[id] = rec;
    }
    return batch;
}

void JSONRPCRequest::parse(const UniValue& valRequest)
{
    // Parse request
    if (!valRequest.isObject())
        throw JSONRPCError(RPC_INVALID_REQUEST, "Invalid Request object");
    const UniValue& request = valRequest.get_obj();

    // Parse id now so errors from here on will have the id
    if (request.exists("id")) {
        id = request.find_value("id");
    } else {
        id = std::nullopt;
    }

    // Check for JSON-RPC 2.0 (default 1.1)
    m_json_version = JSONRPCVersion::V1_LEGACY;
    const UniValue& jsonrpc_version = request.find_value("jsonrpc");
    if (!jsonrpc_version.isNull()) {
        if (!jsonrpc_version.isStr()) {
            throw JSONRPCError(RPC_INVALID_REQUEST, "jsonrpc field must be a string");
        }
        // The "jsonrpc" key was added in the 2.0 spec, but some older documentation
        // incorrectly included {"jsonrpc":"1.0"} in a request object, so we
        // maintain that for backwards compatibility.
        if (jsonrpc_version.get_str() == "1.0") {
            m_json_version = JSONRPCVersion::V1_LEGACY;
        } else if (jsonrpc_version.get_str() == "2.0") {
            m_json_version = JSONRPCVersion::V2;
        } else {
            throw JSONRPCError(RPC_INVALID_REQUEST, "JSON-RPC version not supported");
        }
    }

    // Parse method
    const UniValue& valMethod{request.find_value("method")};
    if (valMethod.isNull())
        throw JSONRPCError(RPC_INVALID_REQUEST, "Missing method");
    if (!valMethod.isStr())
        throw JSONRPCError(RPC_INVALID_REQUEST, "Method must be a string");
    strMethod = valMethod.get_str();
    if (fLogIPs)
        LogPrint(BCLog::RPC, "ThreadRPCServer method=%s user=%s peeraddr=%s\n", SanitizeString(strMethod),
            this->authUser, this->peerAddr);
    else
        LogPrint(BCLog::RPC, "ThreadRPCServer method=%s user=%s\n", SanitizeString(strMethod), this->authUser);