From 4d5fa04a237a7ccd132893f54e7fe6f003ce994b Mon Sep 17 00:00:00 2001 From: JohnDoe6345789 Date: Fri, 26 Dec 2025 05:58:20 +0000 Subject: [PATCH] docs: dbal,requests,hpp (2 files) --- dbal/README.md | 15 ++++ dbal/cpp/src/runtime/requests_client.hpp | 88 ++++++++++++++++++++++++ 2 files changed, 103 insertions(+) create mode 100644 dbal/cpp/src/runtime/requests_client.hpp diff --git a/dbal/README.md b/dbal/README.md index 435e7b163..afc7d9d93 100644 --- a/dbal/README.md +++ b/dbal/README.md @@ -156,6 +156,21 @@ permissions: ## API Contract Example +### HTTP Utilities + +For outbound integrations the daemon can use the new requests-inspired helper `runtime::RequestsClient`. It wraps Drogon’s `HttpClient`, exposes `get`/`post` helpers, parses JSON responses, and throws clean timeouts so code paths stay predictable. + +```cpp +using namespace dbal::runtime; + +RequestsClient http("https://api.prisma.example"); +auto response = http.post("/rpc/execute", jsonPayload.dump(), {{"Authorization", "Bearer ..."}}); +if (response.statusCode == 200) { + const auto result = response.json["result"]; + // handle Prisma response +} +``` + ### Entity Definition (YAML) ```yaml diff --git a/dbal/cpp/src/runtime/requests_client.hpp b/dbal/cpp/src/runtime/requests_client.hpp new file mode 100644 index 000000000..628d56698 --- /dev/null +++ b/dbal/cpp/src/runtime/requests_client.hpp @@ -0,0 +1,88 @@ +#ifndef DBAL_REQUESTS_CLIENT_HPP +#define DBAL_REQUESTS_CLIENT_HPP + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace dbal { +namespace runtime { + +struct RequestsResponse { + int statusCode; + std::string body; + drogon::Json::Value json; + std::unordered_map headers; +}; + +class RequestsClient { +public: + explicit RequestsClient(const std::string& baseURL) + : client_(drogon::HttpClient::newHttpClient(baseURL)) {} + + RequestsResponse get(const std::string& path, + const std::unordered_map& headers = {}, + int timeoutMs = 30'000) { + return request("GET", path, headers, {}, timeoutMs); + } + + RequestsResponse post(const std::string& path, + const std::string& body, + const std::unordered_map& headers = {}, + int timeoutMs = 30'000) { + return request("POST", path, headers, body, timeoutMs); + } + + RequestsResponse request(const std::string& method, + const std::string& path, + const std::unordered_map& headers = {}, + const std::string& body = {}, + int timeoutMs = 30'000) { + drogon::HttpRequestPtr req = drogon::HttpRequest::newHttpRequest(); + req->setMethod(drogon::HttpMethod::fromString(method)); + req->setPath(path); + req->setBody(body); + for (const auto& [key, value] : headers) { + req->addHeader(key, value); + } + + std::promise promise; + auto future = promise.get_future(); + + client_->sendRequest(req, [p = std::move(promise), timeoutMs](drogon::ReqResult result, const drogon::HttpResponsePtr& resp) mutable { + RequestsResponse response; + response.statusCode = resp ? resp->getStatusCode() : 0; + response.body = resp ? resp->getBody() : ""; + if (resp) { + response.headers = resp->getHeaders(); + try { + response.json = drogon::Json::parse(resp->getBody()); + } catch (...) { + } + } + p.set_value(std::move(response)); + }); + + if (future.wait_for(std::chrono::milliseconds(timeoutMs)) == std::future_status::timeout) { + throw std::runtime_error("HTTP request timed out"); + } + + return future.get(); + } + +private: + drogon::HttpClientPtr client_; +}; + +} +} + +#endif