#pragma once #include #include #include #include #include #include #include #include #include #include "span.hpp" #include "utils.hpp" /// TODO rename file to rublon/Core.hpp /// TODO Create rublon utils 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 headers; std::string body; }; struct Response{ std::map 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); auto res = curl_easy_perform(curl.get()); if(res != CURLE_OK) { // debugLog("No response from Rublon server (perform)", ""); return std::nullopt; } 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(size)}); response.body = response_data.substr(size); return response; } }; } // namespace rublon