diff --git a/.deepsource.toml b/.deepsource.toml index 4067fcb..cf22fab 100644 --- a/.deepsource.toml +++ b/.deepsource.toml @@ -1,7 +1,8 @@ version = 1 exclude_patterns = [ - "**/examples/**" + "**/examples/**", + "**/tests/**" ] [[analyzers]] diff --git a/CMakeLists.txt b/CMakeLists.txt index b09caa9..4b4524e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,6 +22,64 @@ file(GLOB_RECURSE HEADERS ) add_library(vibe STATIC ${SOURCES} ${HEADERS}) +option(TESTING "Enable testing" OFF) +if (TESTING) + + enable_testing() + add_executable(main tests/main_test.cpp) + target_link_libraries( + main + vibe + ) + + include(FetchContent) + + + find_package(GTest QUIET) + + if (NOT GTest_FOUND) + + message(STATUS "extracting https://github.com/google/googletest.git") + FetchContent_Declare( + googletest + GIT_REPOSITORY https://github.com/google/googletest.git + GIT_TAG v1.15.2 + ) + FetchContent_MakeAvailable(googletest) + message(STATUS "using -> build/ [gtest]") + else () + message(STATUS "#### using local GTest: In case of error verify your installation") + endif () + + target_link_libraries(main GTest::gtest_main) + include(GoogleTest) + gtest_discover_tests(main) + + + find_package(CURL QUIET) + if ( NOT CURL_FOUND ) + + message( STATUS "extracting https://github.com/curl/curl.git") + FetchContent_Declare( + curl + GIT_REPOSITORY https://github.com/curl/curl.git + GIT_TAG 83bedbd + ) + FetchContent_MakeAvailable(curl) + message(STATUS "using -> build/ [curl]") + else () + message(STATUS "#### using local curl: In case of error with .so.4 verify your installation curl --version") + endif () + + target_link_libraries(main CURL::libcurl) + +else () + + add_executable(vibex tests/debug.cpp) + target_link_libraries(vibex vibe) + +endif () + install(TARGETS vibe ARCHIVE DESTINATION lib LIBRARY DESTINATION lib diff --git a/README.md b/README.md index e58cae6..a597e68 100644 --- a/README.md +++ b/README.md @@ -93,6 +93,33 @@ In the `examples/` folder, you'll find examples of how to use Vibe for different Linux +## Testing + +cmake shell basic commands +```shell +cmake -DTESTING=ON -S. -B build +cmake --build build/ +cd build/ +ctest +``` + +with NPM + +```shell +npm run build +npm run test +``` + +### Debug + +for debug +```shell +npm run dev:run +``` + +and modify the file tests/debug.cpp + + ## Contribution Contributions are welcome! If you want to contribute to Vibe, please follow these guidelines: diff --git a/examples/files/cpp.html b/examples/files/cpp.html index 2c59de4..476de58 100644 --- a/examples/files/cpp.html +++ b/examples/files/cpp.html @@ -6,7 +6,7 @@ $ - std::cout << "hello from c++" << std::endl; + std::cout << "[hello from c++]" << std::endl; $ \ No newline at end of file diff --git a/examples/files/test.json b/examples/files/test.json index ff89222..f7bab33 100644 --- a/examples/files/test.json +++ b/examples/files/test.json @@ -1,3 +1 @@ -{ - "message": "hello" -} \ No newline at end of file +{"message": "hello"} \ No newline at end of file diff --git a/include/vibe/request/router_epoll.h b/include/vibe/request/router_epoll.h index c2f4107..d27f408 100644 --- a/include/vibe/request/router_epoll.h +++ b/include/vibe/request/router_epoll.h @@ -18,40 +18,60 @@ #include "../util/nterminal.h" #include "io.h" -constexpr int BUFFER = enums::neo::eSize::BUFFER; -constexpr int SESSION = enums::neo::eSize::SESSION; -constexpr int INIT_MAX_EVENTS = 10; - namespace workers { using RoutesMap = std::unordered_map>; +using enums::neo; + + constexpr int BUFFER = neo::eSize::BUFFER; + constexpr int SESSION = neo::eSize::SESSION; + constexpr int INIT_MAX_EVENTS = 10; template class RouterEpoll { - int epoll_fd; + int epoll_fd, file_descriptor; shared_ptr> events; shared_ptr connection; shared_ptr request_t; + neo::eStatus listen_status_; public: explicit RouterEpoll(const shared_ptr &conn) : - epoll_fd(epoll_create1(0)), + epoll_fd(epoll_create1(0)), file_descriptor(-1), events(make_shared>(INIT_MAX_EVENTS)), - connection(conn) + connection(conn), + listen_status_(enums::neo::eStatus::START) {} - auto getMainProcess(const shared_ptr &_routes){ - connection->on(); - int file_descriptor = connection->getDescription(); + auto InitListenProcess() { + connection->on(); + file_descriptor = connection->getDescription(); - if(Server::setNonblocking(file_descriptor) == MG_ERROR) - close(file_descriptor); + if(Server::setNonblocking(file_descriptor) == MG_ERROR) + close(file_descriptor); - if (epoll_fd == -1) - throw std::range_error(VB_EPOLL_RANGE); + if (epoll_fd == -1) + throw std::range_error(VB_EPOLL_RANGE); + } + + + auto ListenProcess(epoll_event &event) const { + try { + const int notice = epoll_wait(epoll_fd, events->data(), INIT_MAX_EVENTS, VB_NVALUE); + request_t->Dispatch(notice, event); + } + catch(const std::exception& e) { + terminal(e.what()); + close(epoll_fd); + if(close(file_descriptor) < VB_OK) + throw std::range_error(VB_MAIN_THREAD); + } + } + auto getMainProcess(const shared_ptr &_routes, const neo::LISTEN_TYPE _listen_type = neo::WHILE) { + InitListenProcess(); epoll_event event{}; event.events = EPOLLIN; @@ -61,22 +81,29 @@ using RoutesMap = std::unordered_map>; close(epoll_fd); throw std::range_error(VB_EPOLL_CTL); } - request_t = make_shared(events, _routes, file_descriptor, epoll_fd, connection); - while (static_cast(enums::neo::eStatus::START)){ - try { - const int notice = epoll_wait(epoll_fd, events->data(), INIT_MAX_EVENTS, VB_NVALUE); - request_t->Dispatch(notice, event); + if (_listen_type == neo::WHILE) { + while (static_cast(listen_status_)) { + ListenProcess(event); } - catch(const std::exception& e) { - terminal(e.what()); + close(epoll_fd); + close(file_descriptor); + request_t.reset(); + } + else { + // UNIQUE + ListenProcess(event); + ListenProcess(event); close(epoll_fd); - if(close(file_descriptor) < VB_OK) - throw std::range_error(VB_MAIN_THREAD); - } + close(file_descriptor); + request_t.reset(); } } + + void setListenStatus(const neo::eStatus _status) { + this->listen_status_ = _status; + } }; } diff --git a/include/vibe/util/enums.h b/include/vibe/util/enums.h index 46cd68f..aecd876 100644 --- a/include/vibe/util/enums.h +++ b/include/vibe/util/enums.h @@ -13,7 +13,6 @@ namespace enums { OK = 0x0, ERROR = -0x1, NA = 0x2, - UKNOW = 0x3 }; enum eSize { BUFFER = 0x800, @@ -26,6 +25,10 @@ namespace enums { START = 0x1, STOP = 0x0 }; + enum LISTEN_TYPE { + WHILE, + UNIQUE + }; }; } // enums diff --git a/include/vibe/vibe.h b/include/vibe/vibe.h index 69fedab..f2b98c3 100644 --- a/include/vibe/vibe.h +++ b/include/vibe/vibe.h @@ -8,11 +8,11 @@ #include #include -using std::make_shared; -using std::make_unique; +using std::make_shared, std::make_unique; using std::string; -using workers::RoutesMap; +using workers::RoutesMap, workers::BUFFER, workers::SESSION; +using enums::neo; template class Vibe { @@ -21,7 +21,7 @@ class Vibe { shared_ptr routes; std::shared_ptr tcpControl; - uint16_t PORT{enums::neo::eSize::DEF_PORT}; + uint16_t PORT{neo::DEF_PORT}; void tcpInt(); @@ -47,12 +47,14 @@ class Vibe { int setPort(uint16_t) noexcept; [[nodiscard]] [[maybe_unused]] inline uint16_t getPort() const noexcept{return PORT;}; void listen(); + void listenOne(); + void setListenStatus(neo::eStatus); }; template [[maybe_unused]] Vibe::Vibe(const uint16_t port) { - if (port >= enums::neo::eSize::MIN_PORT) { PORT = port; } + if (port >= neo::MIN_PORT) { PORT = port; } tcpInt(); } @@ -72,9 +74,9 @@ int Vibe::http_response(const string &endpoint, MiddlewareList middlewareList } catch (const std::exception &e) { std::cerr << e.what() << '\n'; - return enums::neo::eReturn::ERROR; + return neo::ERROR; } - return enums::neo::eReturn::OK; + return neo::OK; } template @@ -128,20 +130,30 @@ template void Vibe::listen() { router_epoll->getMainProcess(routes); } +template +void Vibe::listenOne() { + router_epoll->getMainProcess(routes, neo::UNIQUE); +} + +template +void Vibe::setListenStatus(neo::eStatus _status) { + router_epoll->setListenStatus(_status); +} template int Vibe::setPort(const uint16_t _port) noexcept { - if (_port >= enums::neo::eSize::MIN_PORT) { + if (_port >= neo::MIN_PORT) { PORT = _port; if(tcpControl != nullptr) { tcpControl->setPort(PORT); - return enums::neo::eReturn::OK; + return neo::OK; } } - return enums::neo::eReturn::ERROR; + return neo::ERROR; } + template void Vibe::tcpInt() { diff --git a/package.json b/package.json index 2d55060..ca3a256 100644 --- a/package.json +++ b/package.json @@ -3,9 +3,10 @@ "version": "1.0.0", "description": "User-friendly and compact C++ Web Framework", "scripts": { - "build": "cmake . . && cmake --build .", - "install": "make install", - "test": "echo \"Error: no test specified\" && exit 1" + "build": "cmake -DTESTING=ON -S . -B build/ && cmake --build build", + "test": "ctest --test-dir build", + "dev:build": "cmake -S . -B build/ && cmake --build build", + "dev:run": "cmake -S . -B build/ && cmake --build build && ./build/vibex" }, "repository": { "type": "git", diff --git a/sources/request/io.cpp b/sources/request/io.cpp index 6da7068..f1a4c8c 100644 --- a/sources/request/io.cpp +++ b/sources/request/io.cpp @@ -20,7 +20,6 @@ void RequestIO::Dispatch(const int id, epoll_event &event) const { this->Process(id, event); }); task.get(); - } diff --git a/sources/threading/thread_pool.cpp b/sources/threading/thread_pool.cpp index 1c57fa4..70bf535 100644 --- a/sources/threading/thread_pool.cpp +++ b/sources/threading/thread_pool.cpp @@ -33,7 +33,7 @@ ThreadPool::ThreadPool(const size_t threads) : size_(threads), stop_(false) { ThreadPool::~ThreadPool() { stop_.store(true); - + condition_.notify_all(); for(thread &thread : threads_) thread.join(); } diff --git a/tests/debug.cpp b/tests/debug.cpp new file mode 100644 index 0000000..5b520d9 --- /dev/null +++ b/tests/debug.cpp @@ -0,0 +1,14 @@ +#include "../include/vibe/vibe.h" + +int main() { + + Router router; + router.setPort(8080); + + router.get("/",{[&](Query &web) { + web.send("Hello World, Debug"); + }}); + + + router.listen(); +} \ No newline at end of file diff --git a/tests/main_test.cpp b/tests/main_test.cpp new file mode 100644 index 0000000..5cb0e93 --- /dev/null +++ b/tests/main_test.cpp @@ -0,0 +1,239 @@ +#include "suite.h" + + + TEST_F(TestSuite, TestBaseOne) { + + Router router; + router.setPort(8080); + router.get("/", {[&](Query &http) { + http.send(expected_default); + }}); + + ISOLATE( + router.listenOne(); + ) + + const string res = http->get(); + isolate_method.get(); + + EXPECT_EQ(expected_default, res); + } + + + + TEST_F(TestSuite, TestBasePost) { + + Router router; + router.setPort(8080); + + ISOLATE( + router.post("/", {[&](Query &http) { + http.send(expected_default); + }}); + router.listenOne(); + ) + + const string res = http->post(); + isolate_method.get(); + + EXPECT_EQ(res, res); + } + + + + + TEST_F(TestSuite, TestCompose) { + + Router router; + router.setPort(8080); + const string file = "../examples/file-template/index.html"; + + ISOLATE( + router.get("/", {[&](Query &http) { + int num_modules = 2; + http.compose(file, num_modules); + }}); + router.listenOne(); + ) + + const string res = http->get(); + isolate_method.get(); + + EXPECT_GT(res.length(), neosys::process::readFile(file).length()); + } + + + +TEST_F(TestSuite, TestReadFile) { + + Router router; + router.setPort(8080); + const string file = "../examples/files/test.json"; + + ISOLATE( + router.get("/", {[&](Query &http) { + http.readFile(file, "application/json"); + }}); + router.listenOne(); + ) + + const string response = http->get(); + isolate_method.get(); + + EXPECT_EQ(response, neosys::process::readFile(file)); +} + + + TEST_F(TestSuite, TestCppRender) { + + Router router; + const string file = "../examples/files/cpp.html"; + + router.setPort(8080); + router.get("/", {[&](Query &http) { + http.readFileX(file, "application/html"); + }}); + + ISOLATE( + + router.listenOne(); + ) + + string res = http->get(); + isolate_method.get(); + + const std::regex pattern("\\[(.*?)\\]"); + + if(std::smatch matches; + std::regex_search(res, matches, pattern)) + res = matches[1].str() ; + + + EXPECT_EQ(res, "hello from c++"); + } + + + + TEST_F(TestSuite, TestHeaders) { + + Router router; + router.setPort(8080); + const string file = "../examples/files/cpp.html"; + + router.get("/", {[&](Query &http) { + auto headers = http.body.getHeaders(); + HEADERS my_headers = { + "header-1: value1", + "header-2: value2", + "header-3: value3", + "header-N: valueN" + }; + http.setHeaders(my_headers); + http.send(headers.get("header-1").value); + }}); + + ISOLATE( + router.listenOne(); + ) + + VHeaders my_headers = { + "header-1: valueX" + }; + + const string res = http->get(my_headers); + isolate_method.get(); + + EXPECT_TRUE(res == "valueX"); + } + + + TEST_F(TestSuite, TestMiddleware) { + + Router router; + router.setPort(8080); + + router.post("/", { + + [&](Query &http) { + http.next(); + }, + [&](Query &http) { + http.send(expected_default); + + }}); + + ISOLATE( + router.listenOne(); + ) + + const string res = http->post(); + isolate_method.get(); + EXPECT_TRUE(expected_default == res); + } + + + +TEST_F(TestSuite, TestParametersQuery) { + + Router router; + router.setPort(8080); + + router.get("/",{[&](Query &web) { + + auto params = web.body.getParameters(); + if(!params.exist("id")) return web.send("error id not defined"); + + const string id_value = params.get("id").value; + + if( const size_t total = web.body.total_parameters(); + total == 0) return web.send("error with total_parameters"); + + web.send("success"); + + }}); + ISOLATE( + router.listenOne(); + ) + + const string res = http->get("/?id=2"); + isolate_method.get(); + + EXPECT_EQ(res, "success"); + } + + + + +TEST_F(TestSuite, TestParametersPost) { + + Router router; + router.setPort(8080); + + router.post("/",{[&](Query &web) { + + auto params = web.body.getParameters(); + if(!params.exist("id")) return web.send("error id not defined"); + + const string id_value = params.get("id").value; + + if( const size_t total = web.body.total_parameters(); + total == 0) return web.send("error with total_parameters"); + + web.send("success"); + + }}); + ISOLATE( + router.listenOne(); + ) + + POST fields = { + "id=2" + }; + + const string res = http->post(fields,"/"); + neosys::process::writeFile("./kevin.res.txt", res); + isolate_method.get(); + + EXPECT_EQ(res, "success"); + } + diff --git a/tests/suite.h b/tests/suite.h new file mode 100644 index 0000000..28ee266 --- /dev/null +++ b/tests/suite.h @@ -0,0 +1,37 @@ +#ifndef HEADERS_H +#define HEADERS_H + +#include "../include/vibe/vibe.h" +#include "../include/vibe/util/sysprocess.h" +#include "utils/min.veridic.h" +#include +#include +#include +#include +#include + +using std::string, std::future, std::shared_ptr, std::make_shared; +#define ISOLATE(logic) std::future isolate_method = std::async(std::launch::async, ([&]() { logic })); + +class TestSuite : public ::testing::Test { + + protected: + + static shared_ptr http; + static string url, expected_default; + + static void SetUpTestCase(){ + + url = "http://localhost:8080"; + expected_default = "success"; + http = make_shared(url); + + } +}; + +string TestSuite::url; +string TestSuite::expected_default; +shared_ptr TestSuite::http; + + +#endif //HEADERS_H diff --git a/tests/utils/min.veridic.h b/tests/utils/min.veridic.h new file mode 100644 index 0000000..44e80b1 --- /dev/null +++ b/tests/utils/min.veridic.h @@ -0,0 +1,618 @@ + +// Archivo: http.hpp + +#pragma once + +#ifndef HTTP_H +#define HTTP_H + +#define CURL_STATICLIB +#include +#include +#include +#include +#include +#include + + +#define PUT_TYPE "PUT" +#define POST_t "POST" +#define DELETE_TYPE "DELETE" +#define DEFAULT "00" + +using std::string; + + + +template +struct VHeaders_t { + + std::vector list; + VHeaders_t(std::initializer_list arguments) : list(arguments) { + if (!list.empty()){ + for(auto &it : list) { + std::cout << it << std::endl; + aloc.push_back(it); + } + initial = true; + } + } + bool initial{false}; + std::vector aloc{}; +}; +using VHeaders = VHeaders_t; + + + +template +struct FIELDS +{ + std::vector list; + FIELDS(std::initializer_list arguments) : list(arguments) {} + + string http_params{}; + string transform() + { + for (size_t i = 0; i < list.size(); i++){ + http_params += list[i] + "&"; + } + http_params[http_params.length()-1] = static_cast(00); + return http_params; + } +}; + +typedef FIELDS POST; +typedef FIELDS PUT; +typedef FIELDS GET; +typedef FIELDS DELETE; + + +class HTTP +{ +private: + std::shared_ptr curl = nullptr; + + std::vector http_VHeaders; + std::vector performs; + unsigned int queryIndice = 0; + string URL{}; + string response{}; + bool headerify{false}; + +public: + explicit HTTP(string); + HTTP() = default; + ~HTTP(); + static size_t callback(const void *, size_t, size_t, string *); + + int getSimple(const string& endpoint_= DEFAULT); + int getBase(GET *, const string &endpoint = DEFAULT, bool headers = false, const ::VHeaders *base = nullptr); + int get(GET& fields, const VHeaders & headers, const string& endpoint = DEFAULT); + int getVHeaders(const VHeaders &headers, const string& endpoint = DEFAULT); + + int postSimple(const string &endpoint = DEFAULT); + int postVHeaders(const VHeaders& headers, const string& end = DEFAULT); + int post(POST &, const string& endpoint = DEFAULT, const string& type = DEFAULT); + int post(POST *, const VHeaders &, const string& endpoint = DEFAULT, const string& type = DEFAULT); + + + int put(PUT &, const string& _endpoint=DEFAULT); + int put(PUT &, const VHeaders &, const string& _endpoint = DEFAULT); + + int Delete(DELETE &, const string& _endpoint = DEFAULT); + int Delete(DELETE &, const VHeaders &, const string& _endpoint = DEFAULT); + + int custom(POST &_fields, const string& type, const string& _endpoint = DEFAULT); + int custom(POST &_fields, const VHeaders &headers, const string &type, const string& _endpoint = DEFAULT); + + + static curl_slist* makeVHeaders(const std::vector&); + void setUrl(const string &); + int setVHeaders(const VHeaders&); + + [[nodiscard]] string Response() const; + static string without(string, char); + string genPerfomList(); +}; + +#endif // !HTTP_H +// Archivo: veridic.hpp + +#pragma once + +#ifndef VERIDIC_HPP +#define VERIDIC_HPP + +#include +#define PLAIN_TEXT "Content-Type: text/plain" + +using std::make_shared; +using std::shared_ptr; +using std::string; +using std::vector; + +class Veridic { + +private: + shared_ptr http = nullptr; + string URL{}; + +public: + Veridic(); + explicit Veridic(string ); + bool setUrl(const string&); + + string get(const string& endpoint = DEFAULT); + string get(const VHeaders &, const string& endpoint = DEFAULT); + string get(GET &, const string &endpoint = DEFAULT); + string get(GET &, const VHeaders &, const string& endpoint = DEFAULT); + + + string post(const string& endpoint = DEFAULT); + string post(const VHeaders &, const string& endpoint = DEFAULT); + string post(POST &, const string& endpoint = DEFAULT, const string &type = DEFAULT); + string post(POST &, const VHeaders &, const string& endpoint = DEFAULT, const string& type = DEFAULT); + + string put(PUT &, const string& endpoint = DEFAULT); + string put(PUT &, const VHeaders &, const string& _endpoint = DEFAULT); + + string Delete(DELETE &, const string& endpoint = DEFAULT); + string Delete(DELETE &, const VHeaders &, const string& endpoint = DEFAULT); + + string custom(POST &field, const string& type, const string& endpoint = DEFAULT); + string custom(POST &fields, const VHeaders &headers, const string& type, const string& endpoint = DEFAULT); +}; + +#endif + +#ifndef UTILS_HPP +#define UTILS_HPP + +constexpr auto UTILS_ERROR = "-[critic error]-"; +constexpr auto UTILS_WARNING = "-[warning]-"; +constexpr auto UTILS_SUCCESS = 0; + +constexpr auto SYSTEM_DECORATOR = "-[BAD SYSTEM RESPONSE]-"; +constexpr auto CURL_DECORATOR = "-[BAD CURL RESPONSE]-"; +constexpr auto BAD_RESULT = "-[BAD_USE]-"; + +constexpr auto VHTTP_ERROR = -1; +constexpr auto CURL_ERROR = -2; +constexpr auto HTTP_SUCCESS = 0; + +constexpr auto UTILS_USER_ERROR = 3; + +template +auto screen(std::ostream& out, C const &...content) -> void { + ((out<(curl_easy_init()); + if (!curl) { + screen(std::cout, UTILS_ERROR, SYSTEM_DECORATOR); + } +} + +inline HTTP::~HTTP() {curl.reset();} + +// callback function, this extract response of querys +inline size_t HTTP::callback(const void *buffer, size_t size, size_t nmemb, string *data) { + const size_t n = size * nmemb; + try { + data->append(static_cast(buffer), n); + } + catch (std::bad_alloc &e) { + screen(std::clog, UTILS_ERROR, SYSTEM_DECORATOR, &e); + } + return n; +} + + + +// base http get +inline int HTTP::getSimple(const std::string& endpoint_) { + const string temp_url = endpoint_ != DEFAULT ? URL +endpoint_ : URL; + + curl_easy_setopt(*curl, CURLOPT_HTTPGET, 1L); + curl_easy_setopt(*curl, CURLOPT_URL, temp_url.c_str()); + curl_easy_setopt(*curl, CURLOPT_WRITEFUNCTION, HTTP::callback); + curl_easy_setopt(*curl, CURLOPT_WRITEDATA, &response); + + CURLcode perfom = curl_easy_perform(*curl); + performs.push_back(perfom); + + try { + if (perfom != CURLE_OK) + screen(std::clog, UTILS_WARNING, CURL_DECORATOR, perfom); + } + catch (std::exception &error) { + screen(std::cout, UTILS_ERROR, &error); + } + curl_easy_cleanup(*curl); + return HTTP_SUCCESS; +} + +inline int HTTP::getBase(GET *fields, const std::string& endpoint, const bool headers, const VHeaders *base) { + + string temp_url = endpoint != DEFAULT ? URL +endpoint : URL; + struct curl_slist *VHeadersList = nullptr; + + if(fields != nullptr) { + temp_url += "?" + fields->transform(); + fields = nullptr; + } + + curl_easy_setopt(*curl, CURLOPT_HTTPGET, 1L); + curl_easy_setopt(*curl, CURLOPT_URL, temp_url.c_str()); + curl_easy_setopt(*curl, CURLOPT_WRITEFUNCTION, HTTP::callback); + curl_easy_setopt(*curl, CURLOPT_WRITEDATA, &response); + + if (headers) { + VHeadersList = makeVHeaders(base->aloc); + if (VHeadersList != nullptr){ + curl_easy_setopt(*curl, CURLOPT_HTTPHEADER, VHeadersList ); + } + } + + CURLcode perfom = curl_easy_perform(*curl); + performs.push_back(perfom); + + if (VHeadersList != nullptr){ + curl_slist_free_all(VHeadersList); + base = nullptr; + } + + try { + if (perfom != CURLE_OK) + screen(std::clog, UTILS_WARNING, CURL_DECORATOR, perfom); + } + catch (std::exception &error){ + screen(std::cout, UTILS_ERROR, &error); + return CURL_ERROR; + } + curl_easy_cleanup(*curl); + return HTTP_SUCCESS; +} + +inline int HTTP::get(GET &fields, const VHeaders &headers, const std::string& endpoint) { + return HTTP::getBase(&fields, endpoint, true, &headers); +} + +inline int HTTP::getVHeaders(const VHeaders &headers, const string& endpoint) { + return HTTP::getBase(nullptr, endpoint, true, &headers); +} + +// base http post +inline int HTTP::post(POST &fields, const string& endpoint, const string& type) { + + string temp_url = endpoint != DEFAULT ? URL +endpoint : URL; + + auto postFields = fields.transform(); + + curl_easy_setopt(*curl, CURLOPT_URL, temp_url.c_str()); + curl_easy_setopt(*curl, CURLOPT_WRITEFUNCTION, HTTP::callback); + curl_easy_setopt(*curl, CURLOPT_POSTFIELDS, postFields.c_str()); + curl_easy_setopt(*curl, CURLOPT_WRITEDATA, &response); + + if (type != DEFAULT) { + curl_easy_setopt(*curl, CURLOPT_CUSTOMREQUEST, type.c_str()); + } else{ + curl_easy_setopt(*curl, CURLOPT_CUSTOMREQUEST, (const char*)POST_t); + } + + CURLcode perfom = curl_easy_perform(*curl); + performs.push_back(perfom); + + try { + if (perfom != CURLE_OK) + screen(std::clog, UTILS_WARNING, CURL_DECORATOR, perfom); + } + catch (std::exception &error) { + screen(std::cout, UTILS_ERROR, &error); + return CURL_ERROR; + } + curl_easy_cleanup(*curl); + return HTTP_SUCCESS; +} + +inline int HTTP::post(POST *fields, const VHeaders &headers, const string& endpoint, const string& type) { + + string temp_url = endpoint != DEFAULT ? URL +endpoint : URL; + struct curl_slist *VHeadersList = nullptr; + + curl_easy_setopt(*curl, CURLOPT_URL, temp_url.c_str()); + curl_easy_setopt(*curl, CURLOPT_WRITEFUNCTION, HTTP::callback); + curl_easy_setopt(*curl, CURLOPT_WRITEDATA, &response); + + if(fields != nullptr) { + const auto postFields = fields->transform(); + curl_easy_setopt(*curl, CURLOPT_POSTFIELDS, postFields.c_str()); + fields = nullptr; + } + + if (type != DEFAULT){ + curl_easy_setopt(*curl, CURLOPT_CUSTOMREQUEST, type.c_str()); + } + + VHeadersList = makeVHeaders(headers.aloc); + curl_easy_setopt(*curl, CURLOPT_HTTPHEADER, VHeadersList ); + + CURLcode perfom = curl_easy_perform(*curl); + performs.push_back(perfom); + + curl_slist_free_all(VHeadersList); + + try { + if (perfom != CURLE_OK) + screen(std::clog, UTILS_WARNING, CURL_DECORATOR, perfom); + } + catch (std::exception &error) { + screen(std::cout, UTILS_ERROR, &error); + return CURL_ERROR; + } + curl_easy_cleanup(*curl); + return HTTP_SUCCESS; +} + +inline int HTTP::postVHeaders(const VHeaders &headers, const std::string& end) { + return HTTP::post(nullptr, headers, end, "POST"); +} + +inline int HTTP::postSimple(const std::string &endpoint) { + string temp_url = endpoint != DEFAULT ? URL +endpoint : URL; + + curl_easy_setopt(*curl, CURLOPT_URL, temp_url.c_str()); + curl_easy_setopt(*curl, CURLOPT_WRITEFUNCTION, HTTP::callback); + curl_easy_setopt(*curl, CURLOPT_WRITEDATA, &response); + curl_easy_setopt(*curl, CURLOPT_CUSTOMREQUEST, (const char*)POST_t); + + CURLcode perfom = curl_easy_perform(*curl); + performs.push_back(perfom); + + try { + if (perfom != CURLE_OK) + screen(std::clog, UTILS_WARNING, CURL_DECORATOR, perfom); + } + catch (std::exception &error) { + screen(std::cout, UTILS_ERROR, &error); + return CURL_ERROR; + } + curl_easy_cleanup(*curl); + return HTTP_SUCCESS; +} + +inline int HTTP::put(PUT &_fields, const string& _endpoint) { + return (_endpoint != DEFAULT) ? post(_fields, _endpoint, PUT_TYPE) : post(_fields, PUT_TYPE); +} + +inline int HTTP::put(PUT &_fields, const VHeaders &headers, const string& _endpoint) { + return (_endpoint != DEFAULT) ? post(&_fields, headers, _endpoint, PUT_TYPE) : post(&_fields, headers, PUT_TYPE); +} + +inline int HTTP::Delete(DELETE &_fields, const string& _endpoint) { + return (_endpoint != DEFAULT) ? post(_fields, _endpoint, DELETE_TYPE) : post(_fields, DELETE_TYPE); +} + +inline int HTTP::Delete(DELETE &_fields, const VHeaders &headers, const string& _endpoint) { + return (_endpoint != DEFAULT) ? post(&_fields, headers, _endpoint, DELETE_TYPE) : post(&_fields, headers, DELETE_TYPE); +} + +inline int HTTP::custom(POST &_fields, const string& type, const string& _endpoint) { + return (_endpoint != DEFAULT) ? post(_fields, _endpoint, type) : post(_fields, type); +} + +inline int HTTP::custom(POST &_fields, const VHeaders &headers, const string &type, const string& _endpoint) { + return (_endpoint != DEFAULT) ? post(&_fields, headers, _endpoint, type) : post(&_fields, headers, type); +} + +inline int HTTP::setVHeaders(const VHeaders &headers) +{ + + if (!headers.initial) + return UTILS_USER_ERROR; + http_VHeaders = headers.aloc; + headerify = true; + return UTILS_SUCCESS; +} + +inline curl_slist *HTTP::makeVHeaders(const std::vector& headers) { + struct curl_slist *list = nullptr; + + if (headers.empty()) + return list; + + for (auto &it : headers) { + std::cout << it << std::endl; + list = curl_slist_append(list, it.c_str()); + } + return list; +} + +inline void HTTP::setUrl(const string &_url){ + URL = _url; +} + +// extract response of the querys +inline string HTTP::Response() const { + return response; +} + +// remove separator send of the API +inline string HTTP::without(string target, const char key) { + for (auto &it : target) { + if (it == key) + it = static_cast(00); + } + return target; +} + +// extract the list of result of querys +inline string HTTP::genPerfomList(){ + int map{}; + for (const auto &it : performs){ + map += it; + } + return std::to_string(map); +} +// Archivo: veridic.cpp + + +inline Veridic::Veridic(string tasty_url) : URL(std::move(tasty_url)) {} + +inline bool Veridic::setUrl(const string& url) { + if (!url.empty()) { + URL = url; + return true; + } + return false; +} + +inline string Veridic::get(const string& endpoint) +{ + if (URL.empty()) + return BAD_RESULT; + http = make_shared(URL); + + if (http->getSimple(endpoint != DEFAULT ? endpoint : "") != HTTP_SUCCESS) + return BAD_RESULT; + + auto response = http->Response(); + http.reset(); + return response; +} + +inline string Veridic::get(GET &fields, const string &endpoint) +{ + if (URL.empty()) + return BAD_RESULT; + http = make_shared(URL); + + if (http->getBase(&fields, endpoint != DEFAULT ? endpoint : "") != HTTP_SUCCESS) + return BAD_RESULT; + + auto response = http->Response(); + http.reset(); + return response; +} + +inline string Veridic::get(GET &fields, const VHeaders& headers, const string& endpoint) +{ + if (URL.empty()) + return BAD_RESULT; + http = make_shared(URL); + + if (http->get(fields, headers, endpoint != DEFAULT ? endpoint : "") != HTTP_SUCCESS) + return BAD_RESULT; + + auto response = http->Response(); + http.reset(); + return response; +} + +inline string Veridic::get(const VHeaders& headers, const string& endpoint) +{ + if (URL.empty()) + return BAD_RESULT; + http = make_shared(URL); + + if (http->getVHeaders(headers, endpoint != DEFAULT ? endpoint : "") != HTTP_SUCCESS) + return BAD_RESULT; + + auto response = http->Response(); + http.reset(); + return response; +} + + +inline string Veridic::post(POST &fields, const string& endpoint, const string &type) +{ + + if (URL.empty()) + return BAD_RESULT; + http = make_shared(URL); + + if (http->post(fields, endpoint != DEFAULT ? endpoint : "", !type.empty() ? type : "" ) != HTTP_SUCCESS) + return BAD_RESULT; + + auto response = http->Response(); + http.reset(); + return response; +} + +inline string Veridic::post(POST &fields, const VHeaders &headers, const string& endpoint, const string& type) +{ + + if (URL.empty()) + return BAD_RESULT; + if (!headers.initial) + return BAD_RESULT; + + http = make_shared(URL); + + if (http->post(&fields, headers, endpoint != DEFAULT ? endpoint : "", !type.empty() ? type : "" ) != HTTP_SUCCESS) + return BAD_RESULT; + + auto response = http->Response(); + http.reset(); + return response; +} + +inline string Veridic::post(const std::string& endpoint) { + if (URL.empty()) + return BAD_RESULT; + + http = make_shared(URL); + + if (http->postSimple(endpoint != DEFAULT ? endpoint : "") != HTTP_SUCCESS) + return BAD_RESULT; + + auto response = http->Response(); + http.reset(); + return response; +} + +inline string Veridic::post(const VHeaders &headers, const std::string& endpoint) { + if (URL.empty()) + return BAD_RESULT; + if (!headers.initial) + return BAD_RESULT; + + http = make_shared(URL); + + if (http->postVHeaders(headers, endpoint != DEFAULT ? endpoint : "") != HTTP_SUCCESS) + return BAD_RESULT; + + auto response = http->Response(); + http.reset(); + return response; +} + +inline string Veridic::put(PUT &_fields, const string& endpoint) { + return endpoint != DEFAULT ? post(_fields, endpoint, PUT_TYPE) :post(_fields, PUT_TYPE) ; +} + +inline string Veridic::put(PUT &_fields, const VHeaders &headers, const string& _endpoint) { + return _endpoint != DEFAULT ? post(_fields,headers, _endpoint, PUT_TYPE) :post(_fields, headers, PUT_TYPE) ; +} + +inline string Veridic::Delete(DELETE &_fields, const string& endpoint) { + return endpoint != DEFAULT ? post(_fields, endpoint, DELETE_TYPE) : post(_fields, DELETE_TYPE); +} + +inline string Veridic::Delete(DELETE &_fields, const VHeaders &headers, const string& endpoint) { + return endpoint != DEFAULT ? post(_fields, headers, endpoint, DELETE_TYPE) : post(_fields, headers, DELETE_TYPE); +} + +inline string Veridic::custom(POST &field, const string& type, const string& endpoint) { + return endpoint != DEFAULT ?post(field, endpoint, type) : post(field, type); +} + +inline string Veridic::custom(POST &fields, const VHeaders &headers, const string& type, const string& endpoint) { + return endpoint != DEFAULT ?post(fields, headers , endpoint, type) : post(fields, type); +} \ No newline at end of file