Repository: bitcoin/bitcoin
File: src/bitcoin-cli.cpp (C++)

Code before:
    uint16_t port{BaseParams().RPCPort()};
    SplitHostPort(gArgs.GetArg("-rpcconnect", DEFAULT_RPCCONNECT), port, host);
    port = static_cast<uint16_t>(gArgs.GetIntArg("-rpcport", port));

    // Obtain event base
    raii_event_base base = obtain_event_base();

    // Synchronously look up hostname
    raii_evhttp_connection evcon = obtain_evhttp_connection_base(base.get(), host, port);

    // Set connection timeout
    {
        const int timeout = gArgs.GetIntArg("-rpcclienttimeout", DEFAULT_HTTP_CLIENT_TIMEOUT);
        if (timeout > 0) {
            evhttp_connection_set_timeout(evcon.get(), timeout);
        } else {
            // Indefinite request timeouts are not possible in libevent-http, so we
            // set the timeout to a very long time period instead.

            constexpr int YEAR_IN_SECONDS = 31556952; // Average length of year in Gregorian calendar
            evhttp_connection_set_timeout(evcon.get(), 5 * YEAR_IN_SECONDS);
        }
    }

    HTTPReply response;
    raii_evhttp_request req = obtain_evhttp_request(http_request_done, (void*)&response);
    if (req == nullptr) {
        throw std::runtime_error("create http request failed");
    }

    evhttp_request_set_error_cb(req.get(), http_error_cb);

    // Get credentials
    std::string strRPCUserColonPass;
    bool failedToGetAuthCookie = false;
    if (gArgs.GetArg("-rpcpassword", "") == "") {
        // Try fall back to cookie-based authentication if no password is provided
        if (!GetAuthCookie(&strRPCUserColonPass)) {
            failedToGetAuthCookie = true;
        }
    } else {
        strRPCUserColonPass = gArgs.GetArg("-rpcuser", "") + ":" + gArgs.GetArg("-rpcpassword", "");
    }

    struct evkeyvalq* output_headers = evhttp_request_get_output_headers(req.get());
    assert(output_headers);
    evhttp_add_header(output_headers, "Host", host.c_str());
    evhttp_add_header(output_headers, "Connection", "close");
    evhttp_add_header(output_headers, "Content-Type", "application/json");
    evhttp_add_header(output_headers, "Authorization", (std::string("Basic ") + EncodeBase64(strRPCUserColonPass)).c_str());


Review comment (suggestion):
Style: narrow scope of `rpcport_arg` since it is only used inside the if-block. (In this case the outer scope ends it anyway, this is just a general rule of thumb).

Naming: `rpcport_port` -> `rpcport_int` since the former is a bit repetitive and the latter at least describes its purpose somewhat, despite being a bit Hungarian.

```suggestion
        if (std::optional<std::string> rpcport_arg = gArgs.GetArg("-rpcport")) {
            std::optional<uint16_t> rpcport_int{ToIntegral<uint16_t>(rpcport_arg.value())};
            if (!rpcport_int.has_value() || rpcport_int.value() == 0) {
                throw std::runtime_error(strprintf("Invalid port provided in -rpcport: %s", rpcport_arg.value()));
            }

            // Use the valid port provided
            port = rpcport_int.value();
```

Code after:
    uint16_t port{BaseParams().RPCPort()};
    {
        uint16_t rpcconnect_port{0};
        const std::string rpcconnect_str = gArgs.GetArg("-rpcconnect", DEFAULT_RPCCONNECT);
        if (!SplitHostPort(rpcconnect_str, rpcconnect_port, host)) {
            // Uses argument provided as-is
            // (rather than value parsed)
            // to aid the user in troubleshooting
            throw std::runtime_error(strprintf("Invalid port provided in -rpcconnect: %s", rpcconnect_str));
        } else {
            if (rpcconnect_port != 0) {
                // Use the valid port provided in rpcconnect
                port = rpcconnect_port;
            } // else, no port was provided in rpcconnect (continue using default one)
        }

        if (std::optional<std::string> rpcport_arg = gArgs.GetArg("-rpcport")) {
            // -rpcport was specified
            const uint16_t rpcport_int{ToIntegral<uint16_t>(rpcport_arg.value()).value_or(0)};
            if (rpcport_int == 0) {
                // Uses argument provided as-is
                // (rather than value parsed)
                // to aid the user in troubleshooting
                throw std::runtime_error(strprintf("Invalid port provided in -rpcport: %s", rpcport_arg.value()));
            }

            // Use the valid port provided
            port = rpcport_int;

            // If there was a valid port provided in rpcconnect,
            // rpcconnect_port is non-zero.
            if (rpcconnect_port != 0) {
                tfm::format(std::cerr, "Warning: Port specified in both -rpcconnect and -rpcport. Using -rpcport %u\n", port);
            }
        }
    }

    // Obtain event base
    raii_event_base base = obtain_event_base();

    // Synchronously look up hostname
    raii_evhttp_connection evcon = obtain_evhttp_connection_base(base.get(), host, port);

    // Set connection timeout
    {
        const int timeout = gArgs.GetIntArg("-rpcclienttimeout", DEFAULT_HTTP_CLIENT_TIMEOUT);
        if (timeout > 0) {
            evhttp_connection_set_timeout(evcon.get(), timeout);
        } else {
            // Indefinite request timeouts are not possible in libevent-http, so we
            // set the timeout to a very long time period instead.