diff --git a/src/requester.cpp b/src/requester.cpp new file mode 100644 index 0000000..7ae84ff --- /dev/null +++ b/src/requester.cpp @@ -0,0 +1,56 @@ +#include "requester.hpp" +#include +#include +#include +#include + +size_t requester::write_data(char *buf, size_t sz, size_t nmemb, void *user_data) { + size_t realsize = sz * nmemb; + requester* req {reinterpret_cast(user_data)}; + if (req->_logger) { + SCInfo((*req->_logger), "received ", realsize, " bytes"); + } + req->_text.append(buf, realsize); + return realsize; +} + +requester::requester() { + curl_global_init(CURL_GLOBAL_ALL); + _h.reset(curl_easy_init()); + curl_easy_setopt(_h.get(), CURLOPT_WRITEFUNCTION, write_data); +} + +requester::~requester() { + curl_global_cleanup(); +} + +std::string requester::get(const std::string &url) { + _text = ""; + curl_easy_setopt(_h.get(), CURLOPT_URL, url.c_str()); + curl_easy_setopt(_h.get(), CURLOPT_WRITEDATA, this); + auto success = curl_easy_perform(_h.get()); + if (success != CURLE_OK) throw std::runtime_error("could not get remote data"); + long status; + success = curl_easy_getinfo(_h.get(), CURLINFO_RESPONSE_CODE, &status); + if (success != CURLE_OK || status != 200) throw std::runtime_error("could not get remote data"); + return _text; +} + +std::string requester::post(const std::string& url, const std::string& json) { + curl_easy_setopt(_h.get(), CURLOPT_URL, url.c_str()); + curl_easy_setopt(_h.get(), CURLOPT_POST, 1L); + curl_easy_setopt(_h.get(), CURLOPT_POSTFIELDS, json.c_str()); + curl_easy_setopt(_h.get(), CURLOPT_POSTFIELDSIZE, json.size()); + + struct curl_slist* headers {nullptr}; + headers = curl_slist_append(headers, "Content-Type: application/json"); + std::unique_ptr hdrs {headers, curl_slist_free_all}; + curl_easy_setopt(_h.get(), CURLOPT_HTTPHEADER, headers); + + std::string response; + curl_easy_setopt(_h.get(), CURLOPT_WRITEDATA, &response); + + auto success = curl_easy_perform(_h.get()); + if (success != CURLE_OK) throw std::runtime_error("could not post data"); + return response; +} diff --git a/src/requester.hpp b/src/requester.hpp new file mode 100644 index 0000000..174c3df --- /dev/null +++ b/src/requester.hpp @@ -0,0 +1,39 @@ +#ifndef _requester_H_ +#define _requester_H_ + +#include +#include +#include +#include + +class requester { + public: + // callback for data receiving + static size_t write_data(char* buf, size_t sz, size_t nmemb, void* user_data); + + // this class is a RAII class for a curl handle + requester(); + ~requester(); + + // forbid copying and moving + requester(const requester&) = delete; + requester& operator=(const requester&) = delete; + requester(requester&&) = delete; + requester& operator=(requester&&) = delete; + + // optional logger + void logger(sc::logger* logger) { _logger = logger; } + + // perform a http get request + std::string get(const std::string& url); + + // perform a http post request + std::string post(const std::string& url, const std::string& json); + + private: + std::unique_ptr _h {nullptr, curl_easy_cleanup}; + sc::logger* _logger {nullptr}; + std::string _text; +}; + +#endif // _requester_H_