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

Code before:
    if (i != iend) {
        if (static_cast<int>(g_threadpool_http.WorkQueueSize()) >= g_max_queue_depth) {
            LogWarning("Request rejected because http work queue depth exceeded, it can be increased with the -rpcworkqueue= setting");
            hreq->WriteReply(HTTP_SERVICE_UNAVAILABLE, "Work queue depth exceeded");
            return;
        }

        auto item = [req = hreq, in_path = std::move(path), fn = i->handler]() {
            std::string err_msg;
            try {
                fn(req.get(), in_path);
                return;
            } catch (const std::exception& e) {
                LogWarning("Unexpected error while processing request for '%s'. Error msg: '%s'", req->GetURI(), e.what());
                err_msg = e.what();
            } catch (...) {
                LogWarning("Unknown error while processing request for '%s'", req->GetURI());
                err_msg = "unknown error";
            }
            // Reply so the client doesn't hang waiting for the response.
            req->WriteHeader("Connection", "close");
            // TODO: Implement specific error formatting for the REST and JSON-RPC servers responses.
            req->WriteReply(HTTP_INTERNAL_SERVER_ERROR, err_msg);
        };

        if (auto res = g_threadpool_http.Submit(std::move(item)); !res.has_value()) {
            // Both SubmitError::Inactive and SubmitError::Interrupted mean shutdown
            LogWarning("HTTP request rejected during server shutdown: '%s'", SubmitErrorString(res.error()));
            hreq->WriteReply(HTTP_SERVICE_UNAVAILABLE, "Request rejected during server shutdown");
            return;
        }
    } else {
        hreq->WriteReply(HTTP_NOT_FOUND);
    }
}

/** Callback to reject HTTP requests after shutdown. */
static void http_reject_request_cb(struct evhttp_request* req, void*)
{
    LogDebug(BCLog::HTTP, "Rejecting request while shutting down\n");
    evhttp_send_error(req, HTTP_SERVUNAVAIL, nullptr);
}

/** Event dispatcher thread */
static void ThreadHTTP(struct event_base* base)
{
    util::ThreadRename("http");
    LogDebug(BCLog::HTTP, "Entering http event loop\n");
    event_base_dispatch(base);
    // Event loop will be interrupted by InterruptHTTPServer()
    LogDebug(BCLog::HTTP, "Exited http event loop\n");

Review comment (suggestion):
379a9201b1aabffe5f19dbabf1fe4fd57e8fefba

I'm also interested in trying to save `unique_ptr` for `hreq` and tried some hacks like @hodlinator but nothing great came out of that. If nothing else could we `Assume(hreq.use_count() == 1)` in this block and also below where we send `404`? This would just clarify that we don't reply to a request outside a worker thread unless we're sure the worker thread is nonexistent. 

Code after:
    if (i != iend) {
        if (static_cast<int>(g_threadpool_http.WorkQueueSize()) >= g_max_queue_depth) {
            LogWarning("Request rejected because http work queue depth exceeded, it can be increased with the -rpcworkqueue= setting");
            hreq->WriteReply(HTTP_SERVICE_UNAVAILABLE, "Work queue depth exceeded");
            return;
        }

        auto item = [req = hreq, in_path = std::move(path), fn = i->handler]() {
            std::string err_msg;
            try {
                fn(req.get(), in_path);
                return;
            } catch (const std::exception& e) {
                LogWarning("Unexpected error while processing request for '%s'. Error msg: '%s'", req->GetURI(), e.what());
                err_msg = e.what();
            } catch (...) {
                LogWarning("Unknown error while processing request for '%s'", req->GetURI());
                err_msg = "unknown error";
            }
            // Reply so the client doesn't hang waiting for the response.
            req->WriteHeader("Connection", "close");
            // TODO: Implement specific error formatting for the REST and JSON-RPC servers responses.
            req->WriteReply(HTTP_INTERNAL_SERVER_ERROR, err_msg);
        };

        if (auto res = g_threadpool_http.Submit(std::move(item)); !res.has_value()) {
            Assume(hreq.use_count() == 1); // ensure request will be deleted
            // Both SubmitError::Inactive and SubmitError::Interrupted mean shutdown
            LogWarning("HTTP request rejected during server shutdown: '%s'", SubmitErrorString(res.error()));
            hreq->WriteReply(HTTP_SERVICE_UNAVAILABLE, "Request rejected during server shutdown");
            return;
        }
    } else {
        hreq->WriteReply(HTTP_NOT_FOUND);
    }
}

/** Callback to reject HTTP requests after shutdown. */
static void http_reject_request_cb(struct evhttp_request* req, void*)
{
    LogDebug(BCLog::HTTP, "Rejecting request while shutting down\n");
    evhttp_send_error(req, HTTP_SERVUNAVAIL, nullptr);
}

/** Event dispatcher thread */
static void ThreadHTTP(struct event_base* base)
{
    util::ThreadRename("http");
    LogDebug(BCLog::HTTP, "Entering http event loop\n");
    event_base_dispatch(base);
    // Event loop will be interrupted by InterruptHTTPServer()