| 126 | } |
| 127 | |
| 128 | static void MaybeDispatchRequestToWorker(std::shared_ptr<HTTPRequest> hreq) |
| 129 | { |
| 130 | // Early address-based allow check |
| 131 | if (!ClientAllowed(hreq->GetPeer())) { |
| 132 | LogDebug(BCLog::HTTP, "HTTP request from %s rejected: Client network is not allowed RPC access\n", |
| 133 | hreq->GetPeer().ToStringAddrPort()); |
| 134 | hreq->WriteReply(HTTP_FORBIDDEN); |
| 135 | return; |
| 136 | } |
| 137 | |
| 138 | // Early reject unknown HTTP methods |
| 139 | if (hreq->GetRequestMethod() == HTTPRequestMethod::UNKNOWN) { |
| 140 | LogDebug(BCLog::HTTP, "HTTP request from %s rejected: Unknown HTTP request method\n", |
| 141 | hreq->GetPeer().ToStringAddrPort()); |
| 142 | hreq->WriteReply(HTTP_BAD_METHOD); |
| 143 | return; |
| 144 | } |
| 145 | |
| 146 | // Find registered handler for prefix |
| 147 | std::string strURI = hreq->GetURI(); |
| 148 | std::string path; |
| 149 | LOCK(g_httppathhandlers_mutex); |
| 150 | std::vector<HTTPPathHandler>::const_iterator i = pathHandlers.begin(); |
| 151 | std::vector<HTTPPathHandler>::const_iterator iend = pathHandlers.end(); |
| 152 | for (; i != iend; ++i) { |
| 153 | bool match = false; |
| 154 | if (i->exactMatch) |
| 155 | match = (strURI == i->prefix); |
| 156 | else |
| 157 | match = strURI.starts_with(i->prefix); |
| 158 | if (match) { |
| 159 | path = strURI.substr(i->prefix.size()); |
| 160 | break; |
| 161 | } |
| 162 | } |
| 163 | |
| 164 | // Dispatch to worker thread |
| 165 | if (i != iend) { |
| 166 | if (static_cast<int>(g_threadpool_http.WorkQueueSize()) >= g_max_queue_depth) { |
| 167 | LogWarning("Request rejected because http work queue depth exceeded, it can be increased with the -rpcworkqueue= setting"); |
| 168 | hreq->WriteReply(HTTP_SERVICE_UNAVAILABLE, "Work queue depth exceeded"); |
| 169 | return; |
| 170 | } |
| 171 | |
| 172 | auto item = [req = hreq, in_path = std::move(path), fn = i->handler]() { |
| 173 | std::string err_msg; |
| 174 | try { |
| 175 | fn(req.get(), in_path); |
| 176 | return; |
| 177 | } catch (const std::exception& e) { |
| 178 | LogWarning("Unexpected error while processing request for '%s'. Error msg: '%s'", req->GetURI(), e.what()); |
| 179 | err_msg = e.what(); |
| 180 | } catch (...) { |
| 181 | LogWarning("Unknown error while processing request for '%s'", req->GetURI()); |
| 182 | err_msg = "unknown error"; |
| 183 | } |
| 184 | // Reply so the client doesn't hang waiting for the response. |
| 185 | req->WriteHeader("Connection", "close"); |
nothing calls this directly
no test coverage detected