83 lines
2.8 KiB
C++
83 lines
2.8 KiB
C++
#pragma once
|
|
|
|
#include <algorithm>
|
|
#include <cstdlib>
|
|
#include <curl/curl.h>
|
|
#include <memory>
|
|
#include <optional>
|
|
#include <string>
|
|
#include <string_view>
|
|
#include <vector>
|
|
|
|
#include <memory_resource>
|
|
|
|
#include "utils.hpp"
|
|
|
|
namespace rublon {
|
|
|
|
static size_t WriteMemoryCallback(void * contents, size_t size, size_t nmemb, void * userp) {
|
|
size_t realsize = size * nmemb;
|
|
reinterpret_cast< std::string * >(userp)->append(static_cast< const char * >(contents), realsize);
|
|
return realsize;
|
|
}
|
|
|
|
struct Request {
|
|
std::map< std::string, std::string > headers;
|
|
std::string body;
|
|
};
|
|
|
|
struct Response {
|
|
std::map< std::string, std::string > headers;
|
|
std::string body;
|
|
};
|
|
|
|
class CURL {
|
|
std::unique_ptr< ::CURL, void (*)(::CURL *) > curl;
|
|
|
|
public:
|
|
CURL() : curl{std::unique_ptr< ::CURL, void (*)(::CURL *) >(curl_easy_init(), curl_easy_cleanup)} {}
|
|
|
|
std::optional< Response > request(std::string_view uri, const Request & request) const {
|
|
std::string response_data;
|
|
response_data.reserve(1000);
|
|
|
|
Response response;
|
|
|
|
/// TODO this can be done on stack using pmr
|
|
auto curl_headers = std::unique_ptr< curl_slist, void (*)(curl_slist *) >(nullptr, curl_slist_free_all);
|
|
std::for_each(request.headers.begin(), request.headers.end(), [&](auto header) {
|
|
curl_headers.reset(curl_slist_append(curl_headers.release(), (header.first + ": " + header.second).c_str()));
|
|
});
|
|
|
|
curl_easy_setopt(curl.get(), CURLOPT_VERBOSE, 1);
|
|
curl_easy_setopt(curl.get(), CURLOPT_URL, uri.data());
|
|
curl_easy_setopt(curl.get(), CURLOPT_HTTPHEADER, curl_headers.get());
|
|
curl_easy_setopt(curl.get(), CURLOPT_POST, 1);
|
|
curl_easy_setopt(curl.get(), CURLOPT_POSTFIELDS, request.body.data());
|
|
curl_easy_setopt(curl.get(), CURLOPT_POSTFIELDSIZE, static_cast< u_int32_t >(request.body.size()));
|
|
curl_easy_setopt(curl.get(), CURLOPT_HEADER, 1);
|
|
curl_easy_setopt(curl.get(), CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
|
|
curl_easy_setopt(curl.get(), CURLOPT_WRITEDATA, &response_data);
|
|
|
|
rublon::log(LogLevel::Info, "Request send uri:{%s} body:{%s}", uri.data(), request.body.c_str());
|
|
auto res = curl_easy_perform(curl.get());
|
|
if(res != CURLE_OK) {
|
|
log(LogLevel::Error, "No response from Rublon server err:{%s}", curl_easy_strerror(res));
|
|
return std::nullopt;
|
|
}
|
|
|
|
log(LogLevel::Debug, "Response data :{{ %s }}", response_data.c_str());
|
|
|
|
long size;
|
|
curl_easy_getinfo(curl.get(), CURLINFO_HEADER_SIZE, &size);
|
|
|
|
/// TODO ogarnąć alokację pamięci
|
|
response.headers = details::headers({response_data.data(), static_cast< std::size_t >(size)});
|
|
response.body = response_data.substr(size);
|
|
|
|
return response;
|
|
}
|
|
};
|
|
|
|
} // namespace rublon
|