Files
sniper/src/HttpClient.cpp
T
2026-08-09 16:51:01 -05:00

91 lines
3.2 KiB
C++

#include "HttpClient.hpp"
#include <curl/curl.h>
#include <cstring>
void HttpClient::globalInit() { curl_global_init(CURL_GLOBAL_DEFAULT); }
void HttpClient::globalCleanup() { curl_global_cleanup(); }
namespace {
size_t writeCallback(char* ptr, size_t size, size_t nmemb, void* userdata) {
auto* out = static_cast<std::string*>(userdata);
out->append(ptr, size * nmemb);
return size * nmemb;
}
struct CurlHandle {
CURL* h;
CurlHandle() : h(curl_easy_init()) {}
~CurlHandle() { if (h) curl_easy_cleanup(h); }
};
struct CurlSlist {
curl_slist* list = nullptr;
void append(const std::string& header) { list = curl_slist_append(list, header.c_str()); }
~CurlSlist() { if (list) curl_slist_free_all(list); }
};
} // namespace
HttpResponse HttpClient::get(const std::string& url,
const std::map<std::string, std::string>& headers,
long timeout_seconds) {
HttpResponse resp;
CurlHandle curl;
if (!curl.h) { resp.status = -1; return resp; }
CurlSlist slist;
for (const auto& [k, v] : headers) slist.append(k + ": " + v);
curl_easy_setopt(curl.h, CURLOPT_URL, url.c_str());
curl_easy_setopt(curl.h, CURLOPT_HTTPHEADER, slist.list);
curl_easy_setopt(curl.h, CURLOPT_WRITEFUNCTION, writeCallback);
curl_easy_setopt(curl.h, CURLOPT_WRITEDATA, &resp.body);
curl_easy_setopt(curl.h, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(curl.h, CURLOPT_TIMEOUT, timeout_seconds);
curl_easy_setopt(curl.h, CURLOPT_SSL_VERIFYPEER, 1L);
curl_easy_setopt(curl.h, CURLOPT_ACCEPT_ENCODING, ""); // accept gzip/deflate
CURLcode rc = curl_easy_perform(curl.h);
if (rc != CURLE_OK) {
resp.status = -1;
resp.body = curl_easy_strerror(rc);
return resp;
}
long code = 0;
curl_easy_getinfo(curl.h, CURLINFO_RESPONSE_CODE, &code);
resp.status = code;
return resp;
}
HttpResponse HttpClient::postJson(const std::string& url,
const std::string& json_body,
const std::map<std::string, std::string>& headers,
long timeout_seconds) {
HttpResponse resp;
CurlHandle curl;
if (!curl.h) { resp.status = -1; return resp; }
CurlSlist slist;
slist.append("Content-Type: application/json");
for (const auto& [k, v] : headers) slist.append(k + ": " + v);
curl_easy_setopt(curl.h, CURLOPT_URL, url.c_str());
curl_easy_setopt(curl.h, CURLOPT_HTTPHEADER, slist.list);
curl_easy_setopt(curl.h, CURLOPT_POSTFIELDS, json_body.c_str());
curl_easy_setopt(curl.h, CURLOPT_POSTFIELDSIZE, static_cast<long>(json_body.size()));
curl_easy_setopt(curl.h, CURLOPT_WRITEFUNCTION, writeCallback);
curl_easy_setopt(curl.h, CURLOPT_WRITEDATA, &resp.body);
curl_easy_setopt(curl.h, CURLOPT_TIMEOUT, timeout_seconds);
curl_easy_setopt(curl.h, CURLOPT_SSL_VERIFYPEER, 1L);
CURLcode rc = curl_easy_perform(curl.h);
if (rc != CURLE_OK) {
resp.status = -1;
resp.body = curl_easy_strerror(rc);
return resp;
}
long code = 0;
curl_easy_getinfo(curl.h, CURLINFO_RESPONSE_CODE, &code);
resp.status = code;
return resp;
}