From fc579f92990c70592c9267256ed94afcf3516379 Mon Sep 17 00:00:00 2001 From: wtlgo Date: Tue, 10 Jan 2023 14:03:07 +0300 Subject: [PATCH 01/46] Add clang-format --- .clang-format | 3 + CMakeLists.txt | 7 +- include/wtlgo/Network.hpp | 38 ++++++---- src/Network.cpp | 151 ++++++++++++++++++++------------------ test/CMakeLists.txt | 20 ++--- 5 files changed, 122 insertions(+), 97 deletions(-) create mode 100644 .clang-format diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..4a05f3d --- /dev/null +++ b/.clang-format @@ -0,0 +1,3 @@ +BasedOnStyle: Google +IndentWidth: 4 +AccessModifierOffset: -4 diff --git a/CMakeLists.txt b/CMakeLists.txt index b4894ff..65f933c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,8 +16,13 @@ target_link_libraries(Network PUBLIC ${CURL_LIBRARIES}) target_include_directories(Network PUBLIC include/) target_include_directories(Network PRIVATE include/wtlgo/ ${CURL_INCLUDE_DIR}) + +set(PUBLIC_HEADERS + "include/wtlgo/Network.hpp" +) + set_target_properties(Network PROPERTIES - PUBLIC_HEADER include/wtlgo/Network.hpp + PUBLIC_HEADER "${PUBLIC_HEADERS}" VERSION ${PROJECT_VERSION} ) diff --git a/include/wtlgo/Network.hpp b/include/wtlgo/Network.hpp index 039c5c3..4db8948 100644 --- a/include/wtlgo/Network.hpp +++ b/include/wtlgo/Network.hpp @@ -1,5 +1,5 @@ -#ifndef Network_hpp -#define Network_hpp +#ifndef __NETWORK_HPP__ +#define __NETWORK_HPP__ #include #include @@ -11,33 +11,39 @@ namespace wtlgo { class Network { public: static Network& instance(); - + Network(Network const&) = delete; void operator=(Network const&) = delete; - + void set_proxy(const std::string& proxy); - - std::string request(std::string url, const std::map& args = {}, bool post = false) const; - - std::string upload(std::string url, const std::string& fieldname, const std::string& filename) const; - - bool download(const std::string& url, const std::string& save_as = "") const; - + + std::string request(std::string url, + const std::map& args = {}, + bool post = false) const; + + std::string upload(std::string url, const std::string& fieldname, + const std::string& filename) const; + + bool download(const std::string& url, + const std::string& save_as = "") const; + private: std::string proxy; Network(); ~Network(); - - static size_t string_writer(char* contents, size_t size, size_t nmemb, std::string* stream); - static size_t file_writer(void* contents, size_t size, size_t nmemb, FILE* stream); - std::string join(const std::vector lst, const std::string& delim) const; + static size_t string_writer(char* contents, size_t size, size_t nmemb, + std::string* stream); + static size_t file_writer(void* contents, size_t size, size_t nmemb, + FILE* stream); + + std::string join(const std::vector lst, + const std::string& delim) const; std::string url_encode(const std::string& str) const; }; extern Network& network; - } #endif /* Network_hpp */ diff --git a/src/Network.cpp b/src/Network.cpp index 10e345f..1a89ce8 100644 --- a/src/Network.cpp +++ b/src/Network.cpp @@ -14,9 +14,7 @@ wtlgo::Network& wtlgo::network = wtlgo::Network::instance(); using namespace wtlgo; -Network::Network() { - curl_global_init(CURL_GLOBAL_ALL); -} +Network::Network() { curl_global_init(CURL_GLOBAL_ALL); } Network::~Network() {} @@ -25,48 +23,52 @@ Network& Network::instance() { return instance; } -void Network::set_proxy(const std::string& proxy) { - this->proxy = proxy; -} +void Network::set_proxy(const std::string& proxy) { this->proxy = proxy; } -std::string Network::request(std::string url, const std::map& args, bool post) const { - std::unique_ptr curl { curl_easy_init(), curl_easy_cleanup }; +std::string Network::request(std::string url, + const std::map& args, + bool post) const { + std::unique_ptr curl{curl_easy_init(), + curl_easy_cleanup}; CURLcode res; std::string readBuffer; - + std::string fields; { std::vector tmp_list; - for(const std::pair& row : args) { - tmp_list.push_back(url_encode(row.first) + "=" + url_encode(row.second)); + for (const std::pair& row : args) { + tmp_list.push_back(url_encode(row.first) + "=" + + url_encode(row.second)); } fields = join(tmp_list, "&"); } - - if(curl) { - if(fields.size() > 0) { - if(post) { + + if (curl) { + if (fields.size() > 0) { + if (post) { curl_easy_setopt(curl.get(), CURLOPT_POST, 1); - curl_easy_setopt(curl.get(), CURLOPT_POSTFIELDS, fields.c_str()); - } - else { + curl_easy_setopt(curl.get(), CURLOPT_POSTFIELDS, + fields.c_str()); + } else { url += "?" + fields; } } - + curl_easy_setopt(curl.get(), CURLOPT_SSL_VERIFYPEER, 0L); - curl_easy_setopt(curl.get(), CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); - curl_easy_setopt(curl.get(), CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); + curl_easy_setopt(curl.get(), CURLOPT_HTTP_VERSION, + CURL_HTTP_VERSION_1_1); + curl_easy_setopt(curl.get(), CURLOPT_HTTP_VERSION, + CURL_HTTP_VERSION_1_1); curl_easy_setopt(curl.get(), CURLOPT_URL, url.c_str()); curl_easy_setopt(curl.get(), CURLOPT_WRITEDATA, &readBuffer); curl_easy_setopt(curl.get(), CURLOPT_WRITEFUNCTION, string_writer); curl_easy_setopt(curl.get(), CURLOPT_FOLLOWLOCATION, 1); - if(proxy.size() > 0) + if (proxy.size() > 0) curl_easy_setopt(curl.get(), CURLOPT_PROXY, proxy.c_str()); - + res = curl_easy_perform(curl.get()); - - if(res != 0) { + + if (res != 0) { std::cerr << curl_easy_strerror(res) << std::endl; return ""; } @@ -75,101 +77,110 @@ std::string Network::request(std::string url, const std::map curl { curl_easy_init(), curl_easy_cleanup }; +bool Network::download(const std::string& url, + const std::string& save_as) const { + std::unique_ptr curl{curl_easy_init(), + curl_easy_cleanup}; CURLcode res; - + std::string filename = save_as; - if(filename.size() == 0) { + if (filename.size() == 0) { std::string::size_type slash_p = url.find_last_of('/'); filename = std::string(url.begin() + 1 + slash_p, url.end()); } - - if(curl) { - std::unique_ptr file(fopen(filename.c_str(), "wb"), fclose); - - curl_easy_setopt(curl.get(), CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); + + if (curl) { + std::unique_ptr file( + fopen(filename.c_str(), "wb"), fclose); + + curl_easy_setopt(curl.get(), CURLOPT_HTTP_VERSION, + CURL_HTTP_VERSION_1_1); curl_easy_setopt(curl.get(), CURLOPT_URL, url.c_str()); curl_easy_setopt(curl.get(), CURLOPT_WRITEDATA, file.get()); curl_easy_setopt(curl.get(), CURLOPT_WRITEFUNCTION, file_writer); curl_easy_setopt(curl.get(), CURLOPT_FOLLOWLOCATION, 1); - if(proxy.size() > 0) + if (proxy.size() > 0) curl_easy_setopt(curl.get(), CURLOPT_PROXY, proxy.c_str()); - + res = curl_easy_perform(curl.get()); - - if(res != 0){ + + if (res != 0) { std::cerr << curl_easy_strerror(res) << std::endl; remove(filename.c_str()); return false; } - } - else { + } else { return false; } - + return true; } -std::string Network::upload(std::string url, const std::string& fieldname, const std::string& filename) const { - std::unique_ptr curl { curl_easy_init(), curl_easy_cleanup }; +std::string Network::upload(std::string url, const std::string& fieldname, + const std::string& filename) const { + std::unique_ptr curl{curl_easy_init(), + curl_easy_cleanup}; CURLcode res; std::string readBuffer; - + if (curl) { - std::unique_ptr formpost([&fieldname, &filename]{ - curl_httppost *formpost = nullptr; - curl_httppost *lastptr = nullptr; - - curl_formadd(&formpost, - &lastptr, - CURLFORM_COPYNAME, fieldname.c_str(), - CURLFORM_FILE, filename.c_str(), - CURLFORM_END); - - return formpost; - }(), curl_formfree); - - curl_easy_setopt(curl.get(), CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); + std::unique_ptr formpost( + [&fieldname, &filename] { + curl_httppost* formpost = nullptr; + curl_httppost* lastptr = nullptr; + + curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, + fieldname.c_str(), CURLFORM_FILE, filename.c_str(), + CURLFORM_END); + + return formpost; + }(), + curl_formfree); + + curl_easy_setopt(curl.get(), CURLOPT_HTTP_VERSION, + CURL_HTTP_VERSION_1_1); curl_easy_setopt(curl.get(), CURLOPT_WRITEFUNCTION, string_writer); curl_easy_setopt(curl.get(), CURLOPT_WRITEDATA, &readBuffer); curl_easy_setopt(curl.get(), CURLOPT_URL, url.c_str()); curl_easy_setopt(curl.get(), CURLOPT_HTTPPOST, formpost.get()); - + res = curl_easy_perform(curl.get()); - - if (res != CURLE_OK){ + + if (res != CURLE_OK) { std::cerr << curl_easy_strerror(res) << std::endl; return ""; } } - + return readBuffer; } -size_t Network::string_writer(char* contents, size_t size, size_t nmemb, std::string* stream) { +size_t Network::string_writer(char* contents, size_t size, size_t nmemb, + std::string* stream) { stream->append(contents, size * nmemb); return size * nmemb; } -size_t Network::file_writer(void* contents, size_t size, size_t nmemb, FILE* stream) { +size_t Network::file_writer(void* contents, size_t size, size_t nmemb, + FILE* stream) { size_t written = fwrite(contents, size, nmemb, stream); return written; } -std::string Network::join(const std::vector lst, const std::string& delim) const { +std::string Network::join(const std::vector lst, + const std::string& delim) const { std::ostringstream ss; - for(size_t i = 0; i < lst.size(); i++) + for (size_t i = 0; i < lst.size(); i++) ss << lst[i] << (i + 1 == lst.size() ? "" : delim); return ss.str(); } std::string Network::url_encode(const std::string& str) const { - std::unique_ptr curl { curl_easy_init(), curl_easy_cleanup }; - std::unique_ptr data { + std::unique_ptr curl{curl_easy_init(), + curl_easy_cleanup}; + std::unique_ptr data{ curl_easy_escape(curl.get(), str.c_str(), static_cast(str.size())), - curl_free - }; + curl_free}; return data ? std::string(data.get()) : str; } diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 99a94d6..ec4a8c8 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -7,20 +7,20 @@ include(GoogleTest) if(${GTest_FOUND} AND ${nlohmann_json_FOUND}) -SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread") -file(GLOB TEST_SRC - "src/*.hpp" - "src/*.cpp" -) + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread") + file(GLOB TEST_SRC + "src/*.hpp" + "src/*.cpp" + ) -add_executable(Network_test ${TEST_SRC}) -target_link_libraries(Network_test Network ${GTEST_LIBRARIES} nlohmann_json) -target_include_directories(Network_test PRIVATE ${GTEST_INCLUDE_DIR}) -gtest_add_tests(TARGET Network_test AUTO) + add_executable(Network_test ${TEST_SRC}) + target_link_libraries(Network_test Network ${GTEST_LIBRARIES} nlohmann_json) + target_include_directories(Network_test PRIVATE ${GTEST_INCLUDE_DIR}) + gtest_add_tests(TARGET Network_test AUTO) else() -message(WARNING "You should install GTest and nlohmann-json to enable tests.") + message(WARNING "You should install GTest and nlohmann-json to enable tests.") endif() From 044408431794f4f93bfcbadd083d2bb5a57fcddf Mon Sep 17 00:00:00 2001 From: wtlgo Date: Tue, 10 Jan 2023 14:04:38 +0300 Subject: [PATCH 02/46] Add clang-format --- test/src/PrimaryTest.cpp | 3 +- test/src/RequestTestsGet.cpp | 68 +++++++++++++++++------------------ test/src/RequestTestsPost.cpp | 68 +++++++++++++++++------------------ test/src/utility.cpp | 5 +-- 4 files changed, 72 insertions(+), 72 deletions(-) diff --git a/test/src/PrimaryTest.cpp b/test/src/PrimaryTest.cpp index 31cc2b9..80671dd 100644 --- a/test/src/PrimaryTest.cpp +++ b/test/src/PrimaryTest.cpp @@ -1,8 +1,7 @@ #include #include -TEST(Primary, DidInit) -{ +TEST(Primary, DidInit) { using namespace wtlgo; ASSERT_EQ(&network, &Network::instance()); } diff --git a/test/src/RequestTestsGet.cpp b/test/src/RequestTestsGet.cpp index 4df64ff..f340294 100644 --- a/test/src/RequestTestsGet.cpp +++ b/test/src/RequestTestsGet.cpp @@ -5,106 +5,106 @@ #include "utility.hpp" -TEST(Request, Get_NoSSL_Static) -{ +TEST(Request, Get_NoSSL_Static) { using namespace wtlgo; using json = nlohmann::json; using string = std::string; - - string response = network.request("http://" + test_server + "/get", {{"hello", "hello"}}); + + string response = + network.request("http://" + test_server + "/get", {{"hello", "hello"}}); ASSERT_NO_THROW({ auto resp = json::parse(response); ASSERT_EQ(resp["args"]["hello"], "hello"); }); } -TEST(Request, Get_SSL_Static) -{ +TEST(Request, Get_SSL_Static) { using namespace wtlgo; using json = nlohmann::json; using string = std::string; - - string response = network.request("https://" + test_server + "/get", {{"hello", "hello"}}); + + string response = network.request("https://" + test_server + "/get", + {{"hello", "hello"}}); ASSERT_NO_THROW({ auto resp = json::parse(response); ASSERT_EQ(resp["args"]["hello"], "hello"); }); } -TEST(Request, Get_NoSSL_Random) -{ +TEST(Request, Get_NoSSL_Random) { using namespace wtlgo; using json = nlohmann::json; using string = std::string; - + ASSERT_NO_THROW({ const string arg = random_string(500); const string val = random_string(1000); - - string response = network.request("http://" + test_server + "/get", {{arg, val}}); + + string response = + network.request("http://" + test_server + "/get", {{arg, val}}); auto resp = json::parse(response); - + ASSERT_EQ(resp["args"][arg], val); }); } -TEST(Request, Get_SSL_Random) -{ +TEST(Request, Get_SSL_Random) { using namespace wtlgo; using json = nlohmann::json; using string = std::string; - + ASSERT_NO_THROW({ const string arg = random_string(500); const string val = random_string(500); - - string response = network.request("https://" + test_server + "/get", {{arg, val}}); + + string response = + network.request("https://" + test_server + "/get", {{arg, val}}); auto resp = json::parse(response); - + ASSERT_EQ(resp["args"][arg], val); }); } -TEST(Request, Get_NoSSL_Random_MultipleArgs) -{ +TEST(Request, Get_NoSSL_Random_MultipleArgs) { using namespace wtlgo; using json = nlohmann::json; using string = std::string; using map = std::map; map args; - for(size_t i = 0; i < 10; ++i) { + for (size_t i = 0; i < 10; ++i) { args[random_string(50)] = random_string(50); } ASSERT_NO_THROW({ - string response = network.request("http://" + test_server + "/get", args); + string response = + network.request("http://" + test_server + "/get", args); auto resp = json::parse(response); - - for(const auto& arg : args) { + + for (const auto& arg : args) { ASSERT_EQ(resp["args"][arg.first], arg.second); - } + } }); } -TEST(Request, Get_SSL_Random_MultipleArgs) -{ +TEST(Request, Get_SSL_Random_MultipleArgs) { using namespace wtlgo; using json = nlohmann::json; using string = std::string; using map = std::map; map args; - for(size_t i = 0; i < 10; ++i) { + for (size_t i = 0; i < 10; ++i) { args[random_string(50)] = random_string(50); } ASSERT_NO_THROW({ - string response = network.request("https://" + test_server + "/get", args); + string response = + network.request("https://" + test_server + "/get", args); auto resp = json::parse(response); - - for(const auto& arg : args) { + + for (const auto& arg : args) { ASSERT_EQ(resp["args"][arg.first], arg.second); - } + } }); } diff --git a/test/src/RequestTestsPost.cpp b/test/src/RequestTestsPost.cpp index 8d2f05d..ce0caaa 100644 --- a/test/src/RequestTestsPost.cpp +++ b/test/src/RequestTestsPost.cpp @@ -5,106 +5,106 @@ #include "utility.hpp" -TEST(Request, Post_NoSSL_Static) -{ +TEST(Request, Post_NoSSL_Static) { using namespace wtlgo; using json = nlohmann::json; using string = std::string; - - string response = network.request("http://" + test_server + "/post", {{"hello", "hello"}}, true); + + string response = network.request("http://" + test_server + "/post", + {{"hello", "hello"}}, true); ASSERT_NO_THROW({ auto resp = json::parse(response); ASSERT_EQ(resp["form"]["hello"], "hello"); }); } -TEST(Request, Post_SSL_Static) -{ +TEST(Request, Post_SSL_Static) { using namespace wtlgo; using json = nlohmann::json; using string = std::string; - - string response = network.request("https://" + test_server + "/post", {{"hello", "hello"}}, true); + + string response = network.request("https://" + test_server + "/post", + {{"hello", "hello"}}, true); ASSERT_NO_THROW({ auto resp = json::parse(response); ASSERT_EQ(resp["form"]["hello"], "hello"); }); } -TEST(Request, Post_NoSSL_Random) -{ +TEST(Request, Post_NoSSL_Random) { using namespace wtlgo; using json = nlohmann::json; using string = std::string; - + ASSERT_NO_THROW({ const string arg = random_string(1000); const string val = random_string(1000); - - string response = network.request("http://" + test_server + "/post", {{arg, val}}, true); + + string response = network.request("http://" + test_server + "/post", + {{arg, val}}, true); auto resp = json::parse(response); - + ASSERT_EQ(resp["form"][arg], val); }); } -TEST(Request, Post_SSL_Random) -{ +TEST(Request, Post_SSL_Random) { using namespace wtlgo; using json = nlohmann::json; using string = std::string; - + ASSERT_NO_THROW({ const string arg = random_string(1000); const string val = random_string(1000); - - string response = network.request("https://" + test_server + "/post", {{arg, val}}, true); + + string response = network.request("https://" + test_server + "/post", + {{arg, val}}, true); auto resp = json::parse(response); - + ASSERT_EQ(resp["form"][arg], val); }); } -TEST(Request, Post_NoSSL_Random_MultipleArgs) -{ +TEST(Request, Post_NoSSL_Random_MultipleArgs) { using namespace wtlgo; using json = nlohmann::json; using string = std::string; using map = std::map; map args; - for(size_t i = 0; i < 10; ++i) { + for (size_t i = 0; i < 10; ++i) { args[random_string(1000)] = random_string(1000); } ASSERT_NO_THROW({ - string response = network.request("http://" + test_server + "/post", args, true); + string response = + network.request("http://" + test_server + "/post", args, true); auto resp = json::parse(response); - - for(const auto& arg : args) { + + for (const auto& arg : args) { ASSERT_EQ(resp["form"][arg.first], arg.second); - } + } }); } -TEST(Request, Post_SSL_Random_MultipleArgs) -{ +TEST(Request, Post_SSL_Random_MultipleArgs) { using namespace wtlgo; using json = nlohmann::json; using string = std::string; using map = std::map; map args; - for(size_t i = 0; i < 10; ++i) { + for (size_t i = 0; i < 10; ++i) { args[random_string(1000)] = random_string(1000); } - string response = network.request("https://" + test_server + "/post", args, true); + string response = + network.request("https://" + test_server + "/post", args, true); ASSERT_NO_THROW({ auto resp = json::parse(response); - - for(const auto& arg : args) { + + for (const auto& arg : args) { ASSERT_EQ(resp["form"][arg.first], arg.second); - } + } }); } diff --git a/test/src/utility.cpp b/test/src/utility.cpp index ae25864..11f6ff0 100644 --- a/test/src/utility.cpp +++ b/test/src/utility.cpp @@ -5,11 +5,12 @@ const std::string test_server = "httpbin.org"; std::string random_string(size_t max_length) { - static std::mt19937_64 engine { (std::random_device())() }; + static std::mt19937_64 engine{(std::random_device())()}; std::uniform_int_distribution sdist(0, max_length); std::uniform_int_distribution cdist(0, 127); std::string out; - std::generate_n(std::back_inserter(out), sdist(engine), [&cdist]{ return cdist(engine); }); + std::generate_n(std::back_inserter(out), sdist(engine), + [&cdist] { return cdist(engine); }); return out; } From 1bf9e0d109e00f74548d4e9db5f1e632c0ea0bd2 Mon Sep 17 00:00:00 2001 From: wtlgo Date: Tue, 10 Jan 2023 18:42:49 +0300 Subject: [PATCH 03/46] Adjust CmakeLists.txt --- CMakeLists.txt | 10 ++++++---- src/Network.cpp | 8 ++++++-- test/CMakeLists.txt | 36 ++++++++++++++++++++---------------- test/src/test.cpp | 6 ------ test/src/utility.cpp | 2 +- test/src/utility.hpp | 2 +- 6 files changed, 34 insertions(+), 30 deletions(-) delete mode 100644 test/src/test.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 65f933c..e624536 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,10 +12,10 @@ find_package(CURL REQUIRED) add_library(Network src/Network.cpp include/wtlgo/Network.hpp) target_compile_features(Network PUBLIC cxx_std_17) -target_link_libraries(Network PUBLIC ${CURL_LIBRARIES}) +target_link_libraries(Network PUBLIC CURL::libcurl) target_include_directories(Network PUBLIC include/) -target_include_directories(Network PRIVATE include/wtlgo/ ${CURL_INCLUDE_DIR}) +target_include_directories(Network PRIVATE include/wtlgo/) set(PUBLIC_HEADERS "include/wtlgo/Network.hpp" @@ -33,5 +33,7 @@ install( PUBLIC_HEADER DESTINATION include/wtlgo COMPONENT Development ) -enable_testing() -add_subdirectory(test) +if(DEFINED ENABLE_TESTING) + enable_testing() + add_subdirectory(test) +endif() diff --git a/src/Network.cpp b/src/Network.cpp index 1a89ce8..cd1a3de 100644 --- a/src/Network.cpp +++ b/src/Network.cpp @@ -63,8 +63,9 @@ std::string Network::request(std::string url, curl_easy_setopt(curl.get(), CURLOPT_WRITEDATA, &readBuffer); curl_easy_setopt(curl.get(), CURLOPT_WRITEFUNCTION, string_writer); curl_easy_setopt(curl.get(), CURLOPT_FOLLOWLOCATION, 1); - if (proxy.size() > 0) + if (proxy.size() > 0) { curl_easy_setopt(curl.get(), CURLOPT_PROXY, proxy.c_str()); + } res = curl_easy_perform(curl.get()); @@ -170,8 +171,11 @@ size_t Network::file_writer(void* contents, size_t size, size_t nmemb, std::string Network::join(const std::vector lst, const std::string& delim) const { std::ostringstream ss; - for (size_t i = 0; i < lst.size(); i++) + + for (size_t i = 0; i < lst.size(); i++) { ss << lst[i] << (i + 1 == lst.size() ? "" : delim); + } + return ss.str(); } diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index ec4a8c8..030ea9b 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,26 +1,30 @@ cmake_minimum_required(VERSION 3.13) -find_package(GTest) -find_package(nlohmann_json) -include(GoogleTest) +include(FetchContent) + -if(${GTest_FOUND} AND ${nlohmann_json_FOUND}) +FetchContent_Declare( + json + URL https://github.com/nlohmann/json/releases/download/v3.11.2/json.tar.xz +) +FetchContent_MakeAvailable(json) - SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread") - file(GLOB TEST_SRC - "src/*.hpp" - "src/*.cpp" - ) +FetchContent_Declare( + googletest + URL https://github.com/google/googletest/archive/03597a01ee50ed33e9dfd640b249b4be3799d395.zip +) - add_executable(Network_test ${TEST_SRC}) - target_link_libraries(Network_test Network ${GTEST_LIBRARIES} nlohmann_json) - target_include_directories(Network_test PRIVATE ${GTEST_INCLUDE_DIR}) - gtest_add_tests(TARGET Network_test AUTO) +set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) +FetchContent_MakeAvailable(googletest) -else() - message(WARNING "You should install GTest and nlohmann-json to enable tests.") +file(GLOB TEST_SRC + "src/*.cpp" +) -endif() +add_executable(Network_test ${TEST_SRC}) +target_link_libraries(Network_test Network GTest::gtest_main nlohmann_json::nlohmann_json) +include(GoogleTest) +gtest_discover_tests(Network_test) diff --git a/test/src/test.cpp b/test/src/test.cpp deleted file mode 100644 index f81367c..0000000 --- a/test/src/test.cpp +++ /dev/null @@ -1,6 +0,0 @@ -#include - -int main(int argc, char* argv[]) { - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} diff --git a/test/src/utility.cpp b/test/src/utility.cpp index 11f6ff0..ec2bcb3 100644 --- a/test/src/utility.cpp +++ b/test/src/utility.cpp @@ -7,7 +7,7 @@ const std::string test_server = "httpbin.org"; std::string random_string(size_t max_length) { static std::mt19937_64 engine{(std::random_device())()}; std::uniform_int_distribution sdist(0, max_length); - std::uniform_int_distribution cdist(0, 127); + std::uniform_int_distribution cdist(0, 127); std::string out; std::generate_n(std::back_inserter(out), sdist(engine), diff --git a/test/src/utility.hpp b/test/src/utility.hpp index c04b9ce..b72bfd2 100644 --- a/test/src/utility.hpp +++ b/test/src/utility.hpp @@ -6,4 +6,4 @@ std::string random_string(size_t max_length); extern const std::string test_server; -#endif \ No newline at end of file +#endif From 6b6d16f2b450f925d50d79839c3c7b7a32163713 Mon Sep 17 00:00:00 2001 From: wtlgo Date: Tue, 10 Jan 2023 19:44:03 +0300 Subject: [PATCH 04/46] Add missing const qualifiers --- test/src/RequestTestsGet.cpp | 25 ++++++++------- test/src/RequestTestsPost.cpp | 32 +++++++++++--------- test/src/{PrimaryTest.cpp => SanityTest.cpp} | 2 +- test/src/utility.cpp | 4 +-- 4 files changed, 34 insertions(+), 29 deletions(-) rename test/src/{PrimaryTest.cpp => SanityTest.cpp} (81%) diff --git a/test/src/RequestTestsGet.cpp b/test/src/RequestTestsGet.cpp index f340294..7dbbc25 100644 --- a/test/src/RequestTestsGet.cpp +++ b/test/src/RequestTestsGet.cpp @@ -10,8 +10,9 @@ TEST(Request, Get_NoSSL_Static) { using json = nlohmann::json; using string = std::string; - string response = + const string response = network.request("http://" + test_server + "/get", {{"hello", "hello"}}); + ASSERT_NO_THROW({ auto resp = json::parse(response); ASSERT_EQ(resp["args"]["hello"], "hello"); @@ -23,8 +24,8 @@ TEST(Request, Get_SSL_Static) { using json = nlohmann::json; using string = std::string; - string response = network.request("https://" + test_server + "/get", - {{"hello", "hello"}}); + const string response = network.request("https://" + test_server + "/get", + {{"hello", "hello"}}); ASSERT_NO_THROW({ auto resp = json::parse(response); ASSERT_EQ(resp["args"]["hello"], "hello"); @@ -40,9 +41,10 @@ TEST(Request, Get_NoSSL_Random) { const string arg = random_string(500); const string val = random_string(1000); - string response = + const string response = network.request("http://" + test_server + "/get", {{arg, val}}); - auto resp = json::parse(response); + + const auto resp = json::parse(response); ASSERT_EQ(resp["args"][arg], val); }); @@ -57,9 +59,9 @@ TEST(Request, Get_SSL_Random) { const string arg = random_string(500); const string val = random_string(500); - string response = + const string response = network.request("https://" + test_server + "/get", {{arg, val}}); - auto resp = json::parse(response); + const auto resp = json::parse(response); ASSERT_EQ(resp["args"][arg], val); }); @@ -77,9 +79,9 @@ TEST(Request, Get_NoSSL_Random_MultipleArgs) { } ASSERT_NO_THROW({ - string response = + const string response = network.request("http://" + test_server + "/get", args); - auto resp = json::parse(response); + const auto resp = json::parse(response); for (const auto& arg : args) { ASSERT_EQ(resp["args"][arg.first], arg.second); @@ -99,9 +101,10 @@ TEST(Request, Get_SSL_Random_MultipleArgs) { } ASSERT_NO_THROW({ - string response = + const string response = network.request("https://" + test_server + "/get", args); - auto resp = json::parse(response); + + const auto resp = json::parse(response); for (const auto& arg : args) { ASSERT_EQ(resp["args"][arg.first], arg.second); diff --git a/test/src/RequestTestsPost.cpp b/test/src/RequestTestsPost.cpp index ce0caaa..a51ec93 100644 --- a/test/src/RequestTestsPost.cpp +++ b/test/src/RequestTestsPost.cpp @@ -10,8 +10,8 @@ TEST(Request, Post_NoSSL_Static) { using json = nlohmann::json; using string = std::string; - string response = network.request("http://" + test_server + "/post", - {{"hello", "hello"}}, true); + const string response = network.request("http://" + test_server + "/post", + {{"hello", "hello"}}, true); ASSERT_NO_THROW({ auto resp = json::parse(response); ASSERT_EQ(resp["form"]["hello"], "hello"); @@ -23,10 +23,10 @@ TEST(Request, Post_SSL_Static) { using json = nlohmann::json; using string = std::string; - string response = network.request("https://" + test_server + "/post", - {{"hello", "hello"}}, true); + const string response = network.request("https://" + test_server + "/post", + {{"hello", "hello"}}, true); ASSERT_NO_THROW({ - auto resp = json::parse(response); + const auto resp = json::parse(response); ASSERT_EQ(resp["form"]["hello"], "hello"); }); } @@ -40,9 +40,9 @@ TEST(Request, Post_NoSSL_Random) { const string arg = random_string(1000); const string val = random_string(1000); - string response = network.request("http://" + test_server + "/post", - {{arg, val}}, true); - auto resp = json::parse(response); + const string response = network.request( + "http://" + test_server + "/post", {{arg, val}}, true); + const auto resp = json::parse(response); ASSERT_EQ(resp["form"][arg], val); }); @@ -57,9 +57,10 @@ TEST(Request, Post_SSL_Random) { const string arg = random_string(1000); const string val = random_string(1000); - string response = network.request("https://" + test_server + "/post", - {{arg, val}}, true); - auto resp = json::parse(response); + const string response = network.request( + "https://" + test_server + "/post", {{arg, val}}, true); + + const auto resp = json::parse(response); ASSERT_EQ(resp["form"][arg], val); }); @@ -77,9 +78,9 @@ TEST(Request, Post_NoSSL_Random_MultipleArgs) { } ASSERT_NO_THROW({ - string response = + const string response = network.request("http://" + test_server + "/post", args, true); - auto resp = json::parse(response); + const auto resp = json::parse(response); for (const auto& arg : args) { ASSERT_EQ(resp["form"][arg.first], arg.second); @@ -98,10 +99,11 @@ TEST(Request, Post_SSL_Random_MultipleArgs) { args[random_string(1000)] = random_string(1000); } - string response = + const string response = network.request("https://" + test_server + "/post", args, true); + ASSERT_NO_THROW({ - auto resp = json::parse(response); + const auto resp = json::parse(response); for (const auto& arg : args) { ASSERT_EQ(resp["form"][arg.first], arg.second); diff --git a/test/src/PrimaryTest.cpp b/test/src/SanityTest.cpp similarity index 81% rename from test/src/PrimaryTest.cpp rename to test/src/SanityTest.cpp index 80671dd..b87d1be 100644 --- a/test/src/PrimaryTest.cpp +++ b/test/src/SanityTest.cpp @@ -1,7 +1,7 @@ #include #include -TEST(Primary, DidInit) { +TEST(SanityCheck, DidInit) { using namespace wtlgo; ASSERT_EQ(&network, &Network::instance()); } diff --git a/test/src/utility.cpp b/test/src/utility.cpp index ec2bcb3..f10d8e6 100644 --- a/test/src/utility.cpp +++ b/test/src/utility.cpp @@ -4,8 +4,8 @@ const std::string test_server = "httpbin.org"; -std::string random_string(size_t max_length) { - static std::mt19937_64 engine{(std::random_device())()}; +std::string random_string(const size_t max_length) { + static std::mt19937_64 engine{(std::random_device{})()}; std::uniform_int_distribution sdist(0, max_length); std::uniform_int_distribution cdist(0, 127); From 7c49425083df9b5a117435bb2240ca1f6062cc2f Mon Sep 17 00:00:00 2001 From: wtlgo Date: Wed, 11 Jan 2023 11:25:05 +0300 Subject: [PATCH 05/46] Move old implementation to wtlgo::old namespace --- include/wtlgo/Network.hpp | 3 ++- src/Network.cpp | 8 +++++--- test/src/RequestTestsGet.cpp | 12 ++++++------ test/src/RequestTestsPost.cpp | 12 ++++++------ test/src/SanityTest.cpp | 2 +- 5 files changed, 20 insertions(+), 17 deletions(-) diff --git a/include/wtlgo/Network.hpp b/include/wtlgo/Network.hpp index 4db8948..5e74378 100644 --- a/include/wtlgo/Network.hpp +++ b/include/wtlgo/Network.hpp @@ -7,6 +7,7 @@ #include namespace wtlgo { +namespace old { class Network { public: @@ -45,5 +46,5 @@ class Network { extern Network& network; } - +} #endif /* Network_hpp */ diff --git a/src/Network.cpp b/src/Network.cpp index cd1a3de..f57edd5 100644 --- a/src/Network.cpp +++ b/src/Network.cpp @@ -10,9 +10,9 @@ #include -wtlgo::Network& wtlgo::network = wtlgo::Network::instance(); +wtlgo::old::Network& wtlgo::old::network = wtlgo::old::Network::instance(); -using namespace wtlgo; +using namespace wtlgo::old; Network::Network() { curl_global_init(CURL_GLOBAL_ALL); } @@ -100,8 +100,10 @@ bool Network::download(const std::string& url, curl_easy_setopt(curl.get(), CURLOPT_WRITEDATA, file.get()); curl_easy_setopt(curl.get(), CURLOPT_WRITEFUNCTION, file_writer); curl_easy_setopt(curl.get(), CURLOPT_FOLLOWLOCATION, 1); - if (proxy.size() > 0) + + if (proxy.size() > 0) { curl_easy_setopt(curl.get(), CURLOPT_PROXY, proxy.c_str()); + } res = curl_easy_perform(curl.get()); diff --git a/test/src/RequestTestsGet.cpp b/test/src/RequestTestsGet.cpp index 7dbbc25..9cd77cb 100644 --- a/test/src/RequestTestsGet.cpp +++ b/test/src/RequestTestsGet.cpp @@ -6,7 +6,7 @@ #include "utility.hpp" TEST(Request, Get_NoSSL_Static) { - using namespace wtlgo; + using namespace wtlgo::old; using json = nlohmann::json; using string = std::string; @@ -20,7 +20,7 @@ TEST(Request, Get_NoSSL_Static) { } TEST(Request, Get_SSL_Static) { - using namespace wtlgo; + using namespace wtlgo::old; using json = nlohmann::json; using string = std::string; @@ -33,7 +33,7 @@ TEST(Request, Get_SSL_Static) { } TEST(Request, Get_NoSSL_Random) { - using namespace wtlgo; + using namespace wtlgo::old; using json = nlohmann::json; using string = std::string; @@ -51,7 +51,7 @@ TEST(Request, Get_NoSSL_Random) { } TEST(Request, Get_SSL_Random) { - using namespace wtlgo; + using namespace wtlgo::old; using json = nlohmann::json; using string = std::string; @@ -68,7 +68,7 @@ TEST(Request, Get_SSL_Random) { } TEST(Request, Get_NoSSL_Random_MultipleArgs) { - using namespace wtlgo; + using namespace wtlgo::old; using json = nlohmann::json; using string = std::string; using map = std::map; @@ -90,7 +90,7 @@ TEST(Request, Get_NoSSL_Random_MultipleArgs) { } TEST(Request, Get_SSL_Random_MultipleArgs) { - using namespace wtlgo; + using namespace wtlgo::old; using json = nlohmann::json; using string = std::string; using map = std::map; diff --git a/test/src/RequestTestsPost.cpp b/test/src/RequestTestsPost.cpp index a51ec93..d71bb7e 100644 --- a/test/src/RequestTestsPost.cpp +++ b/test/src/RequestTestsPost.cpp @@ -6,7 +6,7 @@ #include "utility.hpp" TEST(Request, Post_NoSSL_Static) { - using namespace wtlgo; + using namespace wtlgo::old; using json = nlohmann::json; using string = std::string; @@ -19,7 +19,7 @@ TEST(Request, Post_NoSSL_Static) { } TEST(Request, Post_SSL_Static) { - using namespace wtlgo; + using namespace wtlgo::old; using json = nlohmann::json; using string = std::string; @@ -32,7 +32,7 @@ TEST(Request, Post_SSL_Static) { } TEST(Request, Post_NoSSL_Random) { - using namespace wtlgo; + using namespace wtlgo::old; using json = nlohmann::json; using string = std::string; @@ -49,7 +49,7 @@ TEST(Request, Post_NoSSL_Random) { } TEST(Request, Post_SSL_Random) { - using namespace wtlgo; + using namespace wtlgo::old; using json = nlohmann::json; using string = std::string; @@ -67,7 +67,7 @@ TEST(Request, Post_SSL_Random) { } TEST(Request, Post_NoSSL_Random_MultipleArgs) { - using namespace wtlgo; + using namespace wtlgo::old; using json = nlohmann::json; using string = std::string; using map = std::map; @@ -89,7 +89,7 @@ TEST(Request, Post_NoSSL_Random_MultipleArgs) { } TEST(Request, Post_SSL_Random_MultipleArgs) { - using namespace wtlgo; + using namespace wtlgo::old; using json = nlohmann::json; using string = std::string; using map = std::map; diff --git a/test/src/SanityTest.cpp b/test/src/SanityTest.cpp index b87d1be..705fa87 100644 --- a/test/src/SanityTest.cpp +++ b/test/src/SanityTest.cpp @@ -2,6 +2,6 @@ #include TEST(SanityCheck, DidInit) { - using namespace wtlgo; + using namespace wtlgo::old; ASSERT_EQ(&network, &Network::instance()); } From 0a55dfc5afc84338ce3ba1ca85f195222b64b8d0 Mon Sep 17 00:00:00 2001 From: wtlgo Date: Wed, 11 Jan 2023 11:30:28 +0300 Subject: [PATCH 06/46] Rename old implementation --- CMakeLists.txt | 13 +++++++++---- include/wtlgo/{Network.hpp => NetworkOld.hpp} | 0 src/{Network.cpp => NetworkOld.cpp} | 2 +- test/src/RequestTestsGet.cpp | 2 +- test/src/RequestTestsPost.cpp | 2 +- test/src/SanityTest.cpp | 2 +- 6 files changed, 13 insertions(+), 8 deletions(-) rename include/wtlgo/{Network.hpp => NetworkOld.hpp} (100%) rename src/{Network.cpp => NetworkOld.cpp} (99%) diff --git a/CMakeLists.txt b/CMakeLists.txt index e624536..569b285 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,16 +10,21 @@ project( find_package(CURL REQUIRED) -add_library(Network src/Network.cpp include/wtlgo/Network.hpp) +set(PUBLIC_HEADERS + "include/wtlgo/NetworkOld.hpp" +) + +set(SOURCES + "src/NetworkOld.cpp" +) + +add_library(Network ${SOURCES}) target_compile_features(Network PUBLIC cxx_std_17) target_link_libraries(Network PUBLIC CURL::libcurl) target_include_directories(Network PUBLIC include/) target_include_directories(Network PRIVATE include/wtlgo/) -set(PUBLIC_HEADERS - "include/wtlgo/Network.hpp" -) set_target_properties(Network PROPERTIES PUBLIC_HEADER "${PUBLIC_HEADERS}" diff --git a/include/wtlgo/Network.hpp b/include/wtlgo/NetworkOld.hpp similarity index 100% rename from include/wtlgo/Network.hpp rename to include/wtlgo/NetworkOld.hpp diff --git a/src/Network.cpp b/src/NetworkOld.cpp similarity index 99% rename from src/Network.cpp rename to src/NetworkOld.cpp index f57edd5..3042814 100644 --- a/src/Network.cpp +++ b/src/NetworkOld.cpp @@ -8,7 +8,7 @@ #include -#include +#include wtlgo::old::Network& wtlgo::old::network = wtlgo::old::Network::instance(); diff --git a/test/src/RequestTestsGet.cpp b/test/src/RequestTestsGet.cpp index 9cd77cb..d9b9ccf 100644 --- a/test/src/RequestTestsGet.cpp +++ b/test/src/RequestTestsGet.cpp @@ -1,4 +1,4 @@ -#include +#include #include #include #include diff --git a/test/src/RequestTestsPost.cpp b/test/src/RequestTestsPost.cpp index d71bb7e..a9a5955 100644 --- a/test/src/RequestTestsPost.cpp +++ b/test/src/RequestTestsPost.cpp @@ -1,4 +1,4 @@ -#include +#include #include #include #include diff --git a/test/src/SanityTest.cpp b/test/src/SanityTest.cpp index 705fa87..30e5516 100644 --- a/test/src/SanityTest.cpp +++ b/test/src/SanityTest.cpp @@ -1,4 +1,4 @@ -#include +#include #include TEST(SanityCheck, DidInit) { From fddad414b569cf1948048c73af055893ed1976c8 Mon Sep 17 00:00:00 2001 From: wtlgo Date: Wed, 11 Jan 2023 14:23:05 +0300 Subject: [PATCH 07/46] Add Config class --- CMakeLists.txt | 5 +- include/wtlgo/network/Config.hpp | 53 +++++++++++++++++ include/wtlgo/network/HttpMethod.hpp | 10 ++++ src/Config.cpp | 82 +++++++++++++++++++++++++ src/NetworkOld.cpp | 2 +- test/src/Config.cpp | 89 ++++++++++++++++++++++++++++ test/src/utility.cpp | 6 +- test/src/utility.hpp | 2 +- 8 files changed, 243 insertions(+), 6 deletions(-) create mode 100644 include/wtlgo/network/Config.hpp create mode 100644 include/wtlgo/network/HttpMethod.hpp create mode 100644 src/Config.cpp create mode 100644 test/src/Config.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 569b285..a6e41a2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,10 +12,13 @@ find_package(CURL REQUIRED) set(PUBLIC_HEADERS "include/wtlgo/NetworkOld.hpp" + "include/wtlgo/network/Config.hpp" + "include/wtlgo/network/HttpMethod.hpp" ) set(SOURCES "src/NetworkOld.cpp" + "src/Config.cpp" ) add_library(Network ${SOURCES}) @@ -23,7 +26,7 @@ target_compile_features(Network PUBLIC cxx_std_17) target_link_libraries(Network PUBLIC CURL::libcurl) target_include_directories(Network PUBLIC include/) -target_include_directories(Network PRIVATE include/wtlgo/) +target_include_directories(Network PRIVATE include/) set_target_properties(Network PROPERTIES diff --git a/include/wtlgo/network/Config.hpp b/include/wtlgo/network/Config.hpp new file mode 100644 index 0000000..eae09fe --- /dev/null +++ b/include/wtlgo/network/Config.hpp @@ -0,0 +1,53 @@ +#ifndef __WTLGO__NETWORK__CONFIG_HPP__ +#define __WTLGO__NETWORK__CONFIG_HPP__ + +#include +#include +#include +#include +#include + +#include + +namespace wtlgo { +namespace network { + +class Config { +public: + using url_t = std::string; + + using header_field_name_t = std::string; + using header_value_t = std::string; + using header_value_opt_ref_t = + std::optional>; + using headers_t = std::unordered_map; + + Config(); + Config(const Config&); + + virtual ~Config(); + + const url_t& url() const; + Config& url(const url_t& new_url); + + HttpMethod method() const; + Config& method(HttpMethod new_method); + + const url_t& base_url() const; + Config& base_url(const url_t& new_base_url); + + const headers_t& headers() const; + Config& headers(const headers_t& new_headers); + + const header_value_opt_ref_t header(const header_field_name_t& field) const; + Config& header(const header_field_name_t& field_name, + const header_value_t& value); + +private: + struct ConfigImpl; + std::unique_ptr impl; +}; +} +} + +#endif diff --git a/include/wtlgo/network/HttpMethod.hpp b/include/wtlgo/network/HttpMethod.hpp new file mode 100644 index 0000000..c293ef5 --- /dev/null +++ b/include/wtlgo/network/HttpMethod.hpp @@ -0,0 +1,10 @@ +#ifndef __WTLGO__NETWORK__HTTP_METHOD_HPP__ +#define __WTLGO__NETWORK__HTTP_METHOD_HPP__ + +namespace wtlgo { +namespace network { +enum class HttpMethod { GET, POST, PUT, DELETE }; +} +} + +#endif diff --git a/src/Config.cpp b/src/Config.cpp new file mode 100644 index 0000000..def54db --- /dev/null +++ b/src/Config.cpp @@ -0,0 +1,82 @@ +#include +#include + +#include +#include + +using namespace wtlgo::network; + +struct Config::ConfigImpl { + url_t _url; + const url_t& url() const { return _url; } + void url(const url_t& new_url) { _url = new_url; } + + HttpMethod _method = HttpMethod::GET; + HttpMethod method() const { return _method; } + void method(const HttpMethod new_method) { _method = new_method; } + + url_t _base_url; + const url_t& base_url() const { return _base_url; } + void base_url(const url_t& new_base_url) { _base_url = new_base_url; } + + headers_t _headers; + const headers_t& headers() const { return _headers; } + void headers(const headers_t& new_headers) { _headers = new_headers; } + + const header_value_opt_ref_t header( + const header_field_name_t& field_name) const { + const auto field = _headers.find(field_name); + + if (field == _headers.cend()) { + return std::nullopt; + } + + return std::cref(field->second); + } + + void header(const header_field_name_t& field_name, + const header_value_t& value) { + _headers[field_name] = value; + } +}; + +Config::Config() : impl{std::make_unique()} {} +Config::Config(const Config& conf) + : impl{std::make_unique(*conf.impl)} {} + +Config::~Config() = default; + +const Config::url_t& Config::url() const { return impl->url(); } +Config& Config::url(const Config::url_t& new_url) { + impl->url(new_url); + return *this; +} + +HttpMethod Config::method() const { return impl->method(); } +Config& Config::method(const HttpMethod new_method) { + impl->method(new_method); + return *this; +} + +const Config::url_t& Config::base_url() const { return impl->base_url(); } +Config& Config::base_url(const Config::url_t& new_base_url) { + impl->base_url(new_base_url); + return *this; +} + +const Config::headers_t& Config::headers() const { return impl->headers(); } +Config& Config::headers(const Config::headers_t& new_headers) { + impl->headers(new_headers); + return *this; +} + +const Config::header_value_opt_ref_t Config::header( + const Config::header_field_name_t& field) const { + return impl->header(field); +} + +Config& Config::header(const Config::header_field_name_t& field_name, + const Config::header_value_t& value) { + impl->header(field_name, value); + return *this; +} diff --git a/src/NetworkOld.cpp b/src/NetworkOld.cpp index 3042814..c603b9e 100644 --- a/src/NetworkOld.cpp +++ b/src/NetworkOld.cpp @@ -8,7 +8,7 @@ #include -#include +#include wtlgo::old::Network& wtlgo::old::network = wtlgo::old::Network::instance(); diff --git a/test/src/Config.cpp b/test/src/Config.cpp new file mode 100644 index 0000000..903ddfb --- /dev/null +++ b/test/src/Config.cpp @@ -0,0 +1,89 @@ +#include +#include +#include +#include "utility.hpp" + +TEST(Config, Url) { + using namespace wtlgo::network; + + Config config; + + ASSERT_EQ(config.url(), ""); + + const std::string test_url = random_string(42); + ASSERT_EQ(&config.url(test_url), &config); + + ASSERT_EQ(config.url(), test_url); +} + +TEST(Config, Method) { + using namespace wtlgo::network; + + Config config; + + ASSERT_EQ(config.method(), HttpMethod::GET); + + for (const HttpMethod test_method : {HttpMethod::POST, HttpMethod::PUT, + HttpMethod::DELETE, HttpMethod::GET}) { + ASSERT_EQ(&config.method(test_method), &config); + ASSERT_EQ(config.method(), test_method); + } +} + +TEST(Config, BaseUrl) { + using namespace wtlgo::network; + + Config config; + + ASSERT_EQ(config.base_url(), ""); + + const std::string test_base_url = random_string(42); + ASSERT_EQ(&config.base_url(test_base_url), &config); + + ASSERT_EQ(config.base_url(), test_base_url); +} + +TEST(Config, HeadersAll) { + using namespace wtlgo::network; + + Config config; + + ASSERT_EQ(config.headers().size(), 0); + + Config::headers_t test_headers; + for (std::size_t i = 0; i < 10; ++i) { + test_headers[random_string(50)] = random_string(50); + } + + ASSERT_EQ(&config.headers(test_headers), &config); + ASSERT_EQ(config.headers().size(), test_headers.size()); + + for (const auto & [ test_field_name, test_value ] : test_headers) { + const auto& headers = config.headers(); + const auto field = headers.find(test_field_name); + ASSERT_NE(field, headers.cend()); + + ASSERT_EQ(field->first, test_field_name); + ASSERT_EQ(field->second, test_value); + } +} + +TEST(Config, HeadersSingle) { + using namespace wtlgo::network; + + Config config; + + Config::header_field_name_t none_name; + for (std::size_t i = 0; i < 10; ++i) { + const Config::header_field_name_t test_field_name = random_string(10, true); + const Config::header_value_t test_value = random_string(50); + + none_name.push_back(1 + (127 - 1 + test_field_name.at(i)) % (127 - 1)); + + ASSERT_EQ(&config.header(test_field_name, test_value), &config); + + const auto real_value = config.header(test_field_name); + ASSERT_EQ(real_value.has_value(), true); + ASSERT_EQ(real_value.value().get(), test_value); + } +} \ No newline at end of file diff --git a/test/src/utility.cpp b/test/src/utility.cpp index f10d8e6..92f8435 100644 --- a/test/src/utility.cpp +++ b/test/src/utility.cpp @@ -4,13 +4,13 @@ const std::string test_server = "httpbin.org"; -std::string random_string(const size_t max_length) { +std::string random_string(const std::size_t max_length, const bool exact) { static std::mt19937_64 engine{(std::random_device{})()}; - std::uniform_int_distribution sdist(0, max_length); + std::uniform_int_distribution sdist(0, max_length); std::uniform_int_distribution cdist(0, 127); std::string out; - std::generate_n(std::back_inserter(out), sdist(engine), + std::generate_n(std::back_inserter(out), exact ? max_length : sdist(engine), [&cdist] { return cdist(engine); }); return out; } diff --git a/test/src/utility.hpp b/test/src/utility.hpp index b72bfd2..a3e544f 100644 --- a/test/src/utility.hpp +++ b/test/src/utility.hpp @@ -3,7 +3,7 @@ #include -std::string random_string(size_t max_length); +std::string random_string(size_t max_length, bool exact = false); extern const std::string test_server; #endif From b8dd724c28fbc1651e3eb0bf66eed91f472d6444 Mon Sep 17 00:00:00 2001 From: wtlgo Date: Wed, 11 Jan 2023 16:00:15 +0300 Subject: [PATCH 08/46] Rename old tests --- .../{RequestTestsGet.cpp => OldRequestTestsGet.cpp} | 12 ++++++------ ...{RequestTestsPost.cpp => OldRequestTestsPost.cpp} | 12 ++++++------ test/src/{SanityTest.cpp => OldSanityTest.cpp} | 2 +- 3 files changed, 13 insertions(+), 13 deletions(-) rename test/src/{RequestTestsGet.cpp => OldRequestTestsGet.cpp} (92%) rename test/src/{RequestTestsPost.cpp => OldRequestTestsPost.cpp} (92%) rename test/src/{SanityTest.cpp => OldSanityTest.cpp} (81%) diff --git a/test/src/RequestTestsGet.cpp b/test/src/OldRequestTestsGet.cpp similarity index 92% rename from test/src/RequestTestsGet.cpp rename to test/src/OldRequestTestsGet.cpp index d9b9ccf..02fc154 100644 --- a/test/src/RequestTestsGet.cpp +++ b/test/src/OldRequestTestsGet.cpp @@ -5,7 +5,7 @@ #include "utility.hpp" -TEST(Request, Get_NoSSL_Static) { +TEST(OldRequest, Get_NoSSL_Static) { using namespace wtlgo::old; using json = nlohmann::json; using string = std::string; @@ -19,7 +19,7 @@ TEST(Request, Get_NoSSL_Static) { }); } -TEST(Request, Get_SSL_Static) { +TEST(OldRequest, Get_SSL_Static) { using namespace wtlgo::old; using json = nlohmann::json; using string = std::string; @@ -32,7 +32,7 @@ TEST(Request, Get_SSL_Static) { }); } -TEST(Request, Get_NoSSL_Random) { +TEST(OldRequest, Get_NoSSL_Random) { using namespace wtlgo::old; using json = nlohmann::json; using string = std::string; @@ -50,7 +50,7 @@ TEST(Request, Get_NoSSL_Random) { }); } -TEST(Request, Get_SSL_Random) { +TEST(OldRequest, Get_SSL_Random) { using namespace wtlgo::old; using json = nlohmann::json; using string = std::string; @@ -67,7 +67,7 @@ TEST(Request, Get_SSL_Random) { }); } -TEST(Request, Get_NoSSL_Random_MultipleArgs) { +TEST(OldRequest, Get_NoSSL_Random_MultipleArgs) { using namespace wtlgo::old; using json = nlohmann::json; using string = std::string; @@ -89,7 +89,7 @@ TEST(Request, Get_NoSSL_Random_MultipleArgs) { }); } -TEST(Request, Get_SSL_Random_MultipleArgs) { +TEST(OldRequest, Get_SSL_Random_MultipleArgs) { using namespace wtlgo::old; using json = nlohmann::json; using string = std::string; diff --git a/test/src/RequestTestsPost.cpp b/test/src/OldRequestTestsPost.cpp similarity index 92% rename from test/src/RequestTestsPost.cpp rename to test/src/OldRequestTestsPost.cpp index a9a5955..866364e 100644 --- a/test/src/RequestTestsPost.cpp +++ b/test/src/OldRequestTestsPost.cpp @@ -5,7 +5,7 @@ #include "utility.hpp" -TEST(Request, Post_NoSSL_Static) { +TEST(OldRequest, Post_NoSSL_Static) { using namespace wtlgo::old; using json = nlohmann::json; using string = std::string; @@ -18,7 +18,7 @@ TEST(Request, Post_NoSSL_Static) { }); } -TEST(Request, Post_SSL_Static) { +TEST(OldRequest, Post_SSL_Static) { using namespace wtlgo::old; using json = nlohmann::json; using string = std::string; @@ -31,7 +31,7 @@ TEST(Request, Post_SSL_Static) { }); } -TEST(Request, Post_NoSSL_Random) { +TEST(OldRequest, Post_NoSSL_Random) { using namespace wtlgo::old; using json = nlohmann::json; using string = std::string; @@ -48,7 +48,7 @@ TEST(Request, Post_NoSSL_Random) { }); } -TEST(Request, Post_SSL_Random) { +TEST(OldRequest, Post_SSL_Random) { using namespace wtlgo::old; using json = nlohmann::json; using string = std::string; @@ -66,7 +66,7 @@ TEST(Request, Post_SSL_Random) { }); } -TEST(Request, Post_NoSSL_Random_MultipleArgs) { +TEST(OldRequest, Post_NoSSL_Random_MultipleArgs) { using namespace wtlgo::old; using json = nlohmann::json; using string = std::string; @@ -88,7 +88,7 @@ TEST(Request, Post_NoSSL_Random_MultipleArgs) { }); } -TEST(Request, Post_SSL_Random_MultipleArgs) { +TEST(OldRequest, Post_SSL_Random_MultipleArgs) { using namespace wtlgo::old; using json = nlohmann::json; using string = std::string; diff --git a/test/src/SanityTest.cpp b/test/src/OldSanityTest.cpp similarity index 81% rename from test/src/SanityTest.cpp rename to test/src/OldSanityTest.cpp index 30e5516..f8a5cd8 100644 --- a/test/src/SanityTest.cpp +++ b/test/src/OldSanityTest.cpp @@ -1,7 +1,7 @@ #include #include -TEST(SanityCheck, DidInit) { +TEST(OldSanityCheck, DidInit) { using namespace wtlgo::old; ASSERT_EQ(&network, &Network::instance()); } From 45f90fec3d5010256bbf8eca0bbffdfefd1cee95 Mon Sep 17 00:00:00 2001 From: wtlgo Date: Wed, 11 Jan 2023 19:17:19 +0300 Subject: [PATCH 09/46] Add CurlController class --- CMakeLists.txt | 2 ++ include/wtlgo/network/Config.hpp | 5 ++++ include/wtlgo/network/CurlController.hpp | 33 ++++++++++++++++++++++ src/CurlController.cpp | 36 ++++++++++++++++++++++++ src/NetworkOld.cpp | 2 -- test/src/CurlController.cpp | 15 ++++++++++ 6 files changed, 91 insertions(+), 2 deletions(-) create mode 100644 include/wtlgo/network/CurlController.hpp create mode 100644 src/CurlController.cpp create mode 100644 test/src/CurlController.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index a6e41a2..e70f602 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,11 +14,13 @@ set(PUBLIC_HEADERS "include/wtlgo/NetworkOld.hpp" "include/wtlgo/network/Config.hpp" "include/wtlgo/network/HttpMethod.hpp" + "include/wtlgo/network/CurlController.hpp" ) set(SOURCES "src/NetworkOld.cpp" "src/Config.cpp" + "src/CurlController.cpp" ) add_library(Network ${SOURCES}) diff --git a/include/wtlgo/network/Config.hpp b/include/wtlgo/network/Config.hpp index eae09fe..e6fb40b 100644 --- a/include/wtlgo/network/Config.hpp +++ b/include/wtlgo/network/Config.hpp @@ -6,6 +6,7 @@ #include #include #include +#include #include @@ -22,6 +23,10 @@ class Config { std::optional>; using headers_t = std::unordered_map; + using data_field_name_t = std::string; + using data_value_t = std::variant; + using data_t = std::unordered_map; + Config(); Config(const Config&); diff --git a/include/wtlgo/network/CurlController.hpp b/include/wtlgo/network/CurlController.hpp new file mode 100644 index 0000000..79c303a --- /dev/null +++ b/include/wtlgo/network/CurlController.hpp @@ -0,0 +1,33 @@ +#ifndef __WTLGO__NETWORK__CURL_CONTROLLER_HPP__ +#define __WTLGO__NETWORK__CURL_CONTROLLER_HPP__ + +#include + +#include + +namespace wtlgo { +namespace network { +class CurlController { +public: + using curl_handler_t = std::unique_ptr; + + CurlController(const CurlController&) = delete; + void operator=(const CurlController&) = delete; + + static CurlController& instance(); + + void global_init(); + + curl_handler_t get_handler(); + +private: + CurlController(); + ~CurlController(); + + struct CurlControllerImpl; + std::unique_ptr impl; +}; +} +} + +#endif diff --git a/src/CurlController.cpp b/src/CurlController.cpp new file mode 100644 index 0000000..0ca3603 --- /dev/null +++ b/src/CurlController.cpp @@ -0,0 +1,36 @@ +#include +#include + +#include + +#include + +using namespace wtlgo::network; + +struct CurlController::CurlControllerImpl { + std::atomic_bool did_init{false}; + void global_init() { + if (did_init.exchange(true)) return; + curl_global_init(CURL_GLOBAL_ALL); + } + + curl_handler_t get_handler(CurlController& controller) { + controller.global_init(); + return {curl_easy_init(), curl_easy_cleanup}; + } +}; + +CurlController& CurlController::instance() { + static CurlController instance; + return instance; +} + +void CurlController::global_init() { impl->global_init(); } + +CurlController::curl_handler_t CurlController::get_handler() { + return impl->get_handler(*this); +} + +CurlController::CurlController() + : impl{std::make_unique()} {} +CurlController::~CurlController() = default; diff --git a/src/NetworkOld.cpp b/src/NetworkOld.cpp index c603b9e..72626d7 100644 --- a/src/NetworkOld.cpp +++ b/src/NetworkOld.cpp @@ -55,8 +55,6 @@ std::string Network::request(std::string url, } curl_easy_setopt(curl.get(), CURLOPT_SSL_VERIFYPEER, 0L); - curl_easy_setopt(curl.get(), CURLOPT_HTTP_VERSION, - CURL_HTTP_VERSION_1_1); curl_easy_setopt(curl.get(), CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); curl_easy_setopt(curl.get(), CURLOPT_URL, url.c_str()); diff --git a/test/src/CurlController.cpp b/test/src/CurlController.cpp new file mode 100644 index 0000000..a1525f1 --- /dev/null +++ b/test/src/CurlController.cpp @@ -0,0 +1,15 @@ +#include +#include + +TEST(CurlController, IsSingleton) { + using namespace wtlgo::network; + + ASSERT_EQ(&CurlController::instance(), &CurlController::instance()); +} + +TEST(CurlController, ProducesCURLInstance) { + using namespace wtlgo::network; + + const auto test = CurlController::instance().get_handler(); + ASSERT_NE(test, nullptr); +} From b5c4a92afec0a4944e741e9e48bbfd9f95e41524 Mon Sep 17 00:00:00 2001 From: wtlgo Date: Wed, 11 Jan 2023 19:33:07 +0300 Subject: [PATCH 10/46] Add PATCH HTTP method --- include/wtlgo/network/HttpMethod.hpp | 2 +- test/src/Config.cpp | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/include/wtlgo/network/HttpMethod.hpp b/include/wtlgo/network/HttpMethod.hpp index c293ef5..99bd9b3 100644 --- a/include/wtlgo/network/HttpMethod.hpp +++ b/include/wtlgo/network/HttpMethod.hpp @@ -3,7 +3,7 @@ namespace wtlgo { namespace network { -enum class HttpMethod { GET, POST, PUT, DELETE }; +enum class HttpMethod { GET, POST, PUT, PATCH, DELETE }; } } diff --git a/test/src/Config.cpp b/test/src/Config.cpp index 903ddfb..1aed8e1 100644 --- a/test/src/Config.cpp +++ b/test/src/Config.cpp @@ -23,8 +23,9 @@ TEST(Config, Method) { ASSERT_EQ(config.method(), HttpMethod::GET); - for (const HttpMethod test_method : {HttpMethod::POST, HttpMethod::PUT, - HttpMethod::DELETE, HttpMethod::GET}) { + for (const HttpMethod test_method : + {HttpMethod::POST, HttpMethod::PUT, HttpMethod::PATCH, + HttpMethod::DELETE, HttpMethod::GET}) { ASSERT_EQ(&config.method(test_method), &config); ASSERT_EQ(config.method(), test_method); } @@ -75,7 +76,8 @@ TEST(Config, HeadersSingle) { Config::header_field_name_t none_name; for (std::size_t i = 0; i < 10; ++i) { - const Config::header_field_name_t test_field_name = random_string(10, true); + const Config::header_field_name_t test_field_name = + random_string(10, true); const Config::header_value_t test_value = random_string(50); none_name.push_back(1 + (127 - 1 + test_field_name.at(i)) % (127 - 1)); From 02ffe64b926d4289646b5326e1363c2727357769 Mon Sep 17 00:00:00 2001 From: wtlgo Date: Wed, 11 Jan 2023 21:00:20 +0300 Subject: [PATCH 11/46] Add Client class base --- CMakeLists.txt | 2 ++ include/wtlgo/network/Client.hpp | 26 ++++++++++++++++++++++++++ src/Client.cpp | 24 ++++++++++++++++++++++++ test/src/Client.cpp | 7 +++++++ 4 files changed, 59 insertions(+) create mode 100644 include/wtlgo/network/Client.hpp create mode 100644 src/Client.cpp create mode 100644 test/src/Client.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index e70f602..3ae48f1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,12 +15,14 @@ set(PUBLIC_HEADERS "include/wtlgo/network/Config.hpp" "include/wtlgo/network/HttpMethod.hpp" "include/wtlgo/network/CurlController.hpp" + "include/wtlgo/network/Client.hpp" ) set(SOURCES "src/NetworkOld.cpp" "src/Config.cpp" "src/CurlController.cpp" + "src/Client.cpp" ) add_library(Network ${SOURCES}) diff --git a/include/wtlgo/network/Client.hpp b/include/wtlgo/network/Client.hpp new file mode 100644 index 0000000..cd83daf --- /dev/null +++ b/include/wtlgo/network/Client.hpp @@ -0,0 +1,26 @@ +#ifndef __WTLGO__NETWORK__CLIENT_HPP__ +#define __WTLGO__NETWORK__CLIENT_HPP__ + +#include + +#include + +namespace wtlgo { +namespace network { +class Client { +public: + Client(); + Client(const Config& config); + virtual ~Client(); + + Config& config(); + const Config& config() const; + +private: + struct ClientImpl; + std::unique_ptr impl; +}; +} +} + +#endif diff --git a/src/Client.cpp b/src/Client.cpp new file mode 100644 index 0000000..19cbd07 --- /dev/null +++ b/src/Client.cpp @@ -0,0 +1,24 @@ +#include + +#include +#include + +using namespace wtlgo::network; + +struct Client::ClientImpl { + Config _config; + + ClientImpl() = default; + ClientImpl(const Config& config) : _config{config} {} + + Config& config() { return _config; } + const Config& config() const { return _config; } +}; + +Client::Client() : impl{std::make_unique()} {} +Client::Client(const Config& config) + : impl{std::make_unique(config)} {} +Client::~Client() = default; + +Config& Client::config() { return impl->config(); } +const Config& Client::config() const { return impl->config(); } diff --git a/test/src/Client.cpp b/test/src/Client.cpp new file mode 100644 index 0000000..e6da317 --- /dev/null +++ b/test/src/Client.cpp @@ -0,0 +1,7 @@ +#include +#include + +TEST(Client, SomeTest) { + using namespace wtlgo::network; + Client client; +} From cae2f27d53526c9f6bf4b955895393b437ce1473 Mon Sep 17 00:00:00 2001 From: wtlgo Date: Thu, 12 Jan 2023 11:24:28 +0300 Subject: [PATCH 12/46] Add data to config --- include/wtlgo/network/Config.hpp | 9 ++++++ src/Config.cpp | 38 +++++++++++++++++++++++ test/src/Config.cpp | 52 +++++++++++++++++++++++++++++++- 3 files changed, 98 insertions(+), 1 deletion(-) diff --git a/include/wtlgo/network/Config.hpp b/include/wtlgo/network/Config.hpp index e6fb40b..c075811 100644 --- a/include/wtlgo/network/Config.hpp +++ b/include/wtlgo/network/Config.hpp @@ -25,6 +25,8 @@ class Config { using data_field_name_t = std::string; using data_value_t = std::variant; + using data_value_opt_ref_t = + std::optional>; using data_t = std::unordered_map; Config(); @@ -48,6 +50,13 @@ class Config { Config& header(const header_field_name_t& field_name, const header_value_t& value); + const data_t& data() const; + Config& data(const data_t& new_data); + + const data_value_opt_ref_t data_field(const data_field_name_t& field) const; + Config& data_field(const data_field_name_t& field, + const data_value_t& value); + private: struct ConfigImpl; std::unique_ptr impl; diff --git a/src/Config.cpp b/src/Config.cpp index def54db..5bbe593 100644 --- a/src/Config.cpp +++ b/src/Config.cpp @@ -38,6 +38,26 @@ struct Config::ConfigImpl { const header_value_t& value) { _headers[field_name] = value; } + + data_t _data; + + const data_t& data() const { return _data; } + void data(const data_t& new_data) { _data = new_data; } + + const data_value_opt_ref_t data_field( + const data_field_name_t& field_name) const { + const auto field = _data.find(field_name); + + if (field == _data.cend()) { + return std::nullopt; + } + + return std::cref(field->second); + } + + void data_field(const data_field_name_t& field, const data_value_t& value) { + _data[field] = value; + } }; Config::Config() : impl{std::make_unique()} {} @@ -80,3 +100,21 @@ Config& Config::header(const Config::header_field_name_t& field_name, impl->header(field_name, value); return *this; } + +const Config::data_t& Config::data() const { return impl->data(); } + +Config& Config::data(const Config::data_t& new_data) { + impl->data(new_data); + return *this; +} + +const Config::data_value_opt_ref_t Config::data_field( + const Config::data_field_name_t& field) const { + return impl->data_field(field); +} + +Config& Config::data_field(const Config::data_field_name_t& field, + const Config::data_value_t& value) { + impl->data_field(field, value); + return *this; +} diff --git a/test/src/Config.cpp b/test/src/Config.cpp index 1aed8e1..d5e42d8 100644 --- a/test/src/Config.cpp +++ b/test/src/Config.cpp @@ -88,4 +88,54 @@ TEST(Config, HeadersSingle) { ASSERT_EQ(real_value.has_value(), true); ASSERT_EQ(real_value.value().get(), test_value); } -} \ No newline at end of file + + ASSERT_EQ(config.header(none_name).has_value(), false); +} + +TEST(Config, DataAll) { + using namespace wtlgo::network; + + Config config; + + ASSERT_EQ(config.data().size(), 0); + + Config::data_t test_data; + for (std::size_t i = 0; i < 10; ++i) { + test_data[random_string(50)] = random_string(50); + } + + ASSERT_EQ(&config.data(test_data), &config); + ASSERT_EQ(config.data().size(), test_data.size()); + + for (const auto & [ test_field_name, test_value ] : test_data) { + const auto& data = config.data(); + const auto field = data.find(test_field_name); + ASSERT_NE(field, data.cend()); + + ASSERT_EQ(field->first, test_field_name); + ASSERT_EQ(field->second, test_value); + } +} + +TEST(Config, DataSingle) { + using namespace wtlgo::network; + + Config config; + + Config::data_field_name_t none_name; + for (std::size_t i = 0; i < 10; ++i) { + const Config::data_field_name_t test_field_name = + random_string(10, true); + const Config::data_value_t test_value = random_string(50); + + none_name.push_back(1 + (127 - 1 + test_field_name.at(i)) % (127 - 1)); + + ASSERT_EQ(&config.data_field(test_field_name, test_value), &config); + + const auto real_value = config.data_field(test_field_name); + ASSERT_EQ(real_value.has_value(), true); + ASSERT_EQ(real_value.value().get(), test_value); + } + + ASSERT_EQ(config.data_field(none_name).has_value(), false); +} From fb0077ca2fb7157927729ac91b9ffffc51d7c3c7 Mon Sep 17 00:00:00 2001 From: wtlgo Date: Thu, 12 Jan 2023 11:38:53 +0300 Subject: [PATCH 13/46] Add timeout to config --- include/wtlgo/network/Config.hpp | 5 +++++ src/Config.cpp | 11 ++++++++++- test/src/Config.cpp | 11 +++++++++++ test/src/utility.cpp | 17 ++++++++++++++--- test/src/utility.hpp | 4 +++- 5 files changed, 43 insertions(+), 5 deletions(-) diff --git a/include/wtlgo/network/Config.hpp b/include/wtlgo/network/Config.hpp index c075811..9224260 100644 --- a/include/wtlgo/network/Config.hpp +++ b/include/wtlgo/network/Config.hpp @@ -29,6 +29,8 @@ class Config { std::optional>; using data_t = std::unordered_map; + using timeout_t = unsigned long; + Config(); Config(const Config&); @@ -57,6 +59,9 @@ class Config { Config& data_field(const data_field_name_t& field, const data_value_t& value); + timeout_t timeout() const; + Config& timeout(timeout_t timeout); + private: struct ConfigImpl; std::unique_ptr impl; diff --git a/src/Config.cpp b/src/Config.cpp index 5bbe593..5c5672b 100644 --- a/src/Config.cpp +++ b/src/Config.cpp @@ -40,7 +40,6 @@ struct Config::ConfigImpl { } data_t _data; - const data_t& data() const { return _data; } void data(const data_t& new_data) { _data = new_data; } @@ -58,6 +57,10 @@ struct Config::ConfigImpl { void data_field(const data_field_name_t& field, const data_value_t& value) { _data[field] = value; } + + timeout_t _timeout = 0; + timeout_t timeout() const { return _timeout; } + void timeout(const timeout_t timeout) { _timeout = timeout; } }; Config::Config() : impl{std::make_unique()} {} @@ -118,3 +121,9 @@ Config& Config::data_field(const Config::data_field_name_t& field, impl->data_field(field, value); return *this; } + +Config::timeout_t Config::timeout() const { return impl->timeout(); } +Config& Config::timeout(const timeout_t timeout) { + impl->timeout(timeout); + return *this; +} diff --git a/test/src/Config.cpp b/test/src/Config.cpp index d5e42d8..0dbd1e0 100644 --- a/test/src/Config.cpp +++ b/test/src/Config.cpp @@ -139,3 +139,14 @@ TEST(Config, DataSingle) { ASSERT_EQ(config.data_field(none_name).has_value(), false); } + +TEST(Config, Timeout) { + using namespace wtlgo::network; + Config config; + + ASSERT_EQ(config.timeout(), 0); + + const Config::timeout_t test_timeout = random_unsigned(); + ASSERT_EQ(&config.timeout(test_timeout), &config); + ASSERT_EQ(config.timeout(), test_timeout); +} diff --git a/test/src/utility.cpp b/test/src/utility.cpp index 92f8435..88da74a 100644 --- a/test/src/utility.cpp +++ b/test/src/utility.cpp @@ -1,16 +1,27 @@ #include #include +#include #include "utility.hpp" const std::string test_server = "httpbin.org"; +namespace { +std::mt19937_64 engine{(std::random_device{})()}; +} + std::string random_string(const std::size_t max_length, const bool exact) { - static std::mt19937_64 engine{(std::random_device{})()}; - std::uniform_int_distribution sdist(0, max_length); - std::uniform_int_distribution cdist(0, 127); + std::uniform_int_distribution sdist{0, max_length}; + std::uniform_int_distribution cdist{0, 127}; std::string out; std::generate_n(std::back_inserter(out), exact ? max_length : sdist(engine), [&cdist] { return cdist(engine); }); return out; } + +unsigned random_unsigned() { + static std::uniform_int_distribution dist{ + std::numeric_limits::min(), + std::numeric_limits::max()}; + return dist(engine); +} diff --git a/test/src/utility.hpp b/test/src/utility.hpp index a3e544f..41f4588 100644 --- a/test/src/utility.hpp +++ b/test/src/utility.hpp @@ -3,7 +3,9 @@ #include -std::string random_string(size_t max_length, bool exact = false); extern const std::string test_server; +std::string random_string(size_t max_length, bool exact = false); +unsigned random_unsigned(); + #endif From 79d269eaa65a3fc6032b469bbb2c263cd94bb67e Mon Sep 17 00:00:00 2001 From: wtlgo Date: Thu, 12 Jan 2023 13:14:50 +0300 Subject: [PATCH 14/46] Add HttpBasicAuth class --- CMakeLists.txt | 2 ++ include/wtlgo/network/HttpBasicAuth.hpp | 31 +++++++++++++++++ src/HttpBasicAuth.cpp | 46 +++++++++++++++++++++++++ test/src/HttpBasicAuth.cpp | 39 +++++++++++++++++++++ 4 files changed, 118 insertions(+) create mode 100644 include/wtlgo/network/HttpBasicAuth.hpp create mode 100644 src/HttpBasicAuth.cpp create mode 100644 test/src/HttpBasicAuth.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 3ae48f1..a862bbe 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,6 +16,7 @@ set(PUBLIC_HEADERS "include/wtlgo/network/HttpMethod.hpp" "include/wtlgo/network/CurlController.hpp" "include/wtlgo/network/Client.hpp" + "include/wtlgo/network/HttpBasicAuth.hpp" ) set(SOURCES @@ -23,6 +24,7 @@ set(SOURCES "src/Config.cpp" "src/CurlController.cpp" "src/Client.cpp" + "src/HttpBasicAuth.cpp" ) add_library(Network ${SOURCES}) diff --git a/include/wtlgo/network/HttpBasicAuth.hpp b/include/wtlgo/network/HttpBasicAuth.hpp new file mode 100644 index 0000000..5003cc0 --- /dev/null +++ b/include/wtlgo/network/HttpBasicAuth.hpp @@ -0,0 +1,31 @@ +#ifndef __WTLGO__NETWORK__HTTP_BASIC_AUTH_HPP__ +#define __WTLGO__NETWORK__HTTP_BASIC_AUTH_HPP__ + +#include +#include + +namespace wtlgo { +namespace network { +class HttpBasicAuth { +public: + using username_t = std::string; + using password_t = std::string; + + HttpBasicAuth(); + HttpBasicAuth(const username_t& username, const password_t& password); + virtual ~HttpBasicAuth(); + + const username_t& username() const; + HttpBasicAuth& username(const username_t& new_username); + + const password_t& password() const; + HttpBasicAuth& password(const password_t& new_password); + +private: + struct HttpBasicAuthImpl; + std::unique_ptr impl; +}; +} +} + +#endif diff --git a/src/HttpBasicAuth.cpp b/src/HttpBasicAuth.cpp new file mode 100644 index 0000000..9fb53c7 --- /dev/null +++ b/src/HttpBasicAuth.cpp @@ -0,0 +1,46 @@ +#include + +#include + +using namespace wtlgo::network; + +struct HttpBasicAuth::HttpBasicAuthImpl { + username_t _username; + password_t _password; + + HttpBasicAuthImpl() = default; + HttpBasicAuthImpl(const username_t& username, const password_t& password) + : _username{username}, _password{password} {} + + const username_t& username() const { return _username; } + void username(const username_t& new_username) { _username = new_username; } + + const username_t& password() const { return _password; } + void password(const password_t& new_password) { _password = new_password; } +}; + +HttpBasicAuth::HttpBasicAuth() : impl{std::make_unique()} {} +HttpBasicAuth::HttpBasicAuth(const username_t& username, + const password_t& password) + : impl{std::make_unique(username, password)} {} +HttpBasicAuth::~HttpBasicAuth() = default; + +const HttpBasicAuth::username_t& HttpBasicAuth::username() const { + return impl->username(); +} + +HttpBasicAuth& HttpBasicAuth::username( + const HttpBasicAuth::username_t& new_username) { + impl->username(new_username); + return *this; +} + +const HttpBasicAuth::password_t& HttpBasicAuth::password() const { + return impl->password(); +} + +HttpBasicAuth& HttpBasicAuth::password( + const HttpBasicAuth::password_t& new_password) { + impl->password(new_password); + return *this; +} diff --git a/test/src/HttpBasicAuth.cpp b/test/src/HttpBasicAuth.cpp new file mode 100644 index 0000000..009a067 --- /dev/null +++ b/test/src/HttpBasicAuth.cpp @@ -0,0 +1,39 @@ +#include +#include +#include "utility.hpp" + +TEST(HttpBasicAuth, Init) { + using namespace wtlgo::network; + + const HttpBasicAuth::username_t test_username = random_string(50); + const HttpBasicAuth::password_t test_password = random_string(50); + + HttpBasicAuth auth{test_username, test_password}; + + ASSERT_EQ(auth.username(), test_username); + ASSERT_EQ(auth.password(), test_password); +} + +TEST(HttpBasicAuth, Username) { + using namespace wtlgo::network; + + const HttpBasicAuth::username_t test_username = random_string(50); + + HttpBasicAuth auth; + + ASSERT_EQ(auth.username(), ""); + ASSERT_EQ(&auth.username(test_username), &auth); + ASSERT_EQ(auth.username(), test_username); +} + +TEST(HttpBasicAuth, Password) { + using namespace wtlgo::network; + + const HttpBasicAuth::password_t test_password = random_string(50); + + HttpBasicAuth auth; + + ASSERT_EQ(auth.password(), ""); + ASSERT_EQ(&auth.password(test_password), &auth); + ASSERT_EQ(auth.password(), test_password); +} From 292432eca3ead4abf46d045eac6f6371b703fde1 Mon Sep 17 00:00:00 2001 From: wtlgo Date: Thu, 12 Jan 2023 13:37:07 +0300 Subject: [PATCH 15/46] Add auth to config --- include/wtlgo/network/Config.hpp | 8 ++++- include/wtlgo/network/HttpBasicAuth.hpp | 5 +++ src/Config.cpp | 27 +++++++++++++++ src/HttpBasicAuth.cpp | 2 ++ test/src/Config.cpp | 45 +++++++++++++++++++++++++ 5 files changed, 86 insertions(+), 1 deletion(-) diff --git a/include/wtlgo/network/Config.hpp b/include/wtlgo/network/Config.hpp index 9224260..2e2094f 100644 --- a/include/wtlgo/network/Config.hpp +++ b/include/wtlgo/network/Config.hpp @@ -9,10 +9,10 @@ #include #include +#include namespace wtlgo { namespace network { - class Config { public: using url_t = std::string; @@ -62,6 +62,12 @@ class Config { timeout_t timeout() const; Config& timeout(timeout_t timeout); + const HttpBasicAuth::opt_t& auth() const; + Config& auth(const HttpBasicAuth& auth); + Config& auth(const HttpBasicAuth::username_t& username, + const HttpBasicAuth::password_t& password); + Config& remove_auth(); + private: struct ConfigImpl; std::unique_ptr impl; diff --git a/include/wtlgo/network/HttpBasicAuth.hpp b/include/wtlgo/network/HttpBasicAuth.hpp index 5003cc0..d44baa4 100644 --- a/include/wtlgo/network/HttpBasicAuth.hpp +++ b/include/wtlgo/network/HttpBasicAuth.hpp @@ -3,6 +3,8 @@ #include #include +#include +#include namespace wtlgo { namespace network { @@ -11,8 +13,11 @@ class HttpBasicAuth { using username_t = std::string; using password_t = std::string; + using opt_t = std::optional; + HttpBasicAuth(); HttpBasicAuth(const username_t& username, const password_t& password); + HttpBasicAuth(const HttpBasicAuth&); virtual ~HttpBasicAuth(); const username_t& username() const; diff --git a/src/Config.cpp b/src/Config.cpp index 5c5672b..2ebb76e 100644 --- a/src/Config.cpp +++ b/src/Config.cpp @@ -61,6 +61,15 @@ struct Config::ConfigImpl { timeout_t _timeout = 0; timeout_t timeout() const { return _timeout; } void timeout(const timeout_t timeout) { _timeout = timeout; } + + HttpBasicAuth::opt_t _auth = std::nullopt; + const HttpBasicAuth::opt_t& auth() const { return _auth; } + void auth(const HttpBasicAuth& auth) { _auth.emplace(auth); } + void auth(const HttpBasicAuth::username_t& username, + const HttpBasicAuth::password_t& password) { + _auth.emplace(username, password); + } + void remove_auth() { _auth = std::nullopt; } }; Config::Config() : impl{std::make_unique()} {} @@ -127,3 +136,21 @@ Config& Config::timeout(const timeout_t timeout) { impl->timeout(timeout); return *this; } + +const HttpBasicAuth::opt_t& Config::auth() const { return impl->auth(); } + +Config& Config::auth(const HttpBasicAuth& auth) { + impl->auth(auth); + return *this; +} + +Config& Config::auth(const HttpBasicAuth::username_t& username, + const HttpBasicAuth::password_t& password) { + impl->auth(username, password); + return *this; +} + +Config& Config::remove_auth() { + impl->remove_auth(); + return *this; +} diff --git a/src/HttpBasicAuth.cpp b/src/HttpBasicAuth.cpp index 9fb53c7..1d1e564 100644 --- a/src/HttpBasicAuth.cpp +++ b/src/HttpBasicAuth.cpp @@ -23,6 +23,8 @@ HttpBasicAuth::HttpBasicAuth() : impl{std::make_unique()} {} HttpBasicAuth::HttpBasicAuth(const username_t& username, const password_t& password) : impl{std::make_unique(username, password)} {} +HttpBasicAuth::HttpBasicAuth(const HttpBasicAuth& auth) + : impl{std::make_unique(*auth.impl)} {} HttpBasicAuth::~HttpBasicAuth() = default; const HttpBasicAuth::username_t& HttpBasicAuth::username() const { diff --git a/test/src/Config.cpp b/test/src/Config.cpp index 0dbd1e0..3ba3e4d 100644 --- a/test/src/Config.cpp +++ b/test/src/Config.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include "utility.hpp" @@ -150,3 +151,47 @@ TEST(Config, Timeout) { ASSERT_EQ(&config.timeout(test_timeout), &config); ASSERT_EQ(config.timeout(), test_timeout); } + +TEST(Config, AuthObject) { + using namespace wtlgo::network; + Config config; + + ASSERT_EQ(config.auth().has_value(), false); + + const HttpBasicAuth test_auth{random_string(50), random_string(50)}; + + ASSERT_EQ(&config.auth(test_auth), &config); + ASSERT_EQ(config.auth().has_value(), true); + ASSERT_EQ(config.auth().value().username(), test_auth.username()); + ASSERT_EQ(config.auth().value().password(), test_auth.password()); +} + +TEST(Config, AuthFields) { + using namespace wtlgo::network; + Config config; + + ASSERT_EQ(config.auth().has_value(), false); + + const HttpBasicAuth::username_t test_username = random_string(50); + const HttpBasicAuth::password_t test_password = random_string(50); + + ASSERT_EQ(&config.auth(test_username, test_password), &config); + ASSERT_EQ(config.auth().has_value(), true); + ASSERT_EQ(config.auth().value().username(), test_username); + ASSERT_EQ(config.auth().value().password(), test_password); +} + +TEST(Config, AuthRemove) { + using namespace wtlgo::network; + Config config; + + ASSERT_EQ(config.auth().has_value(), false); + + const HttpBasicAuth test_auth{random_string(50), random_string(50)}; + + ASSERT_EQ(&config.auth(test_auth), &config); + ASSERT_EQ(config.auth().has_value(), true); + + ASSERT_EQ(&config.remove_auth(), &config); + ASSERT_EQ(config.auth().has_value(), false); +} From 67205f80eff20488b859a53c36623548964c0da2 Mon Sep 17 00:00:00 2001 From: wtlgo Date: Mon, 23 Jan 2023 16:15:55 +0300 Subject: [PATCH 16/46] Screw it. from the scratch. Add HttpBasicAuth --- CMakeLists.txt | 12 +- include/wtlgo/network/Client.hpp | 26 --- include/wtlgo/network/Config.hpp | 78 ------- include/wtlgo/network/CurlController.hpp | 33 --- .../wtlgo/network/DefaultHttpBasicAuth.hpp | 46 ++++ include/wtlgo/network/HttpBasicAuth.hpp | 35 ++-- include/wtlgo/network/HttpMethod.hpp | 10 - src/Client.cpp | 24 --- src/Config.cpp | 156 -------------- src/CurlController.cpp | 36 ---- src/DefaultHttpBasicAuth.cpp | 73 +++++++ src/HttpBasicAuth.cpp | 48 ----- test/src/Client.cpp | 7 - test/src/Config.cpp | 197 ------------------ test/src/CurlController.cpp | 15 -- test/src/DefaultHttpBasicAuth.cpp | 45 ++++ test/src/HttpBasicAuth.cpp | 39 ---- test/src/OldRequestTestsGet.cpp | 113 ---------- test/src/OldRequestTestsPost.cpp | 112 ---------- test/src/OldSanityTest.cpp | 7 - 20 files changed, 181 insertions(+), 931 deletions(-) delete mode 100644 include/wtlgo/network/Client.hpp delete mode 100644 include/wtlgo/network/Config.hpp delete mode 100644 include/wtlgo/network/CurlController.hpp create mode 100644 include/wtlgo/network/DefaultHttpBasicAuth.hpp delete mode 100644 include/wtlgo/network/HttpMethod.hpp delete mode 100644 src/Client.cpp delete mode 100644 src/Config.cpp delete mode 100644 src/CurlController.cpp create mode 100644 src/DefaultHttpBasicAuth.cpp delete mode 100644 src/HttpBasicAuth.cpp delete mode 100644 test/src/Client.cpp delete mode 100644 test/src/Config.cpp delete mode 100644 test/src/CurlController.cpp create mode 100644 test/src/DefaultHttpBasicAuth.cpp delete mode 100644 test/src/HttpBasicAuth.cpp delete mode 100644 test/src/OldRequestTestsGet.cpp delete mode 100644 test/src/OldRequestTestsPost.cpp delete mode 100644 test/src/OldSanityTest.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index a862bbe..972f3f5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,19 +12,14 @@ find_package(CURL REQUIRED) set(PUBLIC_HEADERS "include/wtlgo/NetworkOld.hpp" - "include/wtlgo/network/Config.hpp" - "include/wtlgo/network/HttpMethod.hpp" - "include/wtlgo/network/CurlController.hpp" - "include/wtlgo/network/Client.hpp" + "include/wtlgo/network/HttpBasicAuth.hpp" + "include/wtlgo/network/DefaultHttpBasicAuth.hpp" ) set(SOURCES "src/NetworkOld.cpp" - "src/Config.cpp" - "src/CurlController.cpp" - "src/Client.cpp" - "src/HttpBasicAuth.cpp" + "src/DefaultHttpBasicAuth.cpp" ) add_library(Network ${SOURCES}) @@ -34,7 +29,6 @@ target_link_libraries(Network PUBLIC CURL::libcurl) target_include_directories(Network PUBLIC include/) target_include_directories(Network PRIVATE include/) - set_target_properties(Network PROPERTIES PUBLIC_HEADER "${PUBLIC_HEADERS}" VERSION ${PROJECT_VERSION} diff --git a/include/wtlgo/network/Client.hpp b/include/wtlgo/network/Client.hpp deleted file mode 100644 index cd83daf..0000000 --- a/include/wtlgo/network/Client.hpp +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef __WTLGO__NETWORK__CLIENT_HPP__ -#define __WTLGO__NETWORK__CLIENT_HPP__ - -#include - -#include - -namespace wtlgo { -namespace network { -class Client { -public: - Client(); - Client(const Config& config); - virtual ~Client(); - - Config& config(); - const Config& config() const; - -private: - struct ClientImpl; - std::unique_ptr impl; -}; -} -} - -#endif diff --git a/include/wtlgo/network/Config.hpp b/include/wtlgo/network/Config.hpp deleted file mode 100644 index 2e2094f..0000000 --- a/include/wtlgo/network/Config.hpp +++ /dev/null @@ -1,78 +0,0 @@ -#ifndef __WTLGO__NETWORK__CONFIG_HPP__ -#define __WTLGO__NETWORK__CONFIG_HPP__ - -#include -#include -#include -#include -#include -#include - -#include -#include - -namespace wtlgo { -namespace network { -class Config { -public: - using url_t = std::string; - - using header_field_name_t = std::string; - using header_value_t = std::string; - using header_value_opt_ref_t = - std::optional>; - using headers_t = std::unordered_map; - - using data_field_name_t = std::string; - using data_value_t = std::variant; - using data_value_opt_ref_t = - std::optional>; - using data_t = std::unordered_map; - - using timeout_t = unsigned long; - - Config(); - Config(const Config&); - - virtual ~Config(); - - const url_t& url() const; - Config& url(const url_t& new_url); - - HttpMethod method() const; - Config& method(HttpMethod new_method); - - const url_t& base_url() const; - Config& base_url(const url_t& new_base_url); - - const headers_t& headers() const; - Config& headers(const headers_t& new_headers); - - const header_value_opt_ref_t header(const header_field_name_t& field) const; - Config& header(const header_field_name_t& field_name, - const header_value_t& value); - - const data_t& data() const; - Config& data(const data_t& new_data); - - const data_value_opt_ref_t data_field(const data_field_name_t& field) const; - Config& data_field(const data_field_name_t& field, - const data_value_t& value); - - timeout_t timeout() const; - Config& timeout(timeout_t timeout); - - const HttpBasicAuth::opt_t& auth() const; - Config& auth(const HttpBasicAuth& auth); - Config& auth(const HttpBasicAuth::username_t& username, - const HttpBasicAuth::password_t& password); - Config& remove_auth(); - -private: - struct ConfigImpl; - std::unique_ptr impl; -}; -} -} - -#endif diff --git a/include/wtlgo/network/CurlController.hpp b/include/wtlgo/network/CurlController.hpp deleted file mode 100644 index 79c303a..0000000 --- a/include/wtlgo/network/CurlController.hpp +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef __WTLGO__NETWORK__CURL_CONTROLLER_HPP__ -#define __WTLGO__NETWORK__CURL_CONTROLLER_HPP__ - -#include - -#include - -namespace wtlgo { -namespace network { -class CurlController { -public: - using curl_handler_t = std::unique_ptr; - - CurlController(const CurlController&) = delete; - void operator=(const CurlController&) = delete; - - static CurlController& instance(); - - void global_init(); - - curl_handler_t get_handler(); - -private: - CurlController(); - ~CurlController(); - - struct CurlControllerImpl; - std::unique_ptr impl; -}; -} -} - -#endif diff --git a/include/wtlgo/network/DefaultHttpBasicAuth.hpp b/include/wtlgo/network/DefaultHttpBasicAuth.hpp new file mode 100644 index 0000000..f18733d --- /dev/null +++ b/include/wtlgo/network/DefaultHttpBasicAuth.hpp @@ -0,0 +1,46 @@ +#ifndef __WTLGO__NETWORK__DEFAULT_HTTP_BASIC_AUTH__ +#define __WTLGO__NETWORK__DEFAULT_HTTP_BASIC_AUTH__ + +#include + +#include + +namespace wtlgo { +namespace network { +class DefaultHttpBasicAuth + : public HttpBasicAuth, + public std::enable_shared_from_this { +public: + using sptr_t = std::shared_ptr; + using csptr_t = std::shared_ptr; + + ~DefaultHttpBasicAuth(); + + [[nodiscard]] static DefaultHttpBasicAuth::sptr_t create( + HttpBasicAuth::username_ref_t username, + HttpBasicAuth::password_ref_t password); + + HttpBasicAuth::sptr_t clone() const override; + + HttpBasicAuth::username_ref_t username() const override; + HttpBasicAuth::sptr_t username(HttpBasicAuth::username_ref_t) override; + + HttpBasicAuth::password_ref_t password() const override; + HttpBasicAuth::sptr_t password(HttpBasicAuth::password_ref_t) override; + +protected: + DefaultHttpBasicAuth(HttpBasicAuth::username_ref_t username, + HttpBasicAuth::password_ref_t password); + +private: + struct Impl; + const std::unique_ptr impl; + + DefaultHttpBasicAuth(const std::unique_ptr&); +}; + +using DHttpBasicAuth = DefaultHttpBasicAuth; +} +} + +#endif diff --git a/include/wtlgo/network/HttpBasicAuth.hpp b/include/wtlgo/network/HttpBasicAuth.hpp index d44baa4..a4e9d05 100644 --- a/include/wtlgo/network/HttpBasicAuth.hpp +++ b/include/wtlgo/network/HttpBasicAuth.hpp @@ -1,34 +1,27 @@ -#ifndef __WTLGO__NETWORK__HTTP_BASIC_AUTH_HPP__ -#define __WTLGO__NETWORK__HTTP_BASIC_AUTH_HPP__ +#ifndef __WTLGO__NETWORK__HTTP_BASIC_AUTH__ +#define __WTLGO__NETWORK__HTTP_BASIC_AUTH__ -#include #include -#include -#include +#include namespace wtlgo { namespace network { -class HttpBasicAuth { -public: - using username_t = std::string; - using password_t = std::string; +struct HttpBasicAuth { + using sptr_t = std::shared_ptr; + using csptr_t = std::shared_ptr; - using opt_t = std::optional; + using username_ref_t = std::string_view; + using password_ref_t = std::string_view; - HttpBasicAuth(); - HttpBasicAuth(const username_t& username, const password_t& password); - HttpBasicAuth(const HttpBasicAuth&); - virtual ~HttpBasicAuth(); + virtual ~HttpBasicAuth() = default; - const username_t& username() const; - HttpBasicAuth& username(const username_t& new_username); + virtual sptr_t clone() const = 0; - const password_t& password() const; - HttpBasicAuth& password(const password_t& new_password); + virtual username_ref_t username() const = 0; + virtual sptr_t username(username_ref_t) = 0; -private: - struct HttpBasicAuthImpl; - std::unique_ptr impl; + virtual password_ref_t password() const = 0; + virtual sptr_t password(password_ref_t) = 0; }; } } diff --git a/include/wtlgo/network/HttpMethod.hpp b/include/wtlgo/network/HttpMethod.hpp deleted file mode 100644 index 99bd9b3..0000000 --- a/include/wtlgo/network/HttpMethod.hpp +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef __WTLGO__NETWORK__HTTP_METHOD_HPP__ -#define __WTLGO__NETWORK__HTTP_METHOD_HPP__ - -namespace wtlgo { -namespace network { -enum class HttpMethod { GET, POST, PUT, PATCH, DELETE }; -} -} - -#endif diff --git a/src/Client.cpp b/src/Client.cpp deleted file mode 100644 index 19cbd07..0000000 --- a/src/Client.cpp +++ /dev/null @@ -1,24 +0,0 @@ -#include - -#include -#include - -using namespace wtlgo::network; - -struct Client::ClientImpl { - Config _config; - - ClientImpl() = default; - ClientImpl(const Config& config) : _config{config} {} - - Config& config() { return _config; } - const Config& config() const { return _config; } -}; - -Client::Client() : impl{std::make_unique()} {} -Client::Client(const Config& config) - : impl{std::make_unique(config)} {} -Client::~Client() = default; - -Config& Client::config() { return impl->config(); } -const Config& Client::config() const { return impl->config(); } diff --git a/src/Config.cpp b/src/Config.cpp deleted file mode 100644 index 2ebb76e..0000000 --- a/src/Config.cpp +++ /dev/null @@ -1,156 +0,0 @@ -#include -#include - -#include -#include - -using namespace wtlgo::network; - -struct Config::ConfigImpl { - url_t _url; - const url_t& url() const { return _url; } - void url(const url_t& new_url) { _url = new_url; } - - HttpMethod _method = HttpMethod::GET; - HttpMethod method() const { return _method; } - void method(const HttpMethod new_method) { _method = new_method; } - - url_t _base_url; - const url_t& base_url() const { return _base_url; } - void base_url(const url_t& new_base_url) { _base_url = new_base_url; } - - headers_t _headers; - const headers_t& headers() const { return _headers; } - void headers(const headers_t& new_headers) { _headers = new_headers; } - - const header_value_opt_ref_t header( - const header_field_name_t& field_name) const { - const auto field = _headers.find(field_name); - - if (field == _headers.cend()) { - return std::nullopt; - } - - return std::cref(field->second); - } - - void header(const header_field_name_t& field_name, - const header_value_t& value) { - _headers[field_name] = value; - } - - data_t _data; - const data_t& data() const { return _data; } - void data(const data_t& new_data) { _data = new_data; } - - const data_value_opt_ref_t data_field( - const data_field_name_t& field_name) const { - const auto field = _data.find(field_name); - - if (field == _data.cend()) { - return std::nullopt; - } - - return std::cref(field->second); - } - - void data_field(const data_field_name_t& field, const data_value_t& value) { - _data[field] = value; - } - - timeout_t _timeout = 0; - timeout_t timeout() const { return _timeout; } - void timeout(const timeout_t timeout) { _timeout = timeout; } - - HttpBasicAuth::opt_t _auth = std::nullopt; - const HttpBasicAuth::opt_t& auth() const { return _auth; } - void auth(const HttpBasicAuth& auth) { _auth.emplace(auth); } - void auth(const HttpBasicAuth::username_t& username, - const HttpBasicAuth::password_t& password) { - _auth.emplace(username, password); - } - void remove_auth() { _auth = std::nullopt; } -}; - -Config::Config() : impl{std::make_unique()} {} -Config::Config(const Config& conf) - : impl{std::make_unique(*conf.impl)} {} - -Config::~Config() = default; - -const Config::url_t& Config::url() const { return impl->url(); } -Config& Config::url(const Config::url_t& new_url) { - impl->url(new_url); - return *this; -} - -HttpMethod Config::method() const { return impl->method(); } -Config& Config::method(const HttpMethod new_method) { - impl->method(new_method); - return *this; -} - -const Config::url_t& Config::base_url() const { return impl->base_url(); } -Config& Config::base_url(const Config::url_t& new_base_url) { - impl->base_url(new_base_url); - return *this; -} - -const Config::headers_t& Config::headers() const { return impl->headers(); } -Config& Config::headers(const Config::headers_t& new_headers) { - impl->headers(new_headers); - return *this; -} - -const Config::header_value_opt_ref_t Config::header( - const Config::header_field_name_t& field) const { - return impl->header(field); -} - -Config& Config::header(const Config::header_field_name_t& field_name, - const Config::header_value_t& value) { - impl->header(field_name, value); - return *this; -} - -const Config::data_t& Config::data() const { return impl->data(); } - -Config& Config::data(const Config::data_t& new_data) { - impl->data(new_data); - return *this; -} - -const Config::data_value_opt_ref_t Config::data_field( - const Config::data_field_name_t& field) const { - return impl->data_field(field); -} - -Config& Config::data_field(const Config::data_field_name_t& field, - const Config::data_value_t& value) { - impl->data_field(field, value); - return *this; -} - -Config::timeout_t Config::timeout() const { return impl->timeout(); } -Config& Config::timeout(const timeout_t timeout) { - impl->timeout(timeout); - return *this; -} - -const HttpBasicAuth::opt_t& Config::auth() const { return impl->auth(); } - -Config& Config::auth(const HttpBasicAuth& auth) { - impl->auth(auth); - return *this; -} - -Config& Config::auth(const HttpBasicAuth::username_t& username, - const HttpBasicAuth::password_t& password) { - impl->auth(username, password); - return *this; -} - -Config& Config::remove_auth() { - impl->remove_auth(); - return *this; -} diff --git a/src/CurlController.cpp b/src/CurlController.cpp deleted file mode 100644 index 0ca3603..0000000 --- a/src/CurlController.cpp +++ /dev/null @@ -1,36 +0,0 @@ -#include -#include - -#include - -#include - -using namespace wtlgo::network; - -struct CurlController::CurlControllerImpl { - std::atomic_bool did_init{false}; - void global_init() { - if (did_init.exchange(true)) return; - curl_global_init(CURL_GLOBAL_ALL); - } - - curl_handler_t get_handler(CurlController& controller) { - controller.global_init(); - return {curl_easy_init(), curl_easy_cleanup}; - } -}; - -CurlController& CurlController::instance() { - static CurlController instance; - return instance; -} - -void CurlController::global_init() { impl->global_init(); } - -CurlController::curl_handler_t CurlController::get_handler() { - return impl->get_handler(*this); -} - -CurlController::CurlController() - : impl{std::make_unique()} {} -CurlController::~CurlController() = default; diff --git a/src/DefaultHttpBasicAuth.cpp b/src/DefaultHttpBasicAuth.cpp new file mode 100644 index 0000000..3dcb9e4 --- /dev/null +++ b/src/DefaultHttpBasicAuth.cpp @@ -0,0 +1,73 @@ +#include +#include +#include + +#include +#include + +using namespace wtlgo::network; + +struct DefaultHttpBasicAuth::Impl { +private: + std::string _username; + std::string _password; + +public: + Impl() = default; + Impl(const Impl&) = default; + Impl(const HttpBasicAuth::username_ref_t username, + const HttpBasicAuth::password_ref_t password) + : _username{username}, _password{password} {} + + HttpBasicAuth::username_ref_t username() const { return _username; } + void username(const HttpBasicAuth::username_ref_t username) { + _username = username; + } + + HttpBasicAuth::password_ref_t password() const { return _password; } + void password(const HttpBasicAuth::password_ref_t password) { + _password = password; + } +}; + +DefaultHttpBasicAuth::~DefaultHttpBasicAuth() = default; + +DefaultHttpBasicAuth::sptr_t DefaultHttpBasicAuth::create( + const HttpBasicAuth::username_ref_t username, + const HttpBasicAuth::password_ref_t password) { + return std::shared_ptr( + new DefaultHttpBasicAuth{username, password}); +} + +HttpBasicAuth::sptr_t DefaultHttpBasicAuth::clone() const { + return std::shared_ptr( + new DefaultHttpBasicAuth{impl}); +} + +HttpBasicAuth::username_ref_t DefaultHttpBasicAuth::username() const { + return impl->username(); +} + +HttpBasicAuth::sptr_t DefaultHttpBasicAuth::username( + const HttpBasicAuth::username_ref_t username) { + impl->username(username); + return shared_from_this(); +} + +HttpBasicAuth::password_ref_t DefaultHttpBasicAuth::password() const { + return impl->password(); +} + +HttpBasicAuth::sptr_t DefaultHttpBasicAuth::password( + const HttpBasicAuth::password_ref_t password) { + impl->password(password); + return shared_from_this(); +} + +DefaultHttpBasicAuth::DefaultHttpBasicAuth( + const HttpBasicAuth::username_ref_t username, + const HttpBasicAuth::password_ref_t password) + : impl{std::make_unique(username, password)} {} + +DefaultHttpBasicAuth::DefaultHttpBasicAuth(const std::unique_ptr& impl) + : impl{std::make_unique(*impl)} {} diff --git a/src/HttpBasicAuth.cpp b/src/HttpBasicAuth.cpp deleted file mode 100644 index 1d1e564..0000000 --- a/src/HttpBasicAuth.cpp +++ /dev/null @@ -1,48 +0,0 @@ -#include - -#include - -using namespace wtlgo::network; - -struct HttpBasicAuth::HttpBasicAuthImpl { - username_t _username; - password_t _password; - - HttpBasicAuthImpl() = default; - HttpBasicAuthImpl(const username_t& username, const password_t& password) - : _username{username}, _password{password} {} - - const username_t& username() const { return _username; } - void username(const username_t& new_username) { _username = new_username; } - - const username_t& password() const { return _password; } - void password(const password_t& new_password) { _password = new_password; } -}; - -HttpBasicAuth::HttpBasicAuth() : impl{std::make_unique()} {} -HttpBasicAuth::HttpBasicAuth(const username_t& username, - const password_t& password) - : impl{std::make_unique(username, password)} {} -HttpBasicAuth::HttpBasicAuth(const HttpBasicAuth& auth) - : impl{std::make_unique(*auth.impl)} {} -HttpBasicAuth::~HttpBasicAuth() = default; - -const HttpBasicAuth::username_t& HttpBasicAuth::username() const { - return impl->username(); -} - -HttpBasicAuth& HttpBasicAuth::username( - const HttpBasicAuth::username_t& new_username) { - impl->username(new_username); - return *this; -} - -const HttpBasicAuth::password_t& HttpBasicAuth::password() const { - return impl->password(); -} - -HttpBasicAuth& HttpBasicAuth::password( - const HttpBasicAuth::password_t& new_password) { - impl->password(new_password); - return *this; -} diff --git a/test/src/Client.cpp b/test/src/Client.cpp deleted file mode 100644 index e6da317..0000000 --- a/test/src/Client.cpp +++ /dev/null @@ -1,7 +0,0 @@ -#include -#include - -TEST(Client, SomeTest) { - using namespace wtlgo::network; - Client client; -} diff --git a/test/src/Config.cpp b/test/src/Config.cpp deleted file mode 100644 index 3ba3e4d..0000000 --- a/test/src/Config.cpp +++ /dev/null @@ -1,197 +0,0 @@ -#include -#include -#include -#include -#include "utility.hpp" - -TEST(Config, Url) { - using namespace wtlgo::network; - - Config config; - - ASSERT_EQ(config.url(), ""); - - const std::string test_url = random_string(42); - ASSERT_EQ(&config.url(test_url), &config); - - ASSERT_EQ(config.url(), test_url); -} - -TEST(Config, Method) { - using namespace wtlgo::network; - - Config config; - - ASSERT_EQ(config.method(), HttpMethod::GET); - - for (const HttpMethod test_method : - {HttpMethod::POST, HttpMethod::PUT, HttpMethod::PATCH, - HttpMethod::DELETE, HttpMethod::GET}) { - ASSERT_EQ(&config.method(test_method), &config); - ASSERT_EQ(config.method(), test_method); - } -} - -TEST(Config, BaseUrl) { - using namespace wtlgo::network; - - Config config; - - ASSERT_EQ(config.base_url(), ""); - - const std::string test_base_url = random_string(42); - ASSERT_EQ(&config.base_url(test_base_url), &config); - - ASSERT_EQ(config.base_url(), test_base_url); -} - -TEST(Config, HeadersAll) { - using namespace wtlgo::network; - - Config config; - - ASSERT_EQ(config.headers().size(), 0); - - Config::headers_t test_headers; - for (std::size_t i = 0; i < 10; ++i) { - test_headers[random_string(50)] = random_string(50); - } - - ASSERT_EQ(&config.headers(test_headers), &config); - ASSERT_EQ(config.headers().size(), test_headers.size()); - - for (const auto & [ test_field_name, test_value ] : test_headers) { - const auto& headers = config.headers(); - const auto field = headers.find(test_field_name); - ASSERT_NE(field, headers.cend()); - - ASSERT_EQ(field->first, test_field_name); - ASSERT_EQ(field->second, test_value); - } -} - -TEST(Config, HeadersSingle) { - using namespace wtlgo::network; - - Config config; - - Config::header_field_name_t none_name; - for (std::size_t i = 0; i < 10; ++i) { - const Config::header_field_name_t test_field_name = - random_string(10, true); - const Config::header_value_t test_value = random_string(50); - - none_name.push_back(1 + (127 - 1 + test_field_name.at(i)) % (127 - 1)); - - ASSERT_EQ(&config.header(test_field_name, test_value), &config); - - const auto real_value = config.header(test_field_name); - ASSERT_EQ(real_value.has_value(), true); - ASSERT_EQ(real_value.value().get(), test_value); - } - - ASSERT_EQ(config.header(none_name).has_value(), false); -} - -TEST(Config, DataAll) { - using namespace wtlgo::network; - - Config config; - - ASSERT_EQ(config.data().size(), 0); - - Config::data_t test_data; - for (std::size_t i = 0; i < 10; ++i) { - test_data[random_string(50)] = random_string(50); - } - - ASSERT_EQ(&config.data(test_data), &config); - ASSERT_EQ(config.data().size(), test_data.size()); - - for (const auto & [ test_field_name, test_value ] : test_data) { - const auto& data = config.data(); - const auto field = data.find(test_field_name); - ASSERT_NE(field, data.cend()); - - ASSERT_EQ(field->first, test_field_name); - ASSERT_EQ(field->second, test_value); - } -} - -TEST(Config, DataSingle) { - using namespace wtlgo::network; - - Config config; - - Config::data_field_name_t none_name; - for (std::size_t i = 0; i < 10; ++i) { - const Config::data_field_name_t test_field_name = - random_string(10, true); - const Config::data_value_t test_value = random_string(50); - - none_name.push_back(1 + (127 - 1 + test_field_name.at(i)) % (127 - 1)); - - ASSERT_EQ(&config.data_field(test_field_name, test_value), &config); - - const auto real_value = config.data_field(test_field_name); - ASSERT_EQ(real_value.has_value(), true); - ASSERT_EQ(real_value.value().get(), test_value); - } - - ASSERT_EQ(config.data_field(none_name).has_value(), false); -} - -TEST(Config, Timeout) { - using namespace wtlgo::network; - Config config; - - ASSERT_EQ(config.timeout(), 0); - - const Config::timeout_t test_timeout = random_unsigned(); - ASSERT_EQ(&config.timeout(test_timeout), &config); - ASSERT_EQ(config.timeout(), test_timeout); -} - -TEST(Config, AuthObject) { - using namespace wtlgo::network; - Config config; - - ASSERT_EQ(config.auth().has_value(), false); - - const HttpBasicAuth test_auth{random_string(50), random_string(50)}; - - ASSERT_EQ(&config.auth(test_auth), &config); - ASSERT_EQ(config.auth().has_value(), true); - ASSERT_EQ(config.auth().value().username(), test_auth.username()); - ASSERT_EQ(config.auth().value().password(), test_auth.password()); -} - -TEST(Config, AuthFields) { - using namespace wtlgo::network; - Config config; - - ASSERT_EQ(config.auth().has_value(), false); - - const HttpBasicAuth::username_t test_username = random_string(50); - const HttpBasicAuth::password_t test_password = random_string(50); - - ASSERT_EQ(&config.auth(test_username, test_password), &config); - ASSERT_EQ(config.auth().has_value(), true); - ASSERT_EQ(config.auth().value().username(), test_username); - ASSERT_EQ(config.auth().value().password(), test_password); -} - -TEST(Config, AuthRemove) { - using namespace wtlgo::network; - Config config; - - ASSERT_EQ(config.auth().has_value(), false); - - const HttpBasicAuth test_auth{random_string(50), random_string(50)}; - - ASSERT_EQ(&config.auth(test_auth), &config); - ASSERT_EQ(config.auth().has_value(), true); - - ASSERT_EQ(&config.remove_auth(), &config); - ASSERT_EQ(config.auth().has_value(), false); -} diff --git a/test/src/CurlController.cpp b/test/src/CurlController.cpp deleted file mode 100644 index a1525f1..0000000 --- a/test/src/CurlController.cpp +++ /dev/null @@ -1,15 +0,0 @@ -#include -#include - -TEST(CurlController, IsSingleton) { - using namespace wtlgo::network; - - ASSERT_EQ(&CurlController::instance(), &CurlController::instance()); -} - -TEST(CurlController, ProducesCURLInstance) { - using namespace wtlgo::network; - - const auto test = CurlController::instance().get_handler(); - ASSERT_NE(test, nullptr); -} diff --git a/test/src/DefaultHttpBasicAuth.cpp b/test/src/DefaultHttpBasicAuth.cpp new file mode 100644 index 0000000..ec3d516 --- /dev/null +++ b/test/src/DefaultHttpBasicAuth.cpp @@ -0,0 +1,45 @@ +#include +#include "utility.hpp" + +#include + +#include +#include + +TEST(DefaultHttpBasicAuth, Create) { + using namespace wtlgo::network; + + const std::string test_username = random_string(50); + const std::string test_password = random_string(50); + + const HttpBasicAuth::csptr_t client = + DefaultHttpBasicAuth::create(test_username, test_password); + + ASSERT_NE(client, nullptr); + ASSERT_EQ(client->username(), test_username); + ASSERT_EQ(client->password(), test_password); +} + +TEST(DefaultHttpBasicAuth, SetUsername) { + using namespace wtlgo::network; + + const HttpBasicAuth::sptr_t client = + DefaultHttpBasicAuth::create(random_string(50), random_string(50)); + ASSERT_NE(client, nullptr); + + const std::string test_username = random_string(50); + ASSERT_EQ(client, client->username(test_username)); + ASSERT_EQ(client->username(), test_username); +} + +TEST(DefaultHttpBasicAuth, SetPassword) { + using namespace wtlgo::network; + + const HttpBasicAuth::sptr_t client = + DefaultHttpBasicAuth::create(random_string(50), random_string(50)); + ASSERT_NE(client, nullptr); + + const std::string test_password = random_string(50); + ASSERT_EQ(client, client->password(test_password)); + ASSERT_EQ(client->password(), test_password); +} diff --git a/test/src/HttpBasicAuth.cpp b/test/src/HttpBasicAuth.cpp deleted file mode 100644 index 009a067..0000000 --- a/test/src/HttpBasicAuth.cpp +++ /dev/null @@ -1,39 +0,0 @@ -#include -#include -#include "utility.hpp" - -TEST(HttpBasicAuth, Init) { - using namespace wtlgo::network; - - const HttpBasicAuth::username_t test_username = random_string(50); - const HttpBasicAuth::password_t test_password = random_string(50); - - HttpBasicAuth auth{test_username, test_password}; - - ASSERT_EQ(auth.username(), test_username); - ASSERT_EQ(auth.password(), test_password); -} - -TEST(HttpBasicAuth, Username) { - using namespace wtlgo::network; - - const HttpBasicAuth::username_t test_username = random_string(50); - - HttpBasicAuth auth; - - ASSERT_EQ(auth.username(), ""); - ASSERT_EQ(&auth.username(test_username), &auth); - ASSERT_EQ(auth.username(), test_username); -} - -TEST(HttpBasicAuth, Password) { - using namespace wtlgo::network; - - const HttpBasicAuth::password_t test_password = random_string(50); - - HttpBasicAuth auth; - - ASSERT_EQ(auth.password(), ""); - ASSERT_EQ(&auth.password(test_password), &auth); - ASSERT_EQ(auth.password(), test_password); -} diff --git a/test/src/OldRequestTestsGet.cpp b/test/src/OldRequestTestsGet.cpp deleted file mode 100644 index 02fc154..0000000 --- a/test/src/OldRequestTestsGet.cpp +++ /dev/null @@ -1,113 +0,0 @@ -#include -#include -#include -#include - -#include "utility.hpp" - -TEST(OldRequest, Get_NoSSL_Static) { - using namespace wtlgo::old; - using json = nlohmann::json; - using string = std::string; - - const string response = - network.request("http://" + test_server + "/get", {{"hello", "hello"}}); - - ASSERT_NO_THROW({ - auto resp = json::parse(response); - ASSERT_EQ(resp["args"]["hello"], "hello"); - }); -} - -TEST(OldRequest, Get_SSL_Static) { - using namespace wtlgo::old; - using json = nlohmann::json; - using string = std::string; - - const string response = network.request("https://" + test_server + "/get", - {{"hello", "hello"}}); - ASSERT_NO_THROW({ - auto resp = json::parse(response); - ASSERT_EQ(resp["args"]["hello"], "hello"); - }); -} - -TEST(OldRequest, Get_NoSSL_Random) { - using namespace wtlgo::old; - using json = nlohmann::json; - using string = std::string; - - ASSERT_NO_THROW({ - const string arg = random_string(500); - const string val = random_string(1000); - - const string response = - network.request("http://" + test_server + "/get", {{arg, val}}); - - const auto resp = json::parse(response); - - ASSERT_EQ(resp["args"][arg], val); - }); -} - -TEST(OldRequest, Get_SSL_Random) { - using namespace wtlgo::old; - using json = nlohmann::json; - using string = std::string; - - ASSERT_NO_THROW({ - const string arg = random_string(500); - const string val = random_string(500); - - const string response = - network.request("https://" + test_server + "/get", {{arg, val}}); - const auto resp = json::parse(response); - - ASSERT_EQ(resp["args"][arg], val); - }); -} - -TEST(OldRequest, Get_NoSSL_Random_MultipleArgs) { - using namespace wtlgo::old; - using json = nlohmann::json; - using string = std::string; - using map = std::map; - - map args; - for (size_t i = 0; i < 10; ++i) { - args[random_string(50)] = random_string(50); - } - - ASSERT_NO_THROW({ - const string response = - network.request("http://" + test_server + "/get", args); - const auto resp = json::parse(response); - - for (const auto& arg : args) { - ASSERT_EQ(resp["args"][arg.first], arg.second); - } - }); -} - -TEST(OldRequest, Get_SSL_Random_MultipleArgs) { - using namespace wtlgo::old; - using json = nlohmann::json; - using string = std::string; - using map = std::map; - - map args; - for (size_t i = 0; i < 10; ++i) { - args[random_string(50)] = random_string(50); - } - - ASSERT_NO_THROW({ - const string response = - network.request("https://" + test_server + "/get", args); - - const auto resp = json::parse(response); - - for (const auto& arg : args) { - ASSERT_EQ(resp["args"][arg.first], arg.second); - } - }); -} diff --git a/test/src/OldRequestTestsPost.cpp b/test/src/OldRequestTestsPost.cpp deleted file mode 100644 index 866364e..0000000 --- a/test/src/OldRequestTestsPost.cpp +++ /dev/null @@ -1,112 +0,0 @@ -#include -#include -#include -#include - -#include "utility.hpp" - -TEST(OldRequest, Post_NoSSL_Static) { - using namespace wtlgo::old; - using json = nlohmann::json; - using string = std::string; - - const string response = network.request("http://" + test_server + "/post", - {{"hello", "hello"}}, true); - ASSERT_NO_THROW({ - auto resp = json::parse(response); - ASSERT_EQ(resp["form"]["hello"], "hello"); - }); -} - -TEST(OldRequest, Post_SSL_Static) { - using namespace wtlgo::old; - using json = nlohmann::json; - using string = std::string; - - const string response = network.request("https://" + test_server + "/post", - {{"hello", "hello"}}, true); - ASSERT_NO_THROW({ - const auto resp = json::parse(response); - ASSERT_EQ(resp["form"]["hello"], "hello"); - }); -} - -TEST(OldRequest, Post_NoSSL_Random) { - using namespace wtlgo::old; - using json = nlohmann::json; - using string = std::string; - - ASSERT_NO_THROW({ - const string arg = random_string(1000); - const string val = random_string(1000); - - const string response = network.request( - "http://" + test_server + "/post", {{arg, val}}, true); - const auto resp = json::parse(response); - - ASSERT_EQ(resp["form"][arg], val); - }); -} - -TEST(OldRequest, Post_SSL_Random) { - using namespace wtlgo::old; - using json = nlohmann::json; - using string = std::string; - - ASSERT_NO_THROW({ - const string arg = random_string(1000); - const string val = random_string(1000); - - const string response = network.request( - "https://" + test_server + "/post", {{arg, val}}, true); - - const auto resp = json::parse(response); - - ASSERT_EQ(resp["form"][arg], val); - }); -} - -TEST(OldRequest, Post_NoSSL_Random_MultipleArgs) { - using namespace wtlgo::old; - using json = nlohmann::json; - using string = std::string; - using map = std::map; - - map args; - for (size_t i = 0; i < 10; ++i) { - args[random_string(1000)] = random_string(1000); - } - - ASSERT_NO_THROW({ - const string response = - network.request("http://" + test_server + "/post", args, true); - const auto resp = json::parse(response); - - for (const auto& arg : args) { - ASSERT_EQ(resp["form"][arg.first], arg.second); - } - }); -} - -TEST(OldRequest, Post_SSL_Random_MultipleArgs) { - using namespace wtlgo::old; - using json = nlohmann::json; - using string = std::string; - using map = std::map; - - map args; - for (size_t i = 0; i < 10; ++i) { - args[random_string(1000)] = random_string(1000); - } - - const string response = - network.request("https://" + test_server + "/post", args, true); - - ASSERT_NO_THROW({ - const auto resp = json::parse(response); - - for (const auto& arg : args) { - ASSERT_EQ(resp["form"][arg.first], arg.second); - } - }); -} diff --git a/test/src/OldSanityTest.cpp b/test/src/OldSanityTest.cpp deleted file mode 100644 index f8a5cd8..0000000 --- a/test/src/OldSanityTest.cpp +++ /dev/null @@ -1,7 +0,0 @@ -#include -#include - -TEST(OldSanityCheck, DidInit) { - using namespace wtlgo::old; - ASSERT_EQ(&network, &Network::instance()); -} From 51aa92165f615a8892ca8802c8e9aede0fb6d1e0 Mon Sep 17 00:00:00 2001 From: wtlgo Date: Mon, 23 Jan 2023 16:18:02 +0300 Subject: [PATCH 17/46] Make destructor virtual --- include/wtlgo/network/DefaultHttpBasicAuth.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/wtlgo/network/DefaultHttpBasicAuth.hpp b/include/wtlgo/network/DefaultHttpBasicAuth.hpp index f18733d..88f46d3 100644 --- a/include/wtlgo/network/DefaultHttpBasicAuth.hpp +++ b/include/wtlgo/network/DefaultHttpBasicAuth.hpp @@ -14,7 +14,7 @@ class DefaultHttpBasicAuth using sptr_t = std::shared_ptr; using csptr_t = std::shared_ptr; - ~DefaultHttpBasicAuth(); + virtual ~DefaultHttpBasicAuth(); [[nodiscard]] static DefaultHttpBasicAuth::sptr_t create( HttpBasicAuth::username_ref_t username, From 963eb3322d050b7014ac6ac383f9daec5def46f5 Mon Sep 17 00:00:00 2001 From: wtlgo Date: Mon, 23 Jan 2023 16:35:39 +0300 Subject: [PATCH 18/46] Rename sptr_t to ptr_t --- include/wtlgo/network/DefaultHttpBasicAuth.hpp | 12 ++++++------ include/wtlgo/network/HttpBasicAuth.hpp | 10 +++++----- src/DefaultHttpBasicAuth.cpp | 8 ++++---- test/src/DefaultHttpBasicAuth.cpp | 6 +++--- 4 files changed, 18 insertions(+), 18 deletions(-) diff --git a/include/wtlgo/network/DefaultHttpBasicAuth.hpp b/include/wtlgo/network/DefaultHttpBasicAuth.hpp index 88f46d3..9304e52 100644 --- a/include/wtlgo/network/DefaultHttpBasicAuth.hpp +++ b/include/wtlgo/network/DefaultHttpBasicAuth.hpp @@ -11,22 +11,22 @@ class DefaultHttpBasicAuth : public HttpBasicAuth, public std::enable_shared_from_this { public: - using sptr_t = std::shared_ptr; - using csptr_t = std::shared_ptr; + using ptr_t = std::shared_ptr; + using cptr_t = std::shared_ptr; virtual ~DefaultHttpBasicAuth(); - [[nodiscard]] static DefaultHttpBasicAuth::sptr_t create( + [[nodiscard]] static DefaultHttpBasicAuth::ptr_t create( HttpBasicAuth::username_ref_t username, HttpBasicAuth::password_ref_t password); - HttpBasicAuth::sptr_t clone() const override; + HttpBasicAuth::ptr_t clone() const override; HttpBasicAuth::username_ref_t username() const override; - HttpBasicAuth::sptr_t username(HttpBasicAuth::username_ref_t) override; + HttpBasicAuth::ptr_t username(HttpBasicAuth::username_ref_t) override; HttpBasicAuth::password_ref_t password() const override; - HttpBasicAuth::sptr_t password(HttpBasicAuth::password_ref_t) override; + HttpBasicAuth::ptr_t password(HttpBasicAuth::password_ref_t) override; protected: DefaultHttpBasicAuth(HttpBasicAuth::username_ref_t username, diff --git a/include/wtlgo/network/HttpBasicAuth.hpp b/include/wtlgo/network/HttpBasicAuth.hpp index a4e9d05..8bf510a 100644 --- a/include/wtlgo/network/HttpBasicAuth.hpp +++ b/include/wtlgo/network/HttpBasicAuth.hpp @@ -7,21 +7,21 @@ namespace wtlgo { namespace network { struct HttpBasicAuth { - using sptr_t = std::shared_ptr; - using csptr_t = std::shared_ptr; + using ptr_t = std::shared_ptr; + using cptr_t = std::shared_ptr; using username_ref_t = std::string_view; using password_ref_t = std::string_view; virtual ~HttpBasicAuth() = default; - virtual sptr_t clone() const = 0; + virtual ptr_t clone() const = 0; virtual username_ref_t username() const = 0; - virtual sptr_t username(username_ref_t) = 0; + virtual ptr_t username(username_ref_t) = 0; virtual password_ref_t password() const = 0; - virtual sptr_t password(password_ref_t) = 0; + virtual ptr_t password(password_ref_t) = 0; }; } } diff --git a/src/DefaultHttpBasicAuth.cpp b/src/DefaultHttpBasicAuth.cpp index 3dcb9e4..260a77e 100644 --- a/src/DefaultHttpBasicAuth.cpp +++ b/src/DefaultHttpBasicAuth.cpp @@ -32,14 +32,14 @@ struct DefaultHttpBasicAuth::Impl { DefaultHttpBasicAuth::~DefaultHttpBasicAuth() = default; -DefaultHttpBasicAuth::sptr_t DefaultHttpBasicAuth::create( +DefaultHttpBasicAuth::ptr_t DefaultHttpBasicAuth::create( const HttpBasicAuth::username_ref_t username, const HttpBasicAuth::password_ref_t password) { return std::shared_ptr( new DefaultHttpBasicAuth{username, password}); } -HttpBasicAuth::sptr_t DefaultHttpBasicAuth::clone() const { +HttpBasicAuth::ptr_t DefaultHttpBasicAuth::clone() const { return std::shared_ptr( new DefaultHttpBasicAuth{impl}); } @@ -48,7 +48,7 @@ HttpBasicAuth::username_ref_t DefaultHttpBasicAuth::username() const { return impl->username(); } -HttpBasicAuth::sptr_t DefaultHttpBasicAuth::username( +HttpBasicAuth::ptr_t DefaultHttpBasicAuth::username( const HttpBasicAuth::username_ref_t username) { impl->username(username); return shared_from_this(); @@ -58,7 +58,7 @@ HttpBasicAuth::password_ref_t DefaultHttpBasicAuth::password() const { return impl->password(); } -HttpBasicAuth::sptr_t DefaultHttpBasicAuth::password( +HttpBasicAuth::ptr_t DefaultHttpBasicAuth::password( const HttpBasicAuth::password_ref_t password) { impl->password(password); return shared_from_this(); diff --git a/test/src/DefaultHttpBasicAuth.cpp b/test/src/DefaultHttpBasicAuth.cpp index ec3d516..e5da1d0 100644 --- a/test/src/DefaultHttpBasicAuth.cpp +++ b/test/src/DefaultHttpBasicAuth.cpp @@ -12,7 +12,7 @@ TEST(DefaultHttpBasicAuth, Create) { const std::string test_username = random_string(50); const std::string test_password = random_string(50); - const HttpBasicAuth::csptr_t client = + const HttpBasicAuth::cptr_t client = DefaultHttpBasicAuth::create(test_username, test_password); ASSERT_NE(client, nullptr); @@ -23,7 +23,7 @@ TEST(DefaultHttpBasicAuth, Create) { TEST(DefaultHttpBasicAuth, SetUsername) { using namespace wtlgo::network; - const HttpBasicAuth::sptr_t client = + const HttpBasicAuth::ptr_t client = DefaultHttpBasicAuth::create(random_string(50), random_string(50)); ASSERT_NE(client, nullptr); @@ -35,7 +35,7 @@ TEST(DefaultHttpBasicAuth, SetUsername) { TEST(DefaultHttpBasicAuth, SetPassword) { using namespace wtlgo::network; - const HttpBasicAuth::sptr_t client = + const HttpBasicAuth::ptr_t client = DefaultHttpBasicAuth::create(random_string(50), random_string(50)); ASSERT_NE(client, nullptr); From 56d16178eebbc12efea7d87789a2b8f944e4776d Mon Sep 17 00:00:00 2001 From: wtlgo Date: Mon, 23 Jan 2023 16:57:47 +0300 Subject: [PATCH 19/46] Add HttpMethod --- CMakeLists.txt | 2 ++ include/wtlgo/network/HttpMethod.hpp | 10 ++++++++++ 2 files changed, 12 insertions(+) create mode 100644 include/wtlgo/network/HttpMethod.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 972f3f5..03dae3a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,6 +15,8 @@ set(PUBLIC_HEADERS "include/wtlgo/network/HttpBasicAuth.hpp" "include/wtlgo/network/DefaultHttpBasicAuth.hpp" + + "include/wtlgo/network/HttpMethod.hpp" ) set(SOURCES diff --git a/include/wtlgo/network/HttpMethod.hpp b/include/wtlgo/network/HttpMethod.hpp new file mode 100644 index 0000000..dc80544 --- /dev/null +++ b/include/wtlgo/network/HttpMethod.hpp @@ -0,0 +1,10 @@ +#ifndef __WTLGO__NETWORK__DEFAULT_HTTP_METHOD__ +#define __WTLGO__NETWORK__DEFAULT_HTTP_METHOD__ + +namespace wtlgo { +namespace network { +enum class HttpMethod { GET, POST, PUT, PATCH, DELETE }; +} +} + +#endif From 38be01762bce4068d7fdad45b52f539d6f57e343 Mon Sep 17 00:00:00 2001 From: wtlgo Date: Mon, 23 Jan 2023 17:24:18 +0300 Subject: [PATCH 20/46] Add Config --- CMakeLists.txt | 4 +++ include/wtlgo/network/Config.hpp | 18 +++++++++++++ include/wtlgo/network/DefaultConfig.hpp | 34 +++++++++++++++++++++++++ src/DefaultConfig.cpp | 23 +++++++++++++++++ test/src/DefaultConfig.cpp | 11 ++++++++ 5 files changed, 90 insertions(+) create mode 100644 include/wtlgo/network/Config.hpp create mode 100644 include/wtlgo/network/DefaultConfig.hpp create mode 100644 src/DefaultConfig.cpp create mode 100644 test/src/DefaultConfig.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 03dae3a..17c1bc9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,11 +17,15 @@ set(PUBLIC_HEADERS "include/wtlgo/network/DefaultHttpBasicAuth.hpp" "include/wtlgo/network/HttpMethod.hpp" + + "include/wtlgo/network/Config.hpp" + "include/wtlgo/network/DefaultConfig.hpp" ) set(SOURCES "src/NetworkOld.cpp" "src/DefaultHttpBasicAuth.cpp" + "src/DefaultConfig.cpp" ) add_library(Network ${SOURCES}) diff --git a/include/wtlgo/network/Config.hpp b/include/wtlgo/network/Config.hpp new file mode 100644 index 0000000..0dbc9e7 --- /dev/null +++ b/include/wtlgo/network/Config.hpp @@ -0,0 +1,18 @@ +#ifndef __WTLGO__NETWORK__CONFIG__ +#define __WTLGO__NETWORK__CONFIG__ + +#include + +namespace wtlgo { +namespace network { +struct Config { + using ptr_t = std::shared_ptr; + using cptr_t = std::shared_ptr; + + virtual ~Config() = default; + virtual ptr_t clone() const = 0; +}; +} +} + +#endif diff --git a/include/wtlgo/network/DefaultConfig.hpp b/include/wtlgo/network/DefaultConfig.hpp new file mode 100644 index 0000000..49392f5 --- /dev/null +++ b/include/wtlgo/network/DefaultConfig.hpp @@ -0,0 +1,34 @@ +#ifndef __WTLGO__NETWORK__DEFAULT_CONFIG__ +#define __WTLGO__NETWORK__DEFAULT_CONFIG__ + +#include + +#include + +namespace wtlgo { +namespace network { +class DefaultConfig : public Config, + public std::enable_shared_from_this { +public: + using ptr_t = std::shared_ptr; + using cptr_t = std::shared_ptr; + + virtual ~DefaultConfig(); + + [[nodiscard]] static DefaultConfig::ptr_t create(); + + Config::ptr_t clone() const override; + +protected: + DefaultConfig(); + +private: + struct Impl; + const std::unique_ptr impl; + + DefaultConfig(const std::unique_ptr&); +}; +} +} + +#endif diff --git a/src/DefaultConfig.cpp b/src/DefaultConfig.cpp new file mode 100644 index 0000000..d6bba03 --- /dev/null +++ b/src/DefaultConfig.cpp @@ -0,0 +1,23 @@ +#include + +#include +#include + +using namespace wtlgo::network; + +struct DefaultConfig::Impl {}; + +DefaultConfig::~DefaultConfig() = default; + +DefaultConfig::ptr_t DefaultConfig::create() { + return std::shared_ptr{new DefaultConfig{}}; +} + +Config::ptr_t DefaultConfig::clone() const { + return std::shared_ptr{new DefaultConfig{impl}}; +} + +DefaultConfig::DefaultConfig() : impl{std::make_unique()} {} + +DefaultConfig::DefaultConfig(const std::unique_ptr& impl) + : impl{std::make_unique(*impl)} {} diff --git a/test/src/DefaultConfig.cpp b/test/src/DefaultConfig.cpp new file mode 100644 index 0000000..636777c --- /dev/null +++ b/test/src/DefaultConfig.cpp @@ -0,0 +1,11 @@ +#include + +#include +#include + +TEST(DefaultConfig, Create) { + using namespace wtlgo::network; + + const Config::cptr_t config = DefaultConfig::create(); + ASSERT_NE(config, nullptr); +} From a51ff2b6cae6442bb15e2c8d09f3390843ecf6ac Mon Sep 17 00:00:00 2001 From: wtlgo Date: Mon, 23 Jan 2023 17:28:11 +0300 Subject: [PATCH 21/46] Add DefaultHttpBasicAuth.Clone test --- test/src/DefaultHttpBasicAuth.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/test/src/DefaultHttpBasicAuth.cpp b/test/src/DefaultHttpBasicAuth.cpp index e5da1d0..b2d529c 100644 --- a/test/src/DefaultHttpBasicAuth.cpp +++ b/test/src/DefaultHttpBasicAuth.cpp @@ -20,6 +20,21 @@ TEST(DefaultHttpBasicAuth, Create) { ASSERT_EQ(client->password(), test_password); } +TEST(DefaultHttpBasicAuth, Clone) { + using namespace wtlgo::network; + + const HttpBasicAuth::cptr_t client = + DefaultHttpBasicAuth::create(random_string(50), random_string(50)); + ASSERT_NE(client, nullptr); + + const HttpBasicAuth::cptr_t clone = client->clone(); + ASSERT_NE(clone, nullptr); + ASSERT_NE(clone, client); + + ASSERT_EQ(client->username(), clone->username()); + ASSERT_EQ(client->password(), clone->password()); +} + TEST(DefaultHttpBasicAuth, SetUsername) { using namespace wtlgo::network; From 99ef73191f199e76ab3291ad7324a063617603a2 Mon Sep 17 00:00:00 2001 From: wtlgo Date: Mon, 23 Jan 2023 17:31:58 +0300 Subject: [PATCH 22/46] Update DefaultHttpBasicAuth.Clone --- test/src/DefaultHttpBasicAuth.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/src/DefaultHttpBasicAuth.cpp b/test/src/DefaultHttpBasicAuth.cpp index b2d529c..ec0096f 100644 --- a/test/src/DefaultHttpBasicAuth.cpp +++ b/test/src/DefaultHttpBasicAuth.cpp @@ -32,7 +32,10 @@ TEST(DefaultHttpBasicAuth, Clone) { ASSERT_NE(clone, client); ASSERT_EQ(client->username(), clone->username()); + ASSERT_NE(client->username().data(), clone->username().data()); + ASSERT_EQ(client->password(), clone->password()); + ASSERT_NE(client->password().data(), clone->password().data()); } TEST(DefaultHttpBasicAuth, SetUsername) { From 50e83a0fbffd9e91d19af280d7e56f71998e138c Mon Sep 17 00:00:00 2001 From: wtlgo Date: Mon, 23 Jan 2023 17:37:28 +0300 Subject: [PATCH 23/46] Add DefaultConfig.Clone test --- test/src/DefaultConfig.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/test/src/DefaultConfig.cpp b/test/src/DefaultConfig.cpp index 636777c..94a3b4d 100644 --- a/test/src/DefaultConfig.cpp +++ b/test/src/DefaultConfig.cpp @@ -9,3 +9,14 @@ TEST(DefaultConfig, Create) { const Config::cptr_t config = DefaultConfig::create(); ASSERT_NE(config, nullptr); } + +TEST(DefaultConfig, Clone) { + using namespace wtlgo::network; + + const Config::cptr_t config = DefaultConfig::create(); + ASSERT_NE(config, nullptr); + + const Config::cptr_t clone = config->clone(); + ASSERT_NE(clone, nullptr); + ASSERT_NE(clone, config); +} \ No newline at end of file From de5f0d3261c46369117d11163858d1b4a0373d1c Mon Sep 17 00:00:00 2001 From: wtlgo Date: Mon, 23 Jan 2023 17:38:42 +0300 Subject: [PATCH 24/46] Remove unnecessary assertions --- test/src/DefaultConfig.cpp | 3 +-- test/src/DefaultHttpBasicAuth.cpp | 3 --- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/test/src/DefaultConfig.cpp b/test/src/DefaultConfig.cpp index 94a3b4d..ab12ce1 100644 --- a/test/src/DefaultConfig.cpp +++ b/test/src/DefaultConfig.cpp @@ -14,9 +14,8 @@ TEST(DefaultConfig, Clone) { using namespace wtlgo::network; const Config::cptr_t config = DefaultConfig::create(); - ASSERT_NE(config, nullptr); const Config::cptr_t clone = config->clone(); ASSERT_NE(clone, nullptr); ASSERT_NE(clone, config); -} \ No newline at end of file +} diff --git a/test/src/DefaultHttpBasicAuth.cpp b/test/src/DefaultHttpBasicAuth.cpp index ec0096f..3c459c1 100644 --- a/test/src/DefaultHttpBasicAuth.cpp +++ b/test/src/DefaultHttpBasicAuth.cpp @@ -25,7 +25,6 @@ TEST(DefaultHttpBasicAuth, Clone) { const HttpBasicAuth::cptr_t client = DefaultHttpBasicAuth::create(random_string(50), random_string(50)); - ASSERT_NE(client, nullptr); const HttpBasicAuth::cptr_t clone = client->clone(); ASSERT_NE(clone, nullptr); @@ -43,7 +42,6 @@ TEST(DefaultHttpBasicAuth, SetUsername) { const HttpBasicAuth::ptr_t client = DefaultHttpBasicAuth::create(random_string(50), random_string(50)); - ASSERT_NE(client, nullptr); const std::string test_username = random_string(50); ASSERT_EQ(client, client->username(test_username)); @@ -55,7 +53,6 @@ TEST(DefaultHttpBasicAuth, SetPassword) { const HttpBasicAuth::ptr_t client = DefaultHttpBasicAuth::create(random_string(50), random_string(50)); - ASSERT_NE(client, nullptr); const std::string test_password = random_string(50); ASSERT_EQ(client, client->password(test_password)); From ef528f08f05ed9dd8b90d09bf91d8ca47dd20f0e Mon Sep 17 00:00:00 2001 From: wtlgo Date: Mon, 23 Jan 2023 18:02:32 +0300 Subject: [PATCH 25/46] Add Url --- include/wtlgo/network/Config.hpp | 9 +++++ include/wtlgo/network/DefaultConfig.hpp | 4 +++ src/DefaultConfig.cpp | 24 ++++++++++++- test/src/DefaultConfig.cpp | 45 +++++++++++++++++++++++++ 4 files changed, 81 insertions(+), 1 deletion(-) diff --git a/include/wtlgo/network/Config.hpp b/include/wtlgo/network/Config.hpp index 0dbc9e7..6323403 100644 --- a/include/wtlgo/network/Config.hpp +++ b/include/wtlgo/network/Config.hpp @@ -2,6 +2,8 @@ #define __WTLGO__NETWORK__CONFIG__ #include +#include +#include namespace wtlgo { namespace network { @@ -11,6 +13,13 @@ struct Config { virtual ~Config() = default; virtual ptr_t clone() const = 0; + + using url_ref_t = std::string_view; + using url_opt_ref_t = std::optional; + + virtual url_opt_ref_t url() const = 0; + virtual ptr_t url(url_ref_t) = 0; + virtual ptr_t clear_url() = 0; }; } } diff --git a/include/wtlgo/network/DefaultConfig.hpp b/include/wtlgo/network/DefaultConfig.hpp index 49392f5..7268ff8 100644 --- a/include/wtlgo/network/DefaultConfig.hpp +++ b/include/wtlgo/network/DefaultConfig.hpp @@ -19,6 +19,10 @@ class DefaultConfig : public Config, Config::ptr_t clone() const override; + Config::url_opt_ref_t url() const; + Config::ptr_t url(Config::url_ref_t); + Config::ptr_t clear_url(); + protected: DefaultConfig(); diff --git a/src/DefaultConfig.cpp b/src/DefaultConfig.cpp index d6bba03..4cb0fdd 100644 --- a/src/DefaultConfig.cpp +++ b/src/DefaultConfig.cpp @@ -1,11 +1,21 @@ #include +#include +#include #include #include using namespace wtlgo::network; -struct DefaultConfig::Impl {}; +struct DefaultConfig::Impl { +private: + std::optional _url; + +public: + Config::url_opt_ref_t url() const { return _url; } + void url(const Config::url_ref_t url) { _url = url; } + void clear_url() { _url = std::nullopt; } +}; DefaultConfig::~DefaultConfig() = default; @@ -17,6 +27,18 @@ Config::ptr_t DefaultConfig::clone() const { return std::shared_ptr{new DefaultConfig{impl}}; } +Config::url_opt_ref_t DefaultConfig::url() const { return impl->url(); } + +Config::ptr_t DefaultConfig::url(const Config::url_ref_t url) { + impl->url(url); + return shared_from_this(); +} + +Config::ptr_t DefaultConfig::clear_url() { + impl->clear_url(); + return shared_from_this(); +} + DefaultConfig::DefaultConfig() : impl{std::make_unique()} {} DefaultConfig::DefaultConfig(const std::unique_ptr& impl) diff --git a/test/src/DefaultConfig.cpp b/test/src/DefaultConfig.cpp index ab12ce1..58f437c 100644 --- a/test/src/DefaultConfig.cpp +++ b/test/src/DefaultConfig.cpp @@ -1,4 +1,8 @@ #include +#include "utility.hpp" + +#include +#include #include #include @@ -19,3 +23,44 @@ TEST(DefaultConfig, Clone) { ASSERT_NE(clone, nullptr); ASSERT_NE(clone, config); } + +TEST(DefaultConfig, UrlSet) { + using namespace wtlgo::network; + + const Config::ptr_t config = DefaultConfig::create(); + + const std::string test_url = random_string(50); + + ASSERT_EQ(config, config->url(test_url)); + ASSERT_EQ(config->url(), test_url); +} + +TEST(DefaultConfig, UrlClear) { + using namespace wtlgo::network; + + const Config::ptr_t config = + DefaultConfig::create()->url(random_string(50)); + + ASSERT_EQ(config, config->clear_url()); + ASSERT_EQ(config->url(), std::nullopt); +} + +TEST(DefaultConfig, UrlCloneEmpty) { + using namespace wtlgo::network; + + const Config::cptr_t config = DefaultConfig::create()->clear_url(); + const Config::cptr_t clone = config->clone(); + + ASSERT_EQ(clone->url(), std::nullopt); +} + +TEST(DefaultConfig, UrlCloneValue) { + using namespace wtlgo::network; + + const Config::cptr_t config = + DefaultConfig::create()->url(random_string(50)); + const Config::cptr_t clone = config->clone(); + + ASSERT_EQ(clone->url(), config->url()); + ASSERT_NE(clone->url().value().data(), config->url().value().data()); +} From b2120b5d482d97a026001293fabe3ebe879d3d41 Mon Sep 17 00:00:00 2001 From: wtlgo Date: Mon, 23 Jan 2023 18:35:53 +0300 Subject: [PATCH 26/46] Add merge to Config --- include/wtlgo/network/Config.hpp | 4 +- include/wtlgo/network/DefaultConfig.hpp | 2 + src/DefaultConfig.cpp | 24 +++++++++ test/src/DefaultConfig.cpp | 71 ++++++++++++++++++++++++- 4 files changed, 99 insertions(+), 2 deletions(-) diff --git a/include/wtlgo/network/Config.hpp b/include/wtlgo/network/Config.hpp index 6323403..aef621d 100644 --- a/include/wtlgo/network/Config.hpp +++ b/include/wtlgo/network/Config.hpp @@ -12,7 +12,9 @@ struct Config { using cptr_t = std::shared_ptr; virtual ~Config() = default; - virtual ptr_t clone() const = 0; + + [[nodiscard]] virtual ptr_t clone() const = 0; + [[nodiscard]] virtual ptr_t merge(cptr_t) const = 0; using url_ref_t = std::string_view; using url_opt_ref_t = std::optional; diff --git a/include/wtlgo/network/DefaultConfig.hpp b/include/wtlgo/network/DefaultConfig.hpp index 7268ff8..5aba375 100644 --- a/include/wtlgo/network/DefaultConfig.hpp +++ b/include/wtlgo/network/DefaultConfig.hpp @@ -18,6 +18,7 @@ class DefaultConfig : public Config, [[nodiscard]] static DefaultConfig::ptr_t create(); Config::ptr_t clone() const override; + Config::ptr_t merge(Config::cptr_t) const override; Config::url_opt_ref_t url() const; Config::ptr_t url(Config::url_ref_t); @@ -31,6 +32,7 @@ class DefaultConfig : public Config, const std::unique_ptr impl; DefaultConfig(const std::unique_ptr&); + DefaultConfig(std::unique_ptr&&); }; } } diff --git a/src/DefaultConfig.cpp b/src/DefaultConfig.cpp index 4cb0fdd..95245c5 100644 --- a/src/DefaultConfig.cpp +++ b/src/DefaultConfig.cpp @@ -1,6 +1,8 @@ #include #include #include +#include +#include #include #include @@ -12,6 +14,20 @@ struct DefaultConfig::Impl { std::optional _url; public: + std::unique_ptr merge(const Config::cptr_t rconfig) const { + if (rconfig == nullptr) { + throw std::invalid_argument{"nullptr is provided!"}; + } + + auto res = std::make_unique(*this); + + if (rconfig->url()) { + res->_url = rconfig->url(); + } + + return res; + } + Config::url_opt_ref_t url() const { return _url; } void url(const Config::url_ref_t url) { _url = url; } void clear_url() { _url = std::nullopt; } @@ -27,6 +43,11 @@ Config::ptr_t DefaultConfig::clone() const { return std::shared_ptr{new DefaultConfig{impl}}; } +Config::ptr_t DefaultConfig::merge(const Config::cptr_t rconfig) const { + return std::shared_ptr{ + new DefaultConfig{impl->merge(rconfig)}}; +} + Config::url_opt_ref_t DefaultConfig::url() const { return impl->url(); } Config::ptr_t DefaultConfig::url(const Config::url_ref_t url) { @@ -43,3 +64,6 @@ DefaultConfig::DefaultConfig() : impl{std::make_unique()} {} DefaultConfig::DefaultConfig(const std::unique_ptr& impl) : impl{std::make_unique(*impl)} {} + +DefaultConfig::DefaultConfig(std::unique_ptr&& impl) + : impl{std::move(impl)} {} diff --git a/test/src/DefaultConfig.cpp b/test/src/DefaultConfig.cpp index 58f437c..d7c99fd 100644 --- a/test/src/DefaultConfig.cpp +++ b/test/src/DefaultConfig.cpp @@ -3,6 +3,7 @@ #include #include +#include #include #include @@ -24,6 +25,27 @@ TEST(DefaultConfig, Clone) { ASSERT_NE(clone, config); } +TEST(DefaultConfig, Merge) { + using namespace wtlgo::network; + + const Config::cptr_t lconfig = DefaultConfig::create(); + const Config::cptr_t rconfig = DefaultConfig::create(); + const Config::cptr_t mconfig = lconfig->merge(rconfig); + + ASSERT_NE(mconfig, nullptr); + ASSERT_NE(mconfig, lconfig); + ASSERT_NE(mconfig, lconfig); +} + +TEST(DefaultConfig, MergeFail) { + using namespace wtlgo::network; + + const Config::cptr_t config = DefaultConfig::create(); + + Config::cptr_t mconfig; + ASSERT_THROW(mconfig = config->merge(nullptr), std::invalid_argument); +} + TEST(DefaultConfig, UrlSet) { using namespace wtlgo::network; @@ -62,5 +84,52 @@ TEST(DefaultConfig, UrlCloneValue) { const Config::cptr_t clone = config->clone(); ASSERT_EQ(clone->url(), config->url()); - ASSERT_NE(clone->url().value().data(), config->url().value().data()); + ASSERT_NE(clone->url()->data(), config->url()->data()); +} + +TEST(DefaultConfig, UrlMergeEmpty) { + using namespace wtlgo::network; + + const Config::cptr_t lconfig = DefaultConfig::create()->clear_url(); + const Config::cptr_t rconfig = DefaultConfig::create()->clear_url(); + const Config::cptr_t mconfig = lconfig->merge(rconfig); + + ASSERT_EQ(mconfig->url(), std::nullopt); +} + +TEST(DefaultConfig, UrlMergeRight) { + using namespace wtlgo::network; + + const Config::cptr_t lconfig = DefaultConfig::create()->clear_url(); + const Config::cptr_t rconfig = + DefaultConfig::create()->url(random_string(50)); + const Config::cptr_t mconfig = lconfig->merge(rconfig); + + ASSERT_EQ(mconfig->url(), rconfig->url()); + ASSERT_NE(mconfig->url()->data(), rconfig->url()->data()); +} + +TEST(DefaultConfig, UrlMergeLeft) { + using namespace wtlgo::network; + + const Config::cptr_t lconfig = + DefaultConfig::create()->url(random_string(50)); + const Config::cptr_t rconfig = DefaultConfig::create()->clear_url(); + const Config::cptr_t mconfig = lconfig->merge(rconfig); + + ASSERT_EQ(mconfig->url(), lconfig->url()); + ASSERT_NE(mconfig->url()->data(), lconfig->url()->data()); +} + +TEST(DefaultConfig, UrlMergeFull) { + using namespace wtlgo::network; + + const Config::cptr_t lconfig = + DefaultConfig::create()->url(random_string(50)); + const Config::cptr_t rconfig = + DefaultConfig::create()->url(random_string(50)); + const Config::cptr_t mconfig = lconfig->merge(rconfig); + + ASSERT_EQ(mconfig->url(), rconfig->url()); + ASSERT_NE(mconfig->url()->data(), rconfig->url()->data()); } From fd3a27a46a8fc61e89939eb1816f0121e854b379 Mon Sep 17 00:00:00 2001 From: wtlgo Date: Mon, 23 Jan 2023 18:37:10 +0300 Subject: [PATCH 27/46] Add alias to DefaultConfig --- include/wtlgo/network/DefaultConfig.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/wtlgo/network/DefaultConfig.hpp b/include/wtlgo/network/DefaultConfig.hpp index 5aba375..541cdf0 100644 --- a/include/wtlgo/network/DefaultConfig.hpp +++ b/include/wtlgo/network/DefaultConfig.hpp @@ -34,6 +34,8 @@ class DefaultConfig : public Config, DefaultConfig(const std::unique_ptr&); DefaultConfig(std::unique_ptr&&); }; + +using DConfig = DefaultConfig; } } From 1cc2572e765919a81b4149435675c90a43d76c0f Mon Sep 17 00:00:00 2001 From: wtlgo Date: Mon, 23 Jan 2023 20:31:22 +0300 Subject: [PATCH 28/46] Factor out merge and copy shenenigans --- CMakeLists.txt | 6 +++ include/wtlgo/network/DefaultConfig.hpp | 5 +- src/DefaultConfig.cpp | 22 +++++---- src/internal/CopyOnWriteConfig.cpp | 63 ++++++++++++++++++++++++ src/internal/CopyOnWriteConfig.hpp | 39 +++++++++++++++ src/internal/MergedConfig.cpp | 65 +++++++++++++++++++++++++ src/internal/MergedConfig.hpp | 39 +++++++++++++++ test/src/DefaultConfig.cpp | 12 ----- 8 files changed, 227 insertions(+), 24 deletions(-) create mode 100644 src/internal/CopyOnWriteConfig.cpp create mode 100644 src/internal/CopyOnWriteConfig.hpp create mode 100644 src/internal/MergedConfig.cpp create mode 100644 src/internal/MergedConfig.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 17c1bc9..76cb9c6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -26,6 +26,12 @@ set(SOURCES "src/NetworkOld.cpp" "src/DefaultHttpBasicAuth.cpp" "src/DefaultConfig.cpp" + + "src/internal/MergedConfig.hpp" + "src/internal/MergedConfig.cpp" + + "src/internal/CopyOnWriteConfig.hpp" + "src/internal/CopyOnWriteConfig.cpp" ) add_library(Network ${SOURCES}) diff --git a/include/wtlgo/network/DefaultConfig.hpp b/include/wtlgo/network/DefaultConfig.hpp index 541cdf0..52bb3bc 100644 --- a/include/wtlgo/network/DefaultConfig.hpp +++ b/include/wtlgo/network/DefaultConfig.hpp @@ -16,6 +16,7 @@ class DefaultConfig : public Config, virtual ~DefaultConfig(); [[nodiscard]] static DefaultConfig::ptr_t create(); + [[nodiscard]] static DefaultConfig::ptr_t clone(Config::cptr_t); Config::ptr_t clone() const override; Config::ptr_t merge(Config::cptr_t) const override; @@ -26,13 +27,11 @@ class DefaultConfig : public Config, protected: DefaultConfig(); + DefaultConfig(const Config::cptr_t); private: struct Impl; const std::unique_ptr impl; - - DefaultConfig(const std::unique_ptr&); - DefaultConfig(std::unique_ptr&&); }; using DConfig = DefaultConfig; diff --git a/src/DefaultConfig.cpp b/src/DefaultConfig.cpp index 95245c5..1bd11bf 100644 --- a/src/DefaultConfig.cpp +++ b/src/DefaultConfig.cpp @@ -4,6 +4,8 @@ #include #include +#include "./internal/MergedConfig.hpp" + #include #include @@ -14,6 +16,10 @@ struct DefaultConfig::Impl { std::optional _url; public: + Impl() = default; + Impl(const Impl&) = default; + Impl(const Config::cptr_t config) : _url{config->url()} {} + std::unique_ptr merge(const Config::cptr_t rconfig) const { if (rconfig == nullptr) { throw std::invalid_argument{"nullptr is provided!"}; @@ -39,13 +45,14 @@ DefaultConfig::ptr_t DefaultConfig::create() { return std::shared_ptr{new DefaultConfig{}}; } -Config::ptr_t DefaultConfig::clone() const { - return std::shared_ptr{new DefaultConfig{impl}}; +DefaultConfig::ptr_t DefaultConfig::clone(const Config::cptr_t config) { + return std::shared_ptr{new DefaultConfig{config}}; } +Config::ptr_t DefaultConfig::clone() const { return clone(shared_from_this()); } + Config::ptr_t DefaultConfig::merge(const Config::cptr_t rconfig) const { - return std::shared_ptr{ - new DefaultConfig{impl->merge(rconfig)}}; + return internal::MergedConfig::merge(shared_from_this(), rconfig); } Config::url_opt_ref_t DefaultConfig::url() const { return impl->url(); } @@ -62,8 +69,5 @@ Config::ptr_t DefaultConfig::clear_url() { DefaultConfig::DefaultConfig() : impl{std::make_unique()} {} -DefaultConfig::DefaultConfig(const std::unique_ptr& impl) - : impl{std::make_unique(*impl)} {} - -DefaultConfig::DefaultConfig(std::unique_ptr&& impl) - : impl{std::move(impl)} {} +DefaultConfig::DefaultConfig(const Config::cptr_t config) + : impl{std::make_unique(config)} {} diff --git a/src/internal/CopyOnWriteConfig.cpp b/src/internal/CopyOnWriteConfig.cpp new file mode 100644 index 0000000..2e1e8c6 --- /dev/null +++ b/src/internal/CopyOnWriteConfig.cpp @@ -0,0 +1,63 @@ +#include + +#include +#include "./MergedConfig.hpp" + +#include "./CopyOnWriteConfig.hpp" + +using namespace wtlgo::network; +using namespace wtlgo::network::internal; + +struct CopyOnWriteConfig::Impl { +private: + Config::cptr_t solid; + Config::ptr_t liquid; + + void solidify() { + if (!solid) return; + + liquid = DefaultConfig::clone(solid); + solid = nullptr; + } + + Config::cptr_t cptr() const { return solid ? solid : liquid; } + Config::ptr_t ptr() { + solidify(); + return liquid; + } + +public: + Impl(const Config::cptr_t config) : solid{config}, liquid{nullptr} {} + + Config::url_opt_ref_t url() const { return cptr()->url(); } + void url(const Config::url_ref_t url) { ptr()->url(url); } + void clear_url() { ptr()->clear_url(); } +}; + +CopyOnWriteConfig::~CopyOnWriteConfig() = default; + +CopyOnWriteConfig::ptr_t CopyOnWriteConfig::adapt(const Config::cptr_t config) { + return std::shared_ptr{new CopyOnWriteConfig{config}}; +} + +Config::ptr_t CopyOnWriteConfig::clone() const { + return DefaultConfig::clone(shared_from_this()); +} + +Config::ptr_t CopyOnWriteConfig::merge(const Config::cptr_t rconfig) const { + return MergedConfig::merge(shared_from_this(), rconfig); +} + +Config::url_opt_ref_t CopyOnWriteConfig::url() const { return impl->url(); } +Config::ptr_t CopyOnWriteConfig::url(const Config::url_ref_t url) { + impl->url(url); + return shared_from_this(); +} + +Config::ptr_t CopyOnWriteConfig::clear_url() { + impl->clear_url(); + return shared_from_this(); +} + +CopyOnWriteConfig::CopyOnWriteConfig(const Config::cptr_t config) + : impl{std::make_unique(config)} {} diff --git a/src/internal/CopyOnWriteConfig.hpp b/src/internal/CopyOnWriteConfig.hpp new file mode 100644 index 0000000..82630ab --- /dev/null +++ b/src/internal/CopyOnWriteConfig.hpp @@ -0,0 +1,39 @@ +#ifndef __WTLGO__NETWORK__INTERNAL__COPY_ON_WRITE_CONFIG__ +#define __WTLGO__NETWORK__INTERNAL__COPY_ON_WRITE_CONFIG__ + +#include +#include + +namespace wtlgo { +namespace network { +namespace internal { +class CopyOnWriteConfig + : public Config, + public std::enable_shared_from_this { +public: + using ptr_t = std::shared_ptr; + using cptr_t = std::shared_ptr; + + virtual ~CopyOnWriteConfig(); + + [[nodiscard]] static CopyOnWriteConfig::ptr_t adapt(Config::cptr_t); + + Config::ptr_t clone() const; + Config::ptr_t merge(Config::cptr_t) const; + + Config::url_opt_ref_t url() const; + Config::ptr_t url(Config::url_ref_t); + Config::ptr_t clear_url(); + +protected: + CopyOnWriteConfig(Config::cptr_t); + +private: + struct Impl; + const std::unique_ptr impl; +}; +} +} +} + +#endif diff --git a/src/internal/MergedConfig.cpp b/src/internal/MergedConfig.cpp new file mode 100644 index 0000000..a90bced --- /dev/null +++ b/src/internal/MergedConfig.cpp @@ -0,0 +1,65 @@ +#include + +#include "./MergedConfig.hpp" +#include "./CopyOnWriteConfig.hpp" + +#include + +using namespace wtlgo::network; +using namespace wtlgo::network::internal; + +struct MergedConfig::Impl { +private: + Config::ptr_t lhs; + Config::ptr_t rhs; + +public: + Impl(const Config::cptr_t lhs, const Config::cptr_t rhs) + : lhs{CopyOnWriteConfig::adapt(lhs)}, + rhs{CopyOnWriteConfig::adapt(rhs)} {} + + Config::url_opt_ref_t url() const { + return rhs->url() ? rhs->url() : lhs->url(); + } + + void url(const Config::url_ref_t url) { + lhs->clear_url(); + rhs->url(url); + } + + void clear_url() { + lhs->clear_url(); + rhs->clear_url(); + } +}; + +MergedConfig::~MergedConfig() = default; + +MergedConfig::ptr_t MergedConfig::merge(const Config::cptr_t lconfig, + const Config::cptr_t rconfig) { + return std::shared_ptr{new MergedConfig{lconfig, rconfig}}; +} + +Config::ptr_t MergedConfig::clone() const { + return DefaultConfig::clone(shared_from_this()); +} + +Config::ptr_t MergedConfig::merge(const Config::cptr_t rconfig) const { + return merge(shared_from_this(), rconfig); +} + +Config::url_opt_ref_t MergedConfig::url() const { return impl->url(); } + +Config::ptr_t MergedConfig::url(const Config::url_ref_t url) { + impl->url(url); + return shared_from_this(); +} + +Config::ptr_t MergedConfig::clear_url() { + impl->clear_url(); + return shared_from_this(); +} + +MergedConfig::MergedConfig(const Config::cptr_t lconfig, + const Config::cptr_t rconfig) + : impl{std::make_unique(lconfig, rconfig)} {} diff --git a/src/internal/MergedConfig.hpp b/src/internal/MergedConfig.hpp new file mode 100644 index 0000000..6983d77 --- /dev/null +++ b/src/internal/MergedConfig.hpp @@ -0,0 +1,39 @@ +#ifndef __WTLGO__NETWORK__INTERNAL__MERGED_CONFIG__ +#define __WTLGO__NETWORK__INTERNAL__MERGED_CONFIG__ + +#include +#include + +namespace wtlgo { +namespace network { +namespace internal { +class MergedConfig : public Config, + public std::enable_shared_from_this { +public: + using ptr_t = std::shared_ptr; + using cptr_t = std::shared_ptr; + + virtual ~MergedConfig(); + + [[nodiscard]] static MergedConfig::ptr_t merge(Config::cptr_t, + Config::cptr_t); + + Config::ptr_t clone() const; + Config::ptr_t merge(Config::cptr_t) const; + + Config::url_opt_ref_t url() const; + Config::ptr_t url(Config::url_ref_t); + Config::ptr_t clear_url(); + +protected: + MergedConfig(Config::cptr_t, Config::cptr_t); + +private: + struct Impl; + const std::unique_ptr impl; +}; +} +} +} + +#endif diff --git a/test/src/DefaultConfig.cpp b/test/src/DefaultConfig.cpp index d7c99fd..d3da208 100644 --- a/test/src/DefaultConfig.cpp +++ b/test/src/DefaultConfig.cpp @@ -37,15 +37,6 @@ TEST(DefaultConfig, Merge) { ASSERT_NE(mconfig, lconfig); } -TEST(DefaultConfig, MergeFail) { - using namespace wtlgo::network; - - const Config::cptr_t config = DefaultConfig::create(); - - Config::cptr_t mconfig; - ASSERT_THROW(mconfig = config->merge(nullptr), std::invalid_argument); -} - TEST(DefaultConfig, UrlSet) { using namespace wtlgo::network; @@ -106,7 +97,6 @@ TEST(DefaultConfig, UrlMergeRight) { const Config::cptr_t mconfig = lconfig->merge(rconfig); ASSERT_EQ(mconfig->url(), rconfig->url()); - ASSERT_NE(mconfig->url()->data(), rconfig->url()->data()); } TEST(DefaultConfig, UrlMergeLeft) { @@ -118,7 +108,6 @@ TEST(DefaultConfig, UrlMergeLeft) { const Config::cptr_t mconfig = lconfig->merge(rconfig); ASSERT_EQ(mconfig->url(), lconfig->url()); - ASSERT_NE(mconfig->url()->data(), lconfig->url()->data()); } TEST(DefaultConfig, UrlMergeFull) { @@ -131,5 +120,4 @@ TEST(DefaultConfig, UrlMergeFull) { const Config::cptr_t mconfig = lconfig->merge(rconfig); ASSERT_EQ(mconfig->url(), rconfig->url()); - ASSERT_NE(mconfig->url()->data(), rconfig->url()->data()); } From 67475231874a0896e5c72a0e0f534c0c90df7453 Mon Sep 17 00:00:00 2001 From: wtlgo Date: Fri, 27 Jan 2023 15:33:33 +0300 Subject: [PATCH 29/46] Add missing override keywork --- include/wtlgo/network/DefaultConfig.hpp | 6 +++--- src/internal/CopyOnWriteConfig.hpp | 10 +++++----- src/internal/MergedConfig.hpp | 10 +++++----- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/include/wtlgo/network/DefaultConfig.hpp b/include/wtlgo/network/DefaultConfig.hpp index 52bb3bc..c3ad5bc 100644 --- a/include/wtlgo/network/DefaultConfig.hpp +++ b/include/wtlgo/network/DefaultConfig.hpp @@ -21,9 +21,9 @@ class DefaultConfig : public Config, Config::ptr_t clone() const override; Config::ptr_t merge(Config::cptr_t) const override; - Config::url_opt_ref_t url() const; - Config::ptr_t url(Config::url_ref_t); - Config::ptr_t clear_url(); + Config::url_opt_ref_t url() const override; + Config::ptr_t url(Config::url_ref_t) override; + Config::ptr_t clear_url() override; protected: DefaultConfig(); diff --git a/src/internal/CopyOnWriteConfig.hpp b/src/internal/CopyOnWriteConfig.hpp index 82630ab..8bafca0 100644 --- a/src/internal/CopyOnWriteConfig.hpp +++ b/src/internal/CopyOnWriteConfig.hpp @@ -18,12 +18,12 @@ class CopyOnWriteConfig [[nodiscard]] static CopyOnWriteConfig::ptr_t adapt(Config::cptr_t); - Config::ptr_t clone() const; - Config::ptr_t merge(Config::cptr_t) const; + Config::ptr_t clone() const override; + Config::ptr_t merge(Config::cptr_t) const override; - Config::url_opt_ref_t url() const; - Config::ptr_t url(Config::url_ref_t); - Config::ptr_t clear_url(); + Config::url_opt_ref_t url() const override; + Config::ptr_t url(Config::url_ref_t) override; + Config::ptr_t clear_url() override; protected: CopyOnWriteConfig(Config::cptr_t); diff --git a/src/internal/MergedConfig.hpp b/src/internal/MergedConfig.hpp index 6983d77..475ff89 100644 --- a/src/internal/MergedConfig.hpp +++ b/src/internal/MergedConfig.hpp @@ -18,12 +18,12 @@ class MergedConfig : public Config, [[nodiscard]] static MergedConfig::ptr_t merge(Config::cptr_t, Config::cptr_t); - Config::ptr_t clone() const; - Config::ptr_t merge(Config::cptr_t) const; + Config::ptr_t clone() const override; + Config::ptr_t merge(Config::cptr_t) const override; - Config::url_opt_ref_t url() const; - Config::ptr_t url(Config::url_ref_t); - Config::ptr_t clear_url(); + Config::url_opt_ref_t url() const override; + Config::ptr_t url(Config::url_ref_t) override; + Config::ptr_t clear_url() override; protected: MergedConfig(Config::cptr_t, Config::cptr_t); From c66c685dc9ad4195e505dae0fe8f90f0858b70d1 Mon Sep 17 00:00:00 2001 From: wtlgo Date: Fri, 27 Jan 2023 16:22:21 +0300 Subject: [PATCH 30/46] Add merge to Config --- include/wtlgo/network/Config.hpp | 9 ++ include/wtlgo/network/DefaultConfig.hpp | 4 + src/DefaultConfig.cpp | 22 ++++- src/internal/CopyOnWriteConfig.cpp | 22 ++++- src/internal/CopyOnWriteConfig.hpp | 4 + src/internal/MergedConfig.cpp | 26 +++++ src/internal/MergedConfig.hpp | 4 + test/src/DefaultConfig.cpp | 120 ++++++++++++++++++++++++ 8 files changed, 207 insertions(+), 4 deletions(-) diff --git a/include/wtlgo/network/Config.hpp b/include/wtlgo/network/Config.hpp index aef621d..9bf1288 100644 --- a/include/wtlgo/network/Config.hpp +++ b/include/wtlgo/network/Config.hpp @@ -5,6 +5,8 @@ #include #include +#include + namespace wtlgo { namespace network { struct Config { @@ -22,6 +24,13 @@ struct Config { virtual url_opt_ref_t url() const = 0; virtual ptr_t url(url_ref_t) = 0; virtual ptr_t clear_url() = 0; + + using method_t = HttpMethod; + using method_opt_t = std::optional; + + virtual method_opt_t method() const = 0; + virtual ptr_t method(method_t) = 0; + virtual ptr_t clear_method() = 0; }; } } diff --git a/include/wtlgo/network/DefaultConfig.hpp b/include/wtlgo/network/DefaultConfig.hpp index c3ad5bc..68eef4a 100644 --- a/include/wtlgo/network/DefaultConfig.hpp +++ b/include/wtlgo/network/DefaultConfig.hpp @@ -25,6 +25,10 @@ class DefaultConfig : public Config, Config::ptr_t url(Config::url_ref_t) override; Config::ptr_t clear_url() override; + Config::method_opt_t method() const override; + Config::ptr_t method(Config::method_t) override; + Config::ptr_t clear_method() override; + protected: DefaultConfig(); DefaultConfig(const Config::cptr_t); diff --git a/src/DefaultConfig.cpp b/src/DefaultConfig.cpp index 1bd11bf..df45211 100644 --- a/src/DefaultConfig.cpp +++ b/src/DefaultConfig.cpp @@ -5,8 +5,8 @@ #include #include "./internal/MergedConfig.hpp" - #include + #include using namespace wtlgo::network; @@ -14,11 +14,13 @@ using namespace wtlgo::network; struct DefaultConfig::Impl { private: std::optional _url; + Config::method_opt_t _method; public: Impl() = default; Impl(const Impl&) = default; - Impl(const Config::cptr_t config) : _url{config->url()} {} + Impl(const Config::cptr_t config) + : _url{config->url()}, _method{config->method()} {} std::unique_ptr merge(const Config::cptr_t rconfig) const { if (rconfig == nullptr) { @@ -37,6 +39,10 @@ struct DefaultConfig::Impl { Config::url_opt_ref_t url() const { return _url; } void url(const Config::url_ref_t url) { _url = url; } void clear_url() { _url = std::nullopt; } + + Config::method_opt_t method() const { return _method; } + void method(const Config::method_t method) { _method = method; } + void clear_method() { _method = std::nullopt; } }; DefaultConfig::~DefaultConfig() = default; @@ -67,6 +73,18 @@ Config::ptr_t DefaultConfig::clear_url() { return shared_from_this(); } +Config::method_opt_t DefaultConfig::method() const { return impl->method(); } + +Config::ptr_t DefaultConfig::method(const Config::method_t method) { + impl->method(method); + return shared_from_this(); +} + +Config::ptr_t DefaultConfig::clear_method() { + impl->clear_method(); + return shared_from_this(); +} + DefaultConfig::DefaultConfig() : impl{std::make_unique()} {} DefaultConfig::DefaultConfig(const Config::cptr_t config) diff --git a/src/internal/CopyOnWriteConfig.cpp b/src/internal/CopyOnWriteConfig.cpp index 2e1e8c6..1de699e 100644 --- a/src/internal/CopyOnWriteConfig.cpp +++ b/src/internal/CopyOnWriteConfig.cpp @@ -13,7 +13,7 @@ struct CopyOnWriteConfig::Impl { Config::cptr_t solid; Config::ptr_t liquid; - void solidify() { + void liquify() { if (!solid) return; liquid = DefaultConfig::clone(solid); @@ -22,7 +22,7 @@ struct CopyOnWriteConfig::Impl { Config::cptr_t cptr() const { return solid ? solid : liquid; } Config::ptr_t ptr() { - solidify(); + liquify(); return liquid; } @@ -32,6 +32,10 @@ struct CopyOnWriteConfig::Impl { Config::url_opt_ref_t url() const { return cptr()->url(); } void url(const Config::url_ref_t url) { ptr()->url(url); } void clear_url() { ptr()->clear_url(); } + + Config::method_opt_t method() const { return cptr()->method(); } + void method(const Config::method_t method) { ptr()->method(method); } + void clear_method() { ptr()->clear_method(); } }; CopyOnWriteConfig::~CopyOnWriteConfig() = default; @@ -59,5 +63,19 @@ Config::ptr_t CopyOnWriteConfig::clear_url() { return shared_from_this(); } +Config::method_opt_t CopyOnWriteConfig::method() const { + return impl->method(); +} + +Config::ptr_t CopyOnWriteConfig::method(const Config::method_t method) { + impl->method(method); + return shared_from_this(); +} + +Config::ptr_t CopyOnWriteConfig::clear_method() { + impl->clear_method(); + return shared_from_this(); +} + CopyOnWriteConfig::CopyOnWriteConfig(const Config::cptr_t config) : impl{std::make_unique(config)} {} diff --git a/src/internal/CopyOnWriteConfig.hpp b/src/internal/CopyOnWriteConfig.hpp index 8bafca0..618b9a5 100644 --- a/src/internal/CopyOnWriteConfig.hpp +++ b/src/internal/CopyOnWriteConfig.hpp @@ -25,6 +25,10 @@ class CopyOnWriteConfig Config::ptr_t url(Config::url_ref_t) override; Config::ptr_t clear_url() override; + Config::method_opt_t method() const override; + Config::ptr_t method(Config::method_t) override; + Config::ptr_t clear_method() override; + protected: CopyOnWriteConfig(Config::cptr_t); diff --git a/src/internal/MergedConfig.cpp b/src/internal/MergedConfig.cpp index a90bced..23e9e4f 100644 --- a/src/internal/MergedConfig.cpp +++ b/src/internal/MergedConfig.cpp @@ -31,6 +31,20 @@ struct MergedConfig::Impl { lhs->clear_url(); rhs->clear_url(); } + + Config::method_opt_t method() const { + return rhs->method() ? rhs->method() : lhs->method(); + } + + void method(const Config::method_t method) { + lhs->clear_method(); + rhs->method(method); + } + + void clear_method() { + lhs->clear_method(); + rhs->clear_method(); + } }; MergedConfig::~MergedConfig() = default; @@ -60,6 +74,18 @@ Config::ptr_t MergedConfig::clear_url() { return shared_from_this(); } +Config::method_opt_t MergedConfig::method() const { return impl->method(); } + +Config::ptr_t MergedConfig::method(const Config::method_t method) { + impl->method(method); + return shared_from_this(); +} + +Config::ptr_t MergedConfig::clear_method() { + impl->clear_method(); + return shared_from_this(); +} + MergedConfig::MergedConfig(const Config::cptr_t lconfig, const Config::cptr_t rconfig) : impl{std::make_unique(lconfig, rconfig)} {} diff --git a/src/internal/MergedConfig.hpp b/src/internal/MergedConfig.hpp index 475ff89..72e7975 100644 --- a/src/internal/MergedConfig.hpp +++ b/src/internal/MergedConfig.hpp @@ -25,6 +25,10 @@ class MergedConfig : public Config, Config::ptr_t url(Config::url_ref_t) override; Config::ptr_t clear_url() override; + Config::method_opt_t method() const override; + Config::ptr_t method(Config::method_t) override; + Config::ptr_t clear_method() override; + protected: MergedConfig(Config::cptr_t, Config::cptr_t); diff --git a/test/src/DefaultConfig.cpp b/test/src/DefaultConfig.cpp index d3da208..8f428eb 100644 --- a/test/src/DefaultConfig.cpp +++ b/test/src/DefaultConfig.cpp @@ -121,3 +121,123 @@ TEST(DefaultConfig, UrlMergeFull) { ASSERT_EQ(mconfig->url(), rconfig->url()); } + +TEST(DefaultConfig, MethodDefault) { + using namespace wtlgo::network; + + const Config::cptr_t config = DefaultConfig::create(); + ASSERT_EQ(config->method(), std::nullopt); +} + +TEST(DefaultConfig, MethodSet) { + using namespace wtlgo::network; + + const Config::ptr_t config = DefaultConfig::create(); + + for (const HttpMethod test_method : + {HttpMethod::GET, HttpMethod::POST, HttpMethod::PATCH, HttpMethod::PUT, + HttpMethod::DELETE}) { + ASSERT_EQ(config, config->method(test_method)); + ASSERT_EQ(config->method(), test_method); + } +} + +TEST(DefaultConfig, MethodClear) { + using namespace wtlgo::network; + + for (const HttpMethod test_method : + {HttpMethod::GET, HttpMethod::POST, HttpMethod::PATCH, HttpMethod::PUT, + HttpMethod::DELETE}) { + const Config::ptr_t config = + DefaultConfig::create()->method(test_method); + + ASSERT_EQ(config, config->clear_method()); + ASSERT_EQ(config->method(), std::nullopt); + } +} + +TEST(DefaultConfig, MethodCloneEmpty) { + using namespace wtlgo::network; + + const Config::cptr_t config = DefaultConfig::create()->clear_method(); + const Config::cptr_t clone = config->clone(); + + ASSERT_EQ(clone->method(), std::nullopt); +} + +TEST(DefaultConfig, MethodCloneValue) { + using namespace wtlgo::network; + + for (const HttpMethod test_method : + {HttpMethod::GET, HttpMethod::POST, HttpMethod::PATCH, HttpMethod::PUT, + HttpMethod::DELETE}) { + const Config::cptr_t config = + DefaultConfig::create()->method(test_method); + const Config::cptr_t clone = config->clone(); + + ASSERT_EQ(clone->method(), test_method); + } +} + +TEST(DefaultConfig, MethodMergeEmpty) { + using namespace wtlgo::network; + + const Config::cptr_t lconfig = DefaultConfig::create()->clear_method(); + const Config::cptr_t rconfig = DefaultConfig::create()->clear_method(); + const Config::cptr_t mconfig = lconfig->merge(rconfig); + + ASSERT_EQ(rconfig->method(), std::nullopt); +} + +TEST(DefaultConfig, MethodMergeLeft) { + using namespace wtlgo::network; + + const Config::cptr_t rconfig = DefaultConfig::create()->clear_method(); + + for (const HttpMethod test_method : + {HttpMethod::GET, HttpMethod::POST, HttpMethod::PATCH, HttpMethod::PUT, + HttpMethod::DELETE}) { + const Config::cptr_t lconfig = + DefaultConfig::create()->method(test_method); + const Config::cptr_t mconfig = lconfig->merge(rconfig); + + ASSERT_EQ(mconfig->method(), test_method); + } +} + +TEST(DefaultConfig, MethodMergeRight) { + using namespace wtlgo::network; + + const Config::cptr_t lconfig = DefaultConfig::create()->clear_method(); + + for (const HttpMethod test_method : + {HttpMethod::GET, HttpMethod::POST, HttpMethod::PATCH, HttpMethod::PUT, + HttpMethod::DELETE}) { + const Config::cptr_t rconfig = + DefaultConfig::create()->method(test_method); + const Config::cptr_t mconfig = lconfig->merge(rconfig); + + ASSERT_EQ(mconfig->method(), test_method); + } +} + +TEST(DefaultConfig, MethodMergeFull) { + using namespace wtlgo::network; + + for (const HttpMethod ltest_method : + {HttpMethod::GET, HttpMethod::POST, HttpMethod::PATCH, HttpMethod::PUT, + HttpMethod::DELETE}) { + const Config::cptr_t lconfig = + DefaultConfig::create()->method(ltest_method); + + for (const HttpMethod rtest_method : + {HttpMethod::GET, HttpMethod::POST, HttpMethod::PATCH, + HttpMethod::PUT, HttpMethod::DELETE}) { + const Config::cptr_t rconfig = + DefaultConfig::create()->method(rtest_method); + const Config::cptr_t mconfig = lconfig->merge(rconfig); + + ASSERT_EQ(mconfig->method(), rtest_method); + } + } +} From b3e0f34c3070ffbf33218e2f28a15749ce754e12 Mon Sep 17 00:00:00 2001 From: wtlgo Date: Tue, 31 Jan 2023 11:06:58 +0300 Subject: [PATCH 31/46] Add base_url to Config --- include/wtlgo/network/Config.hpp | 4 ++ include/wtlgo/network/DefaultConfig.hpp | 4 ++ src/DefaultConfig.cpp | 23 ++++++- src/internal/CopyOnWriteConfig.cpp | 18 ++++++ src/internal/CopyOnWriteConfig.hpp | 4 ++ src/internal/MergedConfig.cpp | 28 ++++++++ src/internal/MergedConfig.hpp | 4 ++ test/src/DefaultConfig.cpp | 85 +++++++++++++++++++++++++ 8 files changed, 169 insertions(+), 1 deletion(-) diff --git a/include/wtlgo/network/Config.hpp b/include/wtlgo/network/Config.hpp index 9bf1288..57307ec 100644 --- a/include/wtlgo/network/Config.hpp +++ b/include/wtlgo/network/Config.hpp @@ -31,6 +31,10 @@ struct Config { virtual method_opt_t method() const = 0; virtual ptr_t method(method_t) = 0; virtual ptr_t clear_method() = 0; + + virtual url_opt_ref_t base_url() const = 0; + virtual ptr_t base_url(url_ref_t) = 0; + virtual ptr_t clear_base_url() = 0; }; } } diff --git a/include/wtlgo/network/DefaultConfig.hpp b/include/wtlgo/network/DefaultConfig.hpp index 68eef4a..31c18e3 100644 --- a/include/wtlgo/network/DefaultConfig.hpp +++ b/include/wtlgo/network/DefaultConfig.hpp @@ -29,6 +29,10 @@ class DefaultConfig : public Config, Config::ptr_t method(Config::method_t) override; Config::ptr_t clear_method() override; + Config::url_opt_ref_t base_url() const override; + Config::ptr_t base_url(Config::url_ref_t) override; + Config::ptr_t clear_base_url() override; + protected: DefaultConfig(); DefaultConfig(const Config::cptr_t); diff --git a/src/DefaultConfig.cpp b/src/DefaultConfig.cpp index df45211..43ae855 100644 --- a/src/DefaultConfig.cpp +++ b/src/DefaultConfig.cpp @@ -15,12 +15,15 @@ struct DefaultConfig::Impl { private: std::optional _url; Config::method_opt_t _method; + std::optional _base_url; public: Impl() = default; Impl(const Impl&) = default; Impl(const Config::cptr_t config) - : _url{config->url()}, _method{config->method()} {} + : _url{config->url()}, + _method{config->method()}, + _base_url{config->base_url()} {} std::unique_ptr merge(const Config::cptr_t rconfig) const { if (rconfig == nullptr) { @@ -43,6 +46,10 @@ struct DefaultConfig::Impl { Config::method_opt_t method() const { return _method; } void method(const Config::method_t method) { _method = method; } void clear_method() { _method = std::nullopt; } + + Config::url_opt_ref_t base_url() const { return _base_url; } + void base_url(const Config::url_ref_t url) { _base_url = url; } + void clear_base_url() { _base_url = std::nullopt; } }; DefaultConfig::~DefaultConfig() = default; @@ -85,6 +92,20 @@ Config::ptr_t DefaultConfig::clear_method() { return shared_from_this(); } +Config::url_opt_ref_t DefaultConfig::base_url() const { + return impl->base_url(); +} + +Config::ptr_t DefaultConfig::base_url(const Config::url_ref_t url) { + impl->base_url(url); + return shared_from_this(); +} + +Config::ptr_t DefaultConfig::clear_base_url() { + impl->clear_base_url(); + return shared_from_this(); +} + DefaultConfig::DefaultConfig() : impl{std::make_unique()} {} DefaultConfig::DefaultConfig(const Config::cptr_t config) diff --git a/src/internal/CopyOnWriteConfig.cpp b/src/internal/CopyOnWriteConfig.cpp index 1de699e..1f5645d 100644 --- a/src/internal/CopyOnWriteConfig.cpp +++ b/src/internal/CopyOnWriteConfig.cpp @@ -36,6 +36,10 @@ struct CopyOnWriteConfig::Impl { Config::method_opt_t method() const { return cptr()->method(); } void method(const Config::method_t method) { ptr()->method(method); } void clear_method() { ptr()->clear_method(); } + + Config::url_opt_ref_t base_url() const { return cptr()->base_url(); } + void base_url(const Config::url_ref_t url) { ptr()->base_url(url); } + void clear_base_url() { ptr()->clear_base_url(); } }; CopyOnWriteConfig::~CopyOnWriteConfig() = default; @@ -77,5 +81,19 @@ Config::ptr_t CopyOnWriteConfig::clear_method() { return shared_from_this(); } +Config::url_opt_ref_t CopyOnWriteConfig::base_url() const { + return impl->base_url(); +} + +Config::ptr_t CopyOnWriteConfig::base_url(const Config::url_ref_t url) { + impl->base_url(url); + return shared_from_this(); +} + +Config::ptr_t CopyOnWriteConfig::clear_base_url() { + impl->clear_base_url(); + return shared_from_this(); +} + CopyOnWriteConfig::CopyOnWriteConfig(const Config::cptr_t config) : impl{std::make_unique(config)} {} diff --git a/src/internal/CopyOnWriteConfig.hpp b/src/internal/CopyOnWriteConfig.hpp index 618b9a5..458b05f 100644 --- a/src/internal/CopyOnWriteConfig.hpp +++ b/src/internal/CopyOnWriteConfig.hpp @@ -29,6 +29,10 @@ class CopyOnWriteConfig Config::ptr_t method(Config::method_t) override; Config::ptr_t clear_method() override; + Config::url_opt_ref_t base_url() const override; + Config::ptr_t base_url(Config::url_ref_t) override; + Config::ptr_t clear_base_url() override; + protected: CopyOnWriteConfig(Config::cptr_t); diff --git a/src/internal/MergedConfig.cpp b/src/internal/MergedConfig.cpp index 23e9e4f..c688fb3 100644 --- a/src/internal/MergedConfig.cpp +++ b/src/internal/MergedConfig.cpp @@ -45,6 +45,20 @@ struct MergedConfig::Impl { lhs->clear_method(); rhs->clear_method(); } + + Config::url_opt_ref_t base_url() const { + return rhs->base_url() ? rhs->base_url() : lhs->base_url(); + } + + void base_url(const Config::url_ref_t url) { + lhs->clear_base_url(); + rhs->base_url(url); + } + + void clear_base_url() { + lhs->clear_base_url(); + rhs->clear_base_url(); + } }; MergedConfig::~MergedConfig() = default; @@ -86,6 +100,20 @@ Config::ptr_t MergedConfig::clear_method() { return shared_from_this(); } +Config::url_opt_ref_t MergedConfig::base_url() const { + return impl->base_url(); +} + +Config::ptr_t MergedConfig::base_url(const Config::url_ref_t url) { + impl->base_url(url); + return shared_from_this(); +} + +Config::ptr_t MergedConfig::clear_base_url() { + impl->clear_base_url(); + return shared_from_this(); +} + MergedConfig::MergedConfig(const Config::cptr_t lconfig, const Config::cptr_t rconfig) : impl{std::make_unique(lconfig, rconfig)} {} diff --git a/src/internal/MergedConfig.hpp b/src/internal/MergedConfig.hpp index 72e7975..61887c1 100644 --- a/src/internal/MergedConfig.hpp +++ b/src/internal/MergedConfig.hpp @@ -29,6 +29,10 @@ class MergedConfig : public Config, Config::ptr_t method(Config::method_t) override; Config::ptr_t clear_method() override; + Config::url_opt_ref_t base_url() const override; + Config::ptr_t base_url(Config::url_ref_t) override; + Config::ptr_t clear_base_url() override; + protected: MergedConfig(Config::cptr_t, Config::cptr_t); diff --git a/test/src/DefaultConfig.cpp b/test/src/DefaultConfig.cpp index 8f428eb..c97efd1 100644 --- a/test/src/DefaultConfig.cpp +++ b/test/src/DefaultConfig.cpp @@ -241,3 +241,88 @@ TEST(DefaultConfig, MethodMergeFull) { } } } + +TEST(DefaultConfig, BaseUrlSet) { + using namespace wtlgo::network; + + const Config::ptr_t config = DefaultConfig::create(); + + const std::string test_url = random_string(50); + + ASSERT_EQ(config, config->base_url(test_url)); + ASSERT_EQ(config->base_url(), test_url); +} + +TEST(DefaultConfig, BaseUrlClear) { + using namespace wtlgo::network; + + const Config::ptr_t config = + DefaultConfig::create()->base_url(random_string(50)); + + ASSERT_EQ(config, config->clear_base_url()); + ASSERT_EQ(config->base_url(), std::nullopt); +} + +TEST(DefaultConfig, BaseUrlCloneEmpty) { + using namespace wtlgo::network; + + const Config::cptr_t config = DefaultConfig::create()->clear_base_url(); + const Config::cptr_t clone = config->clone(); + + ASSERT_EQ(clone->base_url(), std::nullopt); +} + +TEST(DefaultConfig, BaseUrlCloneValue) { + using namespace wtlgo::network; + + const Config::cptr_t config = + DefaultConfig::create()->base_url(random_string(50)); + const Config::cptr_t clone = config->clone(); + + ASSERT_EQ(clone->base_url(), config->base_url()); + ASSERT_NE(clone->base_url()->data(), config->base_url()->data()); +} + +TEST(DefaultConfig, BaseUrlMergeEmpty) { + using namespace wtlgo::network; + + const Config::cptr_t lconfig = DefaultConfig::create()->clear_base_url(); + const Config::cptr_t rconfig = DefaultConfig::create()->clear_base_url(); + const Config::cptr_t mconfig = lconfig->merge(rconfig); + + ASSERT_EQ(mconfig->base_url(), std::nullopt); +} + +TEST(DefaultConfig, BaseUrlMergeRight) { + using namespace wtlgo::network; + + const Config::cptr_t lconfig = DefaultConfig::create()->clear_base_url(); + const Config::cptr_t rconfig = + DefaultConfig::create()->base_url(random_string(50)); + const Config::cptr_t mconfig = lconfig->merge(rconfig); + + ASSERT_EQ(mconfig->base_url(), rconfig->base_url()); +} + +TEST(DefaultConfig, BaseUrlMergeLeft) { + using namespace wtlgo::network; + + const Config::cptr_t lconfig = + DefaultConfig::create()->base_url(random_string(50)); + const Config::cptr_t rconfig = DefaultConfig::create()->clear_base_url(); + const Config::cptr_t mconfig = lconfig->merge(rconfig); + + ASSERT_EQ(mconfig->base_url(), lconfig->base_url()); +} + +TEST(DefaultConfig, BaseUrlMergeFull) { + using namespace wtlgo::network; + + const Config::cptr_t lconfig = + DefaultConfig::create()->base_url(random_string(50)); + const Config::cptr_t rconfig = + DefaultConfig::create()->base_url(random_string(50)); + const Config::cptr_t mconfig = lconfig->merge(rconfig); + + ASSERT_EQ(mconfig->base_url(), rconfig->base_url()); +} From 9d27561880f29a0d558029de789290dafd393b77 Mon Sep 17 00:00:00 2001 From: wtlgo Date: Tue, 31 Jan 2023 11:08:48 +0300 Subject: [PATCH 32/46] Remove dead code --- src/DefaultConfig.cpp | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/src/DefaultConfig.cpp b/src/DefaultConfig.cpp index 43ae855..f38cf87 100644 --- a/src/DefaultConfig.cpp +++ b/src/DefaultConfig.cpp @@ -25,20 +25,6 @@ struct DefaultConfig::Impl { _method{config->method()}, _base_url{config->base_url()} {} - std::unique_ptr merge(const Config::cptr_t rconfig) const { - if (rconfig == nullptr) { - throw std::invalid_argument{"nullptr is provided!"}; - } - - auto res = std::make_unique(*this); - - if (rconfig->url()) { - res->_url = rconfig->url(); - } - - return res; - } - Config::url_opt_ref_t url() const { return _url; } void url(const Config::url_ref_t url) { _url = url; } void clear_url() { _url = std::nullopt; } From e7b3ba06ef3976185299c6de9cbb4f62a514eb49 Mon Sep 17 00:00:00 2001 From: wtlgo Date: Tue, 31 Jan 2023 17:32:46 +0300 Subject: [PATCH 33/46] Add Headers interface and HttpHeaders class --- CMakeLists.txt | 4 ++ include/wtlgo/network/Headers.hpp | 33 ++++++++++ include/wtlgo/network/HttpHeaders.hpp | 37 ++++++++++++ src/HttpHeaders.cpp | 78 ++++++++++++++++++++++++ test/src/DefaultConfig.cpp | 28 ++++----- test/src/DefaultHttpBasicAuth.cpp | 14 ++--- test/src/HttpHeaders.cpp | 86 +++++++++++++++++++++++++++ test/src/utility.hpp | 2 +- 8 files changed, 260 insertions(+), 22 deletions(-) create mode 100644 include/wtlgo/network/Headers.hpp create mode 100644 include/wtlgo/network/HttpHeaders.hpp create mode 100644 src/HttpHeaders.cpp create mode 100644 test/src/HttpHeaders.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 76cb9c6..9a1ee7e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,12 +20,16 @@ set(PUBLIC_HEADERS "include/wtlgo/network/Config.hpp" "include/wtlgo/network/DefaultConfig.hpp" + + "include/wtlgo/network/Headers.hpp" + "include/wtlgo/network/HttpHeaders.hpp" ) set(SOURCES "src/NetworkOld.cpp" "src/DefaultHttpBasicAuth.cpp" "src/DefaultConfig.cpp" + "src/HttpHeaders.cpp" "src/internal/MergedConfig.hpp" "src/internal/MergedConfig.cpp" diff --git a/include/wtlgo/network/Headers.hpp b/include/wtlgo/network/Headers.hpp new file mode 100644 index 0000000..c91a2bc --- /dev/null +++ b/include/wtlgo/network/Headers.hpp @@ -0,0 +1,33 @@ +#ifndef __WTLGO__NETWORK__HEADERS__ +#define __WTLGO__NETWORK__HEADERS__ + +#include +#include +#include +#include + +namespace wtlgo { +namespace network { +struct Headers { + using ptr_t = std::shared_ptr; + using cptr_t = std::shared_ptr; + + virtual ~Headers() = default; + + using key_ref_t = std::string_view; + using key_ref_list_t = std::set; + + using value_ref_t = std::string_view; + using value_ref_opt_t = std::optional; + + virtual ptr_t clone() const = 0; + + virtual key_ref_list_t keys() const = 0; + virtual value_ref_opt_t get(key_ref_t header) const = 0; + virtual ptr_t set(key_ref_t header, value_ref_t value) = 0; + virtual ptr_t erase(key_ref_t header) = 0; +}; +} +} + +#endif diff --git a/include/wtlgo/network/HttpHeaders.hpp b/include/wtlgo/network/HttpHeaders.hpp new file mode 100644 index 0000000..888a45b --- /dev/null +++ b/include/wtlgo/network/HttpHeaders.hpp @@ -0,0 +1,37 @@ +#ifndef __WTLGO__NETWORK__HTTP_HEADERS__ +#define __WTLGO__NETWORK__HTTP_HEADERS__ + +#include + +#include + +namespace wtlgo { +namespace network { +class HttpHeaders : public Headers, + public std::enable_shared_from_this { +public: + using ptr_t = std::shared_ptr; + using cptr_t = std::shared_ptr; + + virtual ~HttpHeaders(); + + [[nodiscard]] static ptr_t create(); + + Headers::ptr_t clone() const override; + + Headers::key_ref_list_t keys() const override; + Headers::value_ref_opt_t get(Headers::key_ref_t header) const override; + Headers::ptr_t set(Headers::key_ref_t header, value_ref_t value) override; + Headers::ptr_t erase(Headers::key_ref_t header) override; + +private: + struct Impl; + const std::unique_ptr impl; + + HttpHeaders(); + HttpHeaders(const std::unique_ptr& impl); +}; +} +} + +#endif diff --git a/src/HttpHeaders.cpp b/src/HttpHeaders.cpp new file mode 100644 index 0000000..af9cbb6 --- /dev/null +++ b/src/HttpHeaders.cpp @@ -0,0 +1,78 @@ +#include +#include +#include +#include +#include +#include + +#include + +using namespace wtlgo::network; + +struct HttpHeaders::Impl { +private: + std::map> _data; + +public: + Headers::key_ref_list_t keys() const { + Headers::key_ref_list_t res; + std::transform( + _data.cbegin(), _data.cend(), std::inserter(res, res.begin()), + [](const auto& val) -> Headers::key_ref_t { return val.first; }); + return res; + } + + Headers::value_ref_opt_t get(const Headers::key_ref_t header) const { + const auto it = _data.find(header); + + if (it == _data.cend()) { + return std::nullopt; + } + + return it->second; + } + + void set(const Headers::key_ref_t header, const value_ref_t value) { + _data.emplace(header, value); + } + + void clear(const Headers::key_ref_t header) { + const auto it = _data.find(header); + if (it != _data.cend()) { + _data.erase(it); + } + } +}; + +HttpHeaders::~HttpHeaders() = default; + +HttpHeaders::ptr_t HttpHeaders::create() { + return std::shared_ptr{new HttpHeaders{}}; +} + +Headers::ptr_t HttpHeaders::clone() const { + return std::shared_ptr{new HttpHeaders{impl}}; +} + +Headers::key_ref_list_t HttpHeaders::keys() const { return impl->keys(); } + +Headers::value_ref_opt_t HttpHeaders::get( + const Headers::key_ref_t header) const { + return impl->get(header); +} + +Headers::ptr_t HttpHeaders::set(const Headers::key_ref_t header, + const value_ref_t value) { + impl->set(header, value); + return shared_from_this(); +} + +Headers::ptr_t HttpHeaders::erase(const Headers::key_ref_t header) { + impl->clear(header); + return shared_from_this(); +} + +HttpHeaders::HttpHeaders() : impl{std::make_unique()} {} + +HttpHeaders::HttpHeaders(const std::unique_ptr& impl) + : impl{std::make_unique(*impl)} {} diff --git a/test/src/DefaultConfig.cpp b/test/src/DefaultConfig.cpp index c97efd1..126cd81 100644 --- a/test/src/DefaultConfig.cpp +++ b/test/src/DefaultConfig.cpp @@ -42,7 +42,7 @@ TEST(DefaultConfig, UrlSet) { const Config::ptr_t config = DefaultConfig::create(); - const std::string test_url = random_string(50); + const std::string test_url = random_string(); ASSERT_EQ(config, config->url(test_url)); ASSERT_EQ(config->url(), test_url); @@ -52,7 +52,7 @@ TEST(DefaultConfig, UrlClear) { using namespace wtlgo::network; const Config::ptr_t config = - DefaultConfig::create()->url(random_string(50)); + DefaultConfig::create()->url(random_string()); ASSERT_EQ(config, config->clear_url()); ASSERT_EQ(config->url(), std::nullopt); @@ -71,7 +71,7 @@ TEST(DefaultConfig, UrlCloneValue) { using namespace wtlgo::network; const Config::cptr_t config = - DefaultConfig::create()->url(random_string(50)); + DefaultConfig::create()->url(random_string()); const Config::cptr_t clone = config->clone(); ASSERT_EQ(clone->url(), config->url()); @@ -93,7 +93,7 @@ TEST(DefaultConfig, UrlMergeRight) { const Config::cptr_t lconfig = DefaultConfig::create()->clear_url(); const Config::cptr_t rconfig = - DefaultConfig::create()->url(random_string(50)); + DefaultConfig::create()->url(random_string()); const Config::cptr_t mconfig = lconfig->merge(rconfig); ASSERT_EQ(mconfig->url(), rconfig->url()); @@ -103,7 +103,7 @@ TEST(DefaultConfig, UrlMergeLeft) { using namespace wtlgo::network; const Config::cptr_t lconfig = - DefaultConfig::create()->url(random_string(50)); + DefaultConfig::create()->url(random_string()); const Config::cptr_t rconfig = DefaultConfig::create()->clear_url(); const Config::cptr_t mconfig = lconfig->merge(rconfig); @@ -114,9 +114,9 @@ TEST(DefaultConfig, UrlMergeFull) { using namespace wtlgo::network; const Config::cptr_t lconfig = - DefaultConfig::create()->url(random_string(50)); + DefaultConfig::create()->url(random_string()); const Config::cptr_t rconfig = - DefaultConfig::create()->url(random_string(50)); + DefaultConfig::create()->url(random_string()); const Config::cptr_t mconfig = lconfig->merge(rconfig); ASSERT_EQ(mconfig->url(), rconfig->url()); @@ -247,7 +247,7 @@ TEST(DefaultConfig, BaseUrlSet) { const Config::ptr_t config = DefaultConfig::create(); - const std::string test_url = random_string(50); + const std::string test_url = random_string(); ASSERT_EQ(config, config->base_url(test_url)); ASSERT_EQ(config->base_url(), test_url); @@ -257,7 +257,7 @@ TEST(DefaultConfig, BaseUrlClear) { using namespace wtlgo::network; const Config::ptr_t config = - DefaultConfig::create()->base_url(random_string(50)); + DefaultConfig::create()->base_url(random_string()); ASSERT_EQ(config, config->clear_base_url()); ASSERT_EQ(config->base_url(), std::nullopt); @@ -276,7 +276,7 @@ TEST(DefaultConfig, BaseUrlCloneValue) { using namespace wtlgo::network; const Config::cptr_t config = - DefaultConfig::create()->base_url(random_string(50)); + DefaultConfig::create()->base_url(random_string()); const Config::cptr_t clone = config->clone(); ASSERT_EQ(clone->base_url(), config->base_url()); @@ -298,7 +298,7 @@ TEST(DefaultConfig, BaseUrlMergeRight) { const Config::cptr_t lconfig = DefaultConfig::create()->clear_base_url(); const Config::cptr_t rconfig = - DefaultConfig::create()->base_url(random_string(50)); + DefaultConfig::create()->base_url(random_string()); const Config::cptr_t mconfig = lconfig->merge(rconfig); ASSERT_EQ(mconfig->base_url(), rconfig->base_url()); @@ -308,7 +308,7 @@ TEST(DefaultConfig, BaseUrlMergeLeft) { using namespace wtlgo::network; const Config::cptr_t lconfig = - DefaultConfig::create()->base_url(random_string(50)); + DefaultConfig::create()->base_url(random_string()); const Config::cptr_t rconfig = DefaultConfig::create()->clear_base_url(); const Config::cptr_t mconfig = lconfig->merge(rconfig); @@ -319,9 +319,9 @@ TEST(DefaultConfig, BaseUrlMergeFull) { using namespace wtlgo::network; const Config::cptr_t lconfig = - DefaultConfig::create()->base_url(random_string(50)); + DefaultConfig::create()->base_url(random_string()); const Config::cptr_t rconfig = - DefaultConfig::create()->base_url(random_string(50)); + DefaultConfig::create()->base_url(random_string()); const Config::cptr_t mconfig = lconfig->merge(rconfig); ASSERT_EQ(mconfig->base_url(), rconfig->base_url()); diff --git a/test/src/DefaultHttpBasicAuth.cpp b/test/src/DefaultHttpBasicAuth.cpp index 3c459c1..188a294 100644 --- a/test/src/DefaultHttpBasicAuth.cpp +++ b/test/src/DefaultHttpBasicAuth.cpp @@ -9,8 +9,8 @@ TEST(DefaultHttpBasicAuth, Create) { using namespace wtlgo::network; - const std::string test_username = random_string(50); - const std::string test_password = random_string(50); + const std::string test_username = random_string(); + const std::string test_password = random_string(); const HttpBasicAuth::cptr_t client = DefaultHttpBasicAuth::create(test_username, test_password); @@ -24,7 +24,7 @@ TEST(DefaultHttpBasicAuth, Clone) { using namespace wtlgo::network; const HttpBasicAuth::cptr_t client = - DefaultHttpBasicAuth::create(random_string(50), random_string(50)); + DefaultHttpBasicAuth::create(random_string(), random_string()); const HttpBasicAuth::cptr_t clone = client->clone(); ASSERT_NE(clone, nullptr); @@ -41,9 +41,9 @@ TEST(DefaultHttpBasicAuth, SetUsername) { using namespace wtlgo::network; const HttpBasicAuth::ptr_t client = - DefaultHttpBasicAuth::create(random_string(50), random_string(50)); + DefaultHttpBasicAuth::create(random_string(), random_string()); - const std::string test_username = random_string(50); + const std::string test_username = random_string(); ASSERT_EQ(client, client->username(test_username)); ASSERT_EQ(client->username(), test_username); } @@ -52,9 +52,9 @@ TEST(DefaultHttpBasicAuth, SetPassword) { using namespace wtlgo::network; const HttpBasicAuth::ptr_t client = - DefaultHttpBasicAuth::create(random_string(50), random_string(50)); + DefaultHttpBasicAuth::create(random_string(), random_string()); - const std::string test_password = random_string(50); + const std::string test_password = random_string(); ASSERT_EQ(client, client->password(test_password)); ASSERT_EQ(client->password(), test_password); } diff --git a/test/src/HttpHeaders.cpp b/test/src/HttpHeaders.cpp new file mode 100644 index 0000000..7693211 --- /dev/null +++ b/test/src/HttpHeaders.cpp @@ -0,0 +1,86 @@ +#include +#include "utility.hpp" + +#include +#include +#include +#include +#include +#include + +#include +#include + +TEST(HttpHeaders, Create) { + using namespace wtlgo::network; + + Headers::cptr_t headers = HttpHeaders::create(); + ASSERT_NE(headers, nullptr); +} + +TEST(HttpHeaders, Clone) { + using namespace wtlgo::network; + + Headers::ptr_t headers = HttpHeaders::create(); + for (std::size_t i = 0; i < 50; ++i) { + headers->set(random_string(), random_string()); + } + + Headers::cptr_t clone = headers->clone(); + + ASSERT_NE(clone, nullptr); + ASSERT_NE(clone, headers); + + for (const auto& header : headers->keys()) { + ASSERT_EQ(headers->get(header), clone->get(header)); + ASSERT_NE(headers->get(header)->data(), clone->get(header)->data()); + } +} + +TEST(HttpHeaders, Set) { + using namespace wtlgo::network; + + Headers::ptr_t headers = HttpHeaders::create(); + + const std::string key = random_string(); + const std::string value = random_string(); + + ASSERT_EQ(headers, headers->set(key, value)); + ASSERT_NE(headers->get(key), std::nullopt); + ASSERT_EQ(headers->get(key), value); +} + +TEST(HttpHeaders, Erase) { + using namespace wtlgo::network; + + const std::string key = random_string(); + Headers::ptr_t headers = HttpHeaders::create()->set(key, random_string()); + + ASSERT_EQ(headers, headers->erase(key)); + ASSERT_EQ(headers->get(key), std::nullopt); +} + +TEST(HttpHeaders, Keys) { + using namespace wtlgo::network; + + const std::set keys = [] { + std::set res; + std::generate_n(std::inserter(res, res.begin()), + random_unsigned() % 100, + []() { return random_string(); }); + return res; + }(); + + Headers::ptr_t headers = HttpHeaders::create(); + for (const auto& header : keys) { + headers->set(header, random_string()); + } + + const std::set ref_keys = [&keys] { + std::set res; + std::copy(keys.cbegin(), keys.cend(), std::inserter(res, res.begin())); + return res; + }(); + + ASSERT_EQ(ref_keys, headers->keys()); +} diff --git a/test/src/utility.hpp b/test/src/utility.hpp index 41f4588..d975f54 100644 --- a/test/src/utility.hpp +++ b/test/src/utility.hpp @@ -5,7 +5,7 @@ extern const std::string test_server; -std::string random_string(size_t max_length, bool exact = false); +std::string random_string(size_t max_length = 100, bool exact = false); unsigned random_unsigned(); #endif From 0d58e8781e672f657b3ec0d1ab30638d879620d9 Mon Sep 17 00:00:00 2001 From: wtlgo Date: Tue, 31 Jan 2023 18:11:50 +0300 Subject: [PATCH 34/46] Apply appropriate access modifier --- include/wtlgo/network/HttpHeaders.hpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/include/wtlgo/network/HttpHeaders.hpp b/include/wtlgo/network/HttpHeaders.hpp index 888a45b..9741245 100644 --- a/include/wtlgo/network/HttpHeaders.hpp +++ b/include/wtlgo/network/HttpHeaders.hpp @@ -24,11 +24,13 @@ class HttpHeaders : public Headers, Headers::ptr_t set(Headers::key_ref_t header, value_ref_t value) override; Headers::ptr_t erase(Headers::key_ref_t header) override; +protected: + HttpHeaders(); + private: struct Impl; const std::unique_ptr impl; - HttpHeaders(); HttpHeaders(const std::unique_ptr& impl); }; } From 1b06660736db6014bf74a92efe09317d92e9eed1 Mon Sep 17 00:00:00 2001 From: wtlgo Date: Tue, 31 Jan 2023 18:14:55 +0300 Subject: [PATCH 35/46] Rename HttpBasicAuth to Auth --- CMakeLists.txt | 2 +- .../network/{HttpBasicAuth.hpp => Auth.hpp} | 12 +++---- .../wtlgo/network/DefaultHttpBasicAuth.hpp | 22 ++++++------ src/DefaultHttpBasicAuth.cpp | 36 +++++++++---------- test/src/DefaultHttpBasicAuth.cpp | 12 +++---- 5 files changed, 42 insertions(+), 42 deletions(-) rename include/wtlgo/network/{HttpBasicAuth.hpp => Auth.hpp} (62%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9a1ee7e..e073e09 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,7 +13,7 @@ find_package(CURL REQUIRED) set(PUBLIC_HEADERS "include/wtlgo/NetworkOld.hpp" - "include/wtlgo/network/HttpBasicAuth.hpp" + "include/wtlgo/network/Auth.hpp" "include/wtlgo/network/DefaultHttpBasicAuth.hpp" "include/wtlgo/network/HttpMethod.hpp" diff --git a/include/wtlgo/network/HttpBasicAuth.hpp b/include/wtlgo/network/Auth.hpp similarity index 62% rename from include/wtlgo/network/HttpBasicAuth.hpp rename to include/wtlgo/network/Auth.hpp index 8bf510a..c675d5a 100644 --- a/include/wtlgo/network/HttpBasicAuth.hpp +++ b/include/wtlgo/network/Auth.hpp @@ -1,19 +1,19 @@ -#ifndef __WTLGO__NETWORK__HTTP_BASIC_AUTH__ -#define __WTLGO__NETWORK__HTTP_BASIC_AUTH__ +#ifndef __WTLGO__NETWORK__AUTH__ +#define __WTLGO__NETWORK__AUTH__ #include #include namespace wtlgo { namespace network { -struct HttpBasicAuth { - using ptr_t = std::shared_ptr; - using cptr_t = std::shared_ptr; +struct Auth { + using ptr_t = std::shared_ptr; + using cptr_t = std::shared_ptr; using username_ref_t = std::string_view; using password_ref_t = std::string_view; - virtual ~HttpBasicAuth() = default; + virtual ~Auth() = default; virtual ptr_t clone() const = 0; diff --git a/include/wtlgo/network/DefaultHttpBasicAuth.hpp b/include/wtlgo/network/DefaultHttpBasicAuth.hpp index 9304e52..0d81481 100644 --- a/include/wtlgo/network/DefaultHttpBasicAuth.hpp +++ b/include/wtlgo/network/DefaultHttpBasicAuth.hpp @@ -3,12 +3,12 @@ #include -#include +#include namespace wtlgo { namespace network { class DefaultHttpBasicAuth - : public HttpBasicAuth, + : public Auth, public std::enable_shared_from_this { public: using ptr_t = std::shared_ptr; @@ -17,20 +17,20 @@ class DefaultHttpBasicAuth virtual ~DefaultHttpBasicAuth(); [[nodiscard]] static DefaultHttpBasicAuth::ptr_t create( - HttpBasicAuth::username_ref_t username, - HttpBasicAuth::password_ref_t password); + Auth::username_ref_t username, + Auth::password_ref_t password); - HttpBasicAuth::ptr_t clone() const override; + Auth::ptr_t clone() const override; - HttpBasicAuth::username_ref_t username() const override; - HttpBasicAuth::ptr_t username(HttpBasicAuth::username_ref_t) override; + Auth::username_ref_t username() const override; + Auth::ptr_t username(Auth::username_ref_t) override; - HttpBasicAuth::password_ref_t password() const override; - HttpBasicAuth::ptr_t password(HttpBasicAuth::password_ref_t) override; + Auth::password_ref_t password() const override; + Auth::ptr_t password(Auth::password_ref_t) override; protected: - DefaultHttpBasicAuth(HttpBasicAuth::username_ref_t username, - HttpBasicAuth::password_ref_t password); + DefaultHttpBasicAuth(Auth::username_ref_t username, + Auth::password_ref_t password); private: struct Impl; diff --git a/src/DefaultHttpBasicAuth.cpp b/src/DefaultHttpBasicAuth.cpp index 260a77e..916ff62 100644 --- a/src/DefaultHttpBasicAuth.cpp +++ b/src/DefaultHttpBasicAuth.cpp @@ -2,7 +2,7 @@ #include #include -#include +#include #include using namespace wtlgo::network; @@ -15,17 +15,17 @@ struct DefaultHttpBasicAuth::Impl { public: Impl() = default; Impl(const Impl&) = default; - Impl(const HttpBasicAuth::username_ref_t username, - const HttpBasicAuth::password_ref_t password) + Impl(const Auth::username_ref_t username, + const Auth::password_ref_t password) : _username{username}, _password{password} {} - HttpBasicAuth::username_ref_t username() const { return _username; } - void username(const HttpBasicAuth::username_ref_t username) { + Auth::username_ref_t username() const { return _username; } + void username(const Auth::username_ref_t username) { _username = username; } - HttpBasicAuth::password_ref_t password() const { return _password; } - void password(const HttpBasicAuth::password_ref_t password) { + Auth::password_ref_t password() const { return _password; } + void password(const Auth::password_ref_t password) { _password = password; } }; @@ -33,40 +33,40 @@ struct DefaultHttpBasicAuth::Impl { DefaultHttpBasicAuth::~DefaultHttpBasicAuth() = default; DefaultHttpBasicAuth::ptr_t DefaultHttpBasicAuth::create( - const HttpBasicAuth::username_ref_t username, - const HttpBasicAuth::password_ref_t password) { + const Auth::username_ref_t username, + const Auth::password_ref_t password) { return std::shared_ptr( new DefaultHttpBasicAuth{username, password}); } -HttpBasicAuth::ptr_t DefaultHttpBasicAuth::clone() const { +Auth::ptr_t DefaultHttpBasicAuth::clone() const { return std::shared_ptr( new DefaultHttpBasicAuth{impl}); } -HttpBasicAuth::username_ref_t DefaultHttpBasicAuth::username() const { +Auth::username_ref_t DefaultHttpBasicAuth::username() const { return impl->username(); } -HttpBasicAuth::ptr_t DefaultHttpBasicAuth::username( - const HttpBasicAuth::username_ref_t username) { +Auth::ptr_t DefaultHttpBasicAuth::username( + const Auth::username_ref_t username) { impl->username(username); return shared_from_this(); } -HttpBasicAuth::password_ref_t DefaultHttpBasicAuth::password() const { +Auth::password_ref_t DefaultHttpBasicAuth::password() const { return impl->password(); } -HttpBasicAuth::ptr_t DefaultHttpBasicAuth::password( - const HttpBasicAuth::password_ref_t password) { +Auth::ptr_t DefaultHttpBasicAuth::password( + const Auth::password_ref_t password) { impl->password(password); return shared_from_this(); } DefaultHttpBasicAuth::DefaultHttpBasicAuth( - const HttpBasicAuth::username_ref_t username, - const HttpBasicAuth::password_ref_t password) + const Auth::username_ref_t username, + const Auth::password_ref_t password) : impl{std::make_unique(username, password)} {} DefaultHttpBasicAuth::DefaultHttpBasicAuth(const std::unique_ptr& impl) diff --git a/test/src/DefaultHttpBasicAuth.cpp b/test/src/DefaultHttpBasicAuth.cpp index 188a294..13e618f 100644 --- a/test/src/DefaultHttpBasicAuth.cpp +++ b/test/src/DefaultHttpBasicAuth.cpp @@ -3,7 +3,7 @@ #include -#include +#include #include TEST(DefaultHttpBasicAuth, Create) { @@ -12,7 +12,7 @@ TEST(DefaultHttpBasicAuth, Create) { const std::string test_username = random_string(); const std::string test_password = random_string(); - const HttpBasicAuth::cptr_t client = + const Auth::cptr_t client = DefaultHttpBasicAuth::create(test_username, test_password); ASSERT_NE(client, nullptr); @@ -23,10 +23,10 @@ TEST(DefaultHttpBasicAuth, Create) { TEST(DefaultHttpBasicAuth, Clone) { using namespace wtlgo::network; - const HttpBasicAuth::cptr_t client = + const Auth::cptr_t client = DefaultHttpBasicAuth::create(random_string(), random_string()); - const HttpBasicAuth::cptr_t clone = client->clone(); + const Auth::cptr_t clone = client->clone(); ASSERT_NE(clone, nullptr); ASSERT_NE(clone, client); @@ -40,7 +40,7 @@ TEST(DefaultHttpBasicAuth, Clone) { TEST(DefaultHttpBasicAuth, SetUsername) { using namespace wtlgo::network; - const HttpBasicAuth::ptr_t client = + const Auth::ptr_t client = DefaultHttpBasicAuth::create(random_string(), random_string()); const std::string test_username = random_string(); @@ -51,7 +51,7 @@ TEST(DefaultHttpBasicAuth, SetUsername) { TEST(DefaultHttpBasicAuth, SetPassword) { using namespace wtlgo::network; - const HttpBasicAuth::ptr_t client = + const Auth::ptr_t client = DefaultHttpBasicAuth::create(random_string(), random_string()); const std::string test_password = random_string(); From 75e0fa8c9a46da2860e1ab5149ada54052f2a37a Mon Sep 17 00:00:00 2001 From: wtlgo Date: Tue, 31 Jan 2023 18:28:23 +0300 Subject: [PATCH 36/46] Rename DefaultHttpBasicAuth to HttpBasicAuth --- CMakeLists.txt | 4 +- .../wtlgo/network/DefaultHttpBasicAuth.hpp | 46 ------------------- include/wtlgo/network/HttpBasicAuth.hpp | 41 +++++++++++++++++ ...ultHttpBasicAuth.cpp => HttpBasicAuth.cpp} | 30 ++++++------ ...ultHttpBasicAuth.cpp => HttpBasicAuth.cpp} | 18 ++++---- 5 files changed, 67 insertions(+), 72 deletions(-) delete mode 100644 include/wtlgo/network/DefaultHttpBasicAuth.hpp create mode 100644 include/wtlgo/network/HttpBasicAuth.hpp rename src/{DefaultHttpBasicAuth.cpp => HttpBasicAuth.cpp} (62%) rename test/src/{DefaultHttpBasicAuth.cpp => HttpBasicAuth.cpp} (72%) diff --git a/CMakeLists.txt b/CMakeLists.txt index e073e09..bacdd98 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,7 +14,7 @@ set(PUBLIC_HEADERS "include/wtlgo/NetworkOld.hpp" "include/wtlgo/network/Auth.hpp" - "include/wtlgo/network/DefaultHttpBasicAuth.hpp" + "include/wtlgo/network/HttpBasicAuth.hpp" "include/wtlgo/network/HttpMethod.hpp" @@ -27,7 +27,7 @@ set(PUBLIC_HEADERS set(SOURCES "src/NetworkOld.cpp" - "src/DefaultHttpBasicAuth.cpp" + "src/HttpBasicAuth.cpp" "src/DefaultConfig.cpp" "src/HttpHeaders.cpp" diff --git a/include/wtlgo/network/DefaultHttpBasicAuth.hpp b/include/wtlgo/network/DefaultHttpBasicAuth.hpp deleted file mode 100644 index 0d81481..0000000 --- a/include/wtlgo/network/DefaultHttpBasicAuth.hpp +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef __WTLGO__NETWORK__DEFAULT_HTTP_BASIC_AUTH__ -#define __WTLGO__NETWORK__DEFAULT_HTTP_BASIC_AUTH__ - -#include - -#include - -namespace wtlgo { -namespace network { -class DefaultHttpBasicAuth - : public Auth, - public std::enable_shared_from_this { -public: - using ptr_t = std::shared_ptr; - using cptr_t = std::shared_ptr; - - virtual ~DefaultHttpBasicAuth(); - - [[nodiscard]] static DefaultHttpBasicAuth::ptr_t create( - Auth::username_ref_t username, - Auth::password_ref_t password); - - Auth::ptr_t clone() const override; - - Auth::username_ref_t username() const override; - Auth::ptr_t username(Auth::username_ref_t) override; - - Auth::password_ref_t password() const override; - Auth::ptr_t password(Auth::password_ref_t) override; - -protected: - DefaultHttpBasicAuth(Auth::username_ref_t username, - Auth::password_ref_t password); - -private: - struct Impl; - const std::unique_ptr impl; - - DefaultHttpBasicAuth(const std::unique_ptr&); -}; - -using DHttpBasicAuth = DefaultHttpBasicAuth; -} -} - -#endif diff --git a/include/wtlgo/network/HttpBasicAuth.hpp b/include/wtlgo/network/HttpBasicAuth.hpp new file mode 100644 index 0000000..f94955b --- /dev/null +++ b/include/wtlgo/network/HttpBasicAuth.hpp @@ -0,0 +1,41 @@ +#ifndef __WTLGO__NETWORK__DEFAULT_HTTP_BASIC_AUTH__ +#define __WTLGO__NETWORK__DEFAULT_HTTP_BASIC_AUTH__ + +#include + +#include + +namespace wtlgo { +namespace network { +class HttpBasicAuth : public Auth, + public std::enable_shared_from_this { +public: + using ptr_t = std::shared_ptr; + using cptr_t = std::shared_ptr; + + virtual ~HttpBasicAuth(); + + [[nodiscard]] static HttpBasicAuth::ptr_t create( + Auth::username_ref_t username, Auth::password_ref_t password); + + Auth::ptr_t clone() const override; + + Auth::username_ref_t username() const override; + Auth::ptr_t username(Auth::username_ref_t) override; + + Auth::password_ref_t password() const override; + Auth::ptr_t password(Auth::password_ref_t) override; + +protected: + HttpBasicAuth(Auth::username_ref_t username, Auth::password_ref_t password); + +private: + struct Impl; + const std::unique_ptr impl; + + HttpBasicAuth(const std::unique_ptr&); +}; +} +} + +#endif diff --git a/src/DefaultHttpBasicAuth.cpp b/src/HttpBasicAuth.cpp similarity index 62% rename from src/DefaultHttpBasicAuth.cpp rename to src/HttpBasicAuth.cpp index 916ff62..5f6adfb 100644 --- a/src/DefaultHttpBasicAuth.cpp +++ b/src/HttpBasicAuth.cpp @@ -3,11 +3,11 @@ #include #include -#include +#include using namespace wtlgo::network; -struct DefaultHttpBasicAuth::Impl { +struct HttpBasicAuth::Impl { private: std::string _username; std::string _password; @@ -30,44 +30,44 @@ struct DefaultHttpBasicAuth::Impl { } }; -DefaultHttpBasicAuth::~DefaultHttpBasicAuth() = default; +HttpBasicAuth::~HttpBasicAuth() = default; -DefaultHttpBasicAuth::ptr_t DefaultHttpBasicAuth::create( +HttpBasicAuth::ptr_t HttpBasicAuth::create( const Auth::username_ref_t username, const Auth::password_ref_t password) { - return std::shared_ptr( - new DefaultHttpBasicAuth{username, password}); + return std::shared_ptr( + new HttpBasicAuth{username, password}); } -Auth::ptr_t DefaultHttpBasicAuth::clone() const { - return std::shared_ptr( - new DefaultHttpBasicAuth{impl}); +Auth::ptr_t HttpBasicAuth::clone() const { + return std::shared_ptr( + new HttpBasicAuth{impl}); } -Auth::username_ref_t DefaultHttpBasicAuth::username() const { +Auth::username_ref_t HttpBasicAuth::username() const { return impl->username(); } -Auth::ptr_t DefaultHttpBasicAuth::username( +Auth::ptr_t HttpBasicAuth::username( const Auth::username_ref_t username) { impl->username(username); return shared_from_this(); } -Auth::password_ref_t DefaultHttpBasicAuth::password() const { +Auth::password_ref_t HttpBasicAuth::password() const { return impl->password(); } -Auth::ptr_t DefaultHttpBasicAuth::password( +Auth::ptr_t HttpBasicAuth::password( const Auth::password_ref_t password) { impl->password(password); return shared_from_this(); } -DefaultHttpBasicAuth::DefaultHttpBasicAuth( +HttpBasicAuth::HttpBasicAuth( const Auth::username_ref_t username, const Auth::password_ref_t password) : impl{std::make_unique(username, password)} {} -DefaultHttpBasicAuth::DefaultHttpBasicAuth(const std::unique_ptr& impl) +HttpBasicAuth::HttpBasicAuth(const std::unique_ptr& impl) : impl{std::make_unique(*impl)} {} diff --git a/test/src/DefaultHttpBasicAuth.cpp b/test/src/HttpBasicAuth.cpp similarity index 72% rename from test/src/DefaultHttpBasicAuth.cpp rename to test/src/HttpBasicAuth.cpp index 13e618f..be37536 100644 --- a/test/src/DefaultHttpBasicAuth.cpp +++ b/test/src/HttpBasicAuth.cpp @@ -4,27 +4,27 @@ #include #include -#include +#include -TEST(DefaultHttpBasicAuth, Create) { +TEST(HttpBasicAuth, Create) { using namespace wtlgo::network; const std::string test_username = random_string(); const std::string test_password = random_string(); const Auth::cptr_t client = - DefaultHttpBasicAuth::create(test_username, test_password); + HttpBasicAuth::create(test_username, test_password); ASSERT_NE(client, nullptr); ASSERT_EQ(client->username(), test_username); ASSERT_EQ(client->password(), test_password); } -TEST(DefaultHttpBasicAuth, Clone) { +TEST(HttpBasicAuth, Clone) { using namespace wtlgo::network; const Auth::cptr_t client = - DefaultHttpBasicAuth::create(random_string(), random_string()); + HttpBasicAuth::create(random_string(), random_string()); const Auth::cptr_t clone = client->clone(); ASSERT_NE(clone, nullptr); @@ -37,22 +37,22 @@ TEST(DefaultHttpBasicAuth, Clone) { ASSERT_NE(client->password().data(), clone->password().data()); } -TEST(DefaultHttpBasicAuth, SetUsername) { +TEST(HttpBasicAuth, SetUsername) { using namespace wtlgo::network; const Auth::ptr_t client = - DefaultHttpBasicAuth::create(random_string(), random_string()); + HttpBasicAuth::create(random_string(), random_string()); const std::string test_username = random_string(); ASSERT_EQ(client, client->username(test_username)); ASSERT_EQ(client->username(), test_username); } -TEST(DefaultHttpBasicAuth, SetPassword) { +TEST(HttpBasicAuth, SetPassword) { using namespace wtlgo::network; const Auth::ptr_t client = - DefaultHttpBasicAuth::create(random_string(), random_string()); + HttpBasicAuth::create(random_string(), random_string()); const std::string test_password = random_string(); ASSERT_EQ(client, client->password(test_password)); From 4d6c8f3c49a6a309dd64ee26d56c525123638c6e Mon Sep 17 00:00:00 2001 From: wtlgo Date: Tue, 31 Jan 2023 18:45:22 +0300 Subject: [PATCH 37/46] Rename DefaultConfig to ClientConfig --- CMakeLists.txt | 4 +- .../{DefaultConfig.hpp => ClientConfig.hpp} | 20 ++- src/{DefaultConfig.cpp => ClientConfig.cpp} | 40 ++--- src/internal/CopyOnWriteConfig.cpp | 6 +- src/internal/MergedConfig.cpp | 4 +- .../{DefaultConfig.cpp => ClientConfig.cpp} | 140 +++++++++--------- 6 files changed, 106 insertions(+), 108 deletions(-) rename include/wtlgo/network/{DefaultConfig.hpp => ClientConfig.hpp} (63%) rename src/{DefaultConfig.cpp => ClientConfig.cpp} (57%) rename test/src/{DefaultConfig.cpp => ClientConfig.cpp} (62%) diff --git a/CMakeLists.txt b/CMakeLists.txt index bacdd98..e412c43 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,7 +19,7 @@ set(PUBLIC_HEADERS "include/wtlgo/network/HttpMethod.hpp" "include/wtlgo/network/Config.hpp" - "include/wtlgo/network/DefaultConfig.hpp" + "include/wtlgo/network/ClientConfig.hpp" "include/wtlgo/network/Headers.hpp" "include/wtlgo/network/HttpHeaders.hpp" @@ -28,7 +28,7 @@ set(PUBLIC_HEADERS set(SOURCES "src/NetworkOld.cpp" "src/HttpBasicAuth.cpp" - "src/DefaultConfig.cpp" + "src/ClientConfig.cpp" "src/HttpHeaders.cpp" "src/internal/MergedConfig.hpp" diff --git a/include/wtlgo/network/DefaultConfig.hpp b/include/wtlgo/network/ClientConfig.hpp similarity index 63% rename from include/wtlgo/network/DefaultConfig.hpp rename to include/wtlgo/network/ClientConfig.hpp index 31c18e3..d34a667 100644 --- a/include/wtlgo/network/DefaultConfig.hpp +++ b/include/wtlgo/network/ClientConfig.hpp @@ -7,16 +7,16 @@ namespace wtlgo { namespace network { -class DefaultConfig : public Config, - public std::enable_shared_from_this { +class ClientConfig : public Config, + public std::enable_shared_from_this { public: - using ptr_t = std::shared_ptr; - using cptr_t = std::shared_ptr; + using ptr_t = std::shared_ptr; + using cptr_t = std::shared_ptr; - virtual ~DefaultConfig(); + virtual ~ClientConfig(); - [[nodiscard]] static DefaultConfig::ptr_t create(); - [[nodiscard]] static DefaultConfig::ptr_t clone(Config::cptr_t); + [[nodiscard]] static ClientConfig::ptr_t create(); + [[nodiscard]] static ClientConfig::ptr_t clone(Config::cptr_t); Config::ptr_t clone() const override; Config::ptr_t merge(Config::cptr_t) const override; @@ -34,15 +34,13 @@ class DefaultConfig : public Config, Config::ptr_t clear_base_url() override; protected: - DefaultConfig(); - DefaultConfig(const Config::cptr_t); + ClientConfig(); + ClientConfig(const Config::cptr_t); private: struct Impl; const std::unique_ptr impl; }; - -using DConfig = DefaultConfig; } } diff --git a/src/DefaultConfig.cpp b/src/ClientConfig.cpp similarity index 57% rename from src/DefaultConfig.cpp rename to src/ClientConfig.cpp index f38cf87..0ce6b2e 100644 --- a/src/DefaultConfig.cpp +++ b/src/ClientConfig.cpp @@ -7,11 +7,11 @@ #include "./internal/MergedConfig.hpp" #include -#include +#include using namespace wtlgo::network; -struct DefaultConfig::Impl { +struct ClientConfig::Impl { private: std::optional _url; Config::method_opt_t _method; @@ -38,61 +38,61 @@ struct DefaultConfig::Impl { void clear_base_url() { _base_url = std::nullopt; } }; -DefaultConfig::~DefaultConfig() = default; +ClientConfig::~ClientConfig() = default; -DefaultConfig::ptr_t DefaultConfig::create() { - return std::shared_ptr{new DefaultConfig{}}; +ClientConfig::ptr_t ClientConfig::create() { + return std::shared_ptr{new ClientConfig{}}; } -DefaultConfig::ptr_t DefaultConfig::clone(const Config::cptr_t config) { - return std::shared_ptr{new DefaultConfig{config}}; +ClientConfig::ptr_t ClientConfig::clone(const Config::cptr_t config) { + return std::shared_ptr{new ClientConfig{config}}; } -Config::ptr_t DefaultConfig::clone() const { return clone(shared_from_this()); } +Config::ptr_t ClientConfig::clone() const { return clone(shared_from_this()); } -Config::ptr_t DefaultConfig::merge(const Config::cptr_t rconfig) const { +Config::ptr_t ClientConfig::merge(const Config::cptr_t rconfig) const { return internal::MergedConfig::merge(shared_from_this(), rconfig); } -Config::url_opt_ref_t DefaultConfig::url() const { return impl->url(); } +Config::url_opt_ref_t ClientConfig::url() const { return impl->url(); } -Config::ptr_t DefaultConfig::url(const Config::url_ref_t url) { +Config::ptr_t ClientConfig::url(const Config::url_ref_t url) { impl->url(url); return shared_from_this(); } -Config::ptr_t DefaultConfig::clear_url() { +Config::ptr_t ClientConfig::clear_url() { impl->clear_url(); return shared_from_this(); } -Config::method_opt_t DefaultConfig::method() const { return impl->method(); } +Config::method_opt_t ClientConfig::method() const { return impl->method(); } -Config::ptr_t DefaultConfig::method(const Config::method_t method) { +Config::ptr_t ClientConfig::method(const Config::method_t method) { impl->method(method); return shared_from_this(); } -Config::ptr_t DefaultConfig::clear_method() { +Config::ptr_t ClientConfig::clear_method() { impl->clear_method(); return shared_from_this(); } -Config::url_opt_ref_t DefaultConfig::base_url() const { +Config::url_opt_ref_t ClientConfig::base_url() const { return impl->base_url(); } -Config::ptr_t DefaultConfig::base_url(const Config::url_ref_t url) { +Config::ptr_t ClientConfig::base_url(const Config::url_ref_t url) { impl->base_url(url); return shared_from_this(); } -Config::ptr_t DefaultConfig::clear_base_url() { +Config::ptr_t ClientConfig::clear_base_url() { impl->clear_base_url(); return shared_from_this(); } -DefaultConfig::DefaultConfig() : impl{std::make_unique()} {} +ClientConfig::ClientConfig() : impl{std::make_unique()} {} -DefaultConfig::DefaultConfig(const Config::cptr_t config) +ClientConfig::ClientConfig(const Config::cptr_t config) : impl{std::make_unique(config)} {} diff --git a/src/internal/CopyOnWriteConfig.cpp b/src/internal/CopyOnWriteConfig.cpp index 1f5645d..2631454 100644 --- a/src/internal/CopyOnWriteConfig.cpp +++ b/src/internal/CopyOnWriteConfig.cpp @@ -1,6 +1,6 @@ #include -#include +#include #include "./MergedConfig.hpp" #include "./CopyOnWriteConfig.hpp" @@ -16,7 +16,7 @@ struct CopyOnWriteConfig::Impl { void liquify() { if (!solid) return; - liquid = DefaultConfig::clone(solid); + liquid = ClientConfig::clone(solid); solid = nullptr; } @@ -49,7 +49,7 @@ CopyOnWriteConfig::ptr_t CopyOnWriteConfig::adapt(const Config::cptr_t config) { } Config::ptr_t CopyOnWriteConfig::clone() const { - return DefaultConfig::clone(shared_from_this()); + return ClientConfig::clone(shared_from_this()); } Config::ptr_t CopyOnWriteConfig::merge(const Config::cptr_t rconfig) const { diff --git a/src/internal/MergedConfig.cpp b/src/internal/MergedConfig.cpp index c688fb3..3de57f3 100644 --- a/src/internal/MergedConfig.cpp +++ b/src/internal/MergedConfig.cpp @@ -3,7 +3,7 @@ #include "./MergedConfig.hpp" #include "./CopyOnWriteConfig.hpp" -#include +#include using namespace wtlgo::network; using namespace wtlgo::network::internal; @@ -69,7 +69,7 @@ MergedConfig::ptr_t MergedConfig::merge(const Config::cptr_t lconfig, } Config::ptr_t MergedConfig::clone() const { - return DefaultConfig::clone(shared_from_this()); + return ClientConfig::clone(shared_from_this()); } Config::ptr_t MergedConfig::merge(const Config::cptr_t rconfig) const { diff --git a/test/src/DefaultConfig.cpp b/test/src/ClientConfig.cpp similarity index 62% rename from test/src/DefaultConfig.cpp rename to test/src/ClientConfig.cpp index 126cd81..f868d09 100644 --- a/test/src/DefaultConfig.cpp +++ b/test/src/ClientConfig.cpp @@ -6,30 +6,30 @@ #include #include -#include +#include -TEST(DefaultConfig, Create) { +TEST(ClientConfig, Create) { using namespace wtlgo::network; - const Config::cptr_t config = DefaultConfig::create(); + const Config::cptr_t config = ClientConfig::create(); ASSERT_NE(config, nullptr); } -TEST(DefaultConfig, Clone) { +TEST(ClientConfig, Clone) { using namespace wtlgo::network; - const Config::cptr_t config = DefaultConfig::create(); + const Config::cptr_t config = ClientConfig::create(); const Config::cptr_t clone = config->clone(); ASSERT_NE(clone, nullptr); ASSERT_NE(clone, config); } -TEST(DefaultConfig, Merge) { +TEST(ClientConfig, Merge) { using namespace wtlgo::network; - const Config::cptr_t lconfig = DefaultConfig::create(); - const Config::cptr_t rconfig = DefaultConfig::create(); + const Config::cptr_t lconfig = ClientConfig::create(); + const Config::cptr_t rconfig = ClientConfig::create(); const Config::cptr_t mconfig = lconfig->merge(rconfig); ASSERT_NE(mconfig, nullptr); @@ -37,10 +37,10 @@ TEST(DefaultConfig, Merge) { ASSERT_NE(mconfig, lconfig); } -TEST(DefaultConfig, UrlSet) { +TEST(ClientConfig, UrlSet) { using namespace wtlgo::network; - const Config::ptr_t config = DefaultConfig::create(); + const Config::ptr_t config = ClientConfig::create(); const std::string test_url = random_string(); @@ -48,91 +48,91 @@ TEST(DefaultConfig, UrlSet) { ASSERT_EQ(config->url(), test_url); } -TEST(DefaultConfig, UrlClear) { +TEST(ClientConfig, UrlClear) { using namespace wtlgo::network; const Config::ptr_t config = - DefaultConfig::create()->url(random_string()); + ClientConfig::create()->url(random_string()); ASSERT_EQ(config, config->clear_url()); ASSERT_EQ(config->url(), std::nullopt); } -TEST(DefaultConfig, UrlCloneEmpty) { +TEST(ClientConfig, UrlCloneEmpty) { using namespace wtlgo::network; - const Config::cptr_t config = DefaultConfig::create()->clear_url(); + const Config::cptr_t config = ClientConfig::create()->clear_url(); const Config::cptr_t clone = config->clone(); ASSERT_EQ(clone->url(), std::nullopt); } -TEST(DefaultConfig, UrlCloneValue) { +TEST(ClientConfig, UrlCloneValue) { using namespace wtlgo::network; const Config::cptr_t config = - DefaultConfig::create()->url(random_string()); + ClientConfig::create()->url(random_string()); const Config::cptr_t clone = config->clone(); ASSERT_EQ(clone->url(), config->url()); ASSERT_NE(clone->url()->data(), config->url()->data()); } -TEST(DefaultConfig, UrlMergeEmpty) { +TEST(ClientConfig, UrlMergeEmpty) { using namespace wtlgo::network; - const Config::cptr_t lconfig = DefaultConfig::create()->clear_url(); - const Config::cptr_t rconfig = DefaultConfig::create()->clear_url(); + const Config::cptr_t lconfig = ClientConfig::create()->clear_url(); + const Config::cptr_t rconfig = ClientConfig::create()->clear_url(); const Config::cptr_t mconfig = lconfig->merge(rconfig); ASSERT_EQ(mconfig->url(), std::nullopt); } -TEST(DefaultConfig, UrlMergeRight) { +TEST(ClientConfig, UrlMergeRight) { using namespace wtlgo::network; - const Config::cptr_t lconfig = DefaultConfig::create()->clear_url(); + const Config::cptr_t lconfig = ClientConfig::create()->clear_url(); const Config::cptr_t rconfig = - DefaultConfig::create()->url(random_string()); + ClientConfig::create()->url(random_string()); const Config::cptr_t mconfig = lconfig->merge(rconfig); ASSERT_EQ(mconfig->url(), rconfig->url()); } -TEST(DefaultConfig, UrlMergeLeft) { +TEST(ClientConfig, UrlMergeLeft) { using namespace wtlgo::network; const Config::cptr_t lconfig = - DefaultConfig::create()->url(random_string()); - const Config::cptr_t rconfig = DefaultConfig::create()->clear_url(); + ClientConfig::create()->url(random_string()); + const Config::cptr_t rconfig = ClientConfig::create()->clear_url(); const Config::cptr_t mconfig = lconfig->merge(rconfig); ASSERT_EQ(mconfig->url(), lconfig->url()); } -TEST(DefaultConfig, UrlMergeFull) { +TEST(ClientConfig, UrlMergeFull) { using namespace wtlgo::network; const Config::cptr_t lconfig = - DefaultConfig::create()->url(random_string()); + ClientConfig::create()->url(random_string()); const Config::cptr_t rconfig = - DefaultConfig::create()->url(random_string()); + ClientConfig::create()->url(random_string()); const Config::cptr_t mconfig = lconfig->merge(rconfig); ASSERT_EQ(mconfig->url(), rconfig->url()); } -TEST(DefaultConfig, MethodDefault) { +TEST(ClientConfig, MethodDefault) { using namespace wtlgo::network; - const Config::cptr_t config = DefaultConfig::create(); + const Config::cptr_t config = ClientConfig::create(); ASSERT_EQ(config->method(), std::nullopt); } -TEST(DefaultConfig, MethodSet) { +TEST(ClientConfig, MethodSet) { using namespace wtlgo::network; - const Config::ptr_t config = DefaultConfig::create(); + const Config::ptr_t config = ClientConfig::create(); for (const HttpMethod test_method : {HttpMethod::GET, HttpMethod::POST, HttpMethod::PATCH, HttpMethod::PUT, @@ -142,99 +142,99 @@ TEST(DefaultConfig, MethodSet) { } } -TEST(DefaultConfig, MethodClear) { +TEST(ClientConfig, MethodClear) { using namespace wtlgo::network; for (const HttpMethod test_method : {HttpMethod::GET, HttpMethod::POST, HttpMethod::PATCH, HttpMethod::PUT, HttpMethod::DELETE}) { const Config::ptr_t config = - DefaultConfig::create()->method(test_method); + ClientConfig::create()->method(test_method); ASSERT_EQ(config, config->clear_method()); ASSERT_EQ(config->method(), std::nullopt); } } -TEST(DefaultConfig, MethodCloneEmpty) { +TEST(ClientConfig, MethodCloneEmpty) { using namespace wtlgo::network; - const Config::cptr_t config = DefaultConfig::create()->clear_method(); + const Config::cptr_t config = ClientConfig::create()->clear_method(); const Config::cptr_t clone = config->clone(); ASSERT_EQ(clone->method(), std::nullopt); } -TEST(DefaultConfig, MethodCloneValue) { +TEST(ClientConfig, MethodCloneValue) { using namespace wtlgo::network; for (const HttpMethod test_method : {HttpMethod::GET, HttpMethod::POST, HttpMethod::PATCH, HttpMethod::PUT, HttpMethod::DELETE}) { const Config::cptr_t config = - DefaultConfig::create()->method(test_method); + ClientConfig::create()->method(test_method); const Config::cptr_t clone = config->clone(); ASSERT_EQ(clone->method(), test_method); } } -TEST(DefaultConfig, MethodMergeEmpty) { +TEST(ClientConfig, MethodMergeEmpty) { using namespace wtlgo::network; - const Config::cptr_t lconfig = DefaultConfig::create()->clear_method(); - const Config::cptr_t rconfig = DefaultConfig::create()->clear_method(); + const Config::cptr_t lconfig = ClientConfig::create()->clear_method(); + const Config::cptr_t rconfig = ClientConfig::create()->clear_method(); const Config::cptr_t mconfig = lconfig->merge(rconfig); ASSERT_EQ(rconfig->method(), std::nullopt); } -TEST(DefaultConfig, MethodMergeLeft) { +TEST(ClientConfig, MethodMergeLeft) { using namespace wtlgo::network; - const Config::cptr_t rconfig = DefaultConfig::create()->clear_method(); + const Config::cptr_t rconfig = ClientConfig::create()->clear_method(); for (const HttpMethod test_method : {HttpMethod::GET, HttpMethod::POST, HttpMethod::PATCH, HttpMethod::PUT, HttpMethod::DELETE}) { const Config::cptr_t lconfig = - DefaultConfig::create()->method(test_method); + ClientConfig::create()->method(test_method); const Config::cptr_t mconfig = lconfig->merge(rconfig); ASSERT_EQ(mconfig->method(), test_method); } } -TEST(DefaultConfig, MethodMergeRight) { +TEST(ClientConfig, MethodMergeRight) { using namespace wtlgo::network; - const Config::cptr_t lconfig = DefaultConfig::create()->clear_method(); + const Config::cptr_t lconfig = ClientConfig::create()->clear_method(); for (const HttpMethod test_method : {HttpMethod::GET, HttpMethod::POST, HttpMethod::PATCH, HttpMethod::PUT, HttpMethod::DELETE}) { const Config::cptr_t rconfig = - DefaultConfig::create()->method(test_method); + ClientConfig::create()->method(test_method); const Config::cptr_t mconfig = lconfig->merge(rconfig); ASSERT_EQ(mconfig->method(), test_method); } } -TEST(DefaultConfig, MethodMergeFull) { +TEST(ClientConfig, MethodMergeFull) { using namespace wtlgo::network; for (const HttpMethod ltest_method : {HttpMethod::GET, HttpMethod::POST, HttpMethod::PATCH, HttpMethod::PUT, HttpMethod::DELETE}) { const Config::cptr_t lconfig = - DefaultConfig::create()->method(ltest_method); + ClientConfig::create()->method(ltest_method); for (const HttpMethod rtest_method : {HttpMethod::GET, HttpMethod::POST, HttpMethod::PATCH, HttpMethod::PUT, HttpMethod::DELETE}) { const Config::cptr_t rconfig = - DefaultConfig::create()->method(rtest_method); + ClientConfig::create()->method(rtest_method); const Config::cptr_t mconfig = lconfig->merge(rconfig); ASSERT_EQ(mconfig->method(), rtest_method); @@ -242,10 +242,10 @@ TEST(DefaultConfig, MethodMergeFull) { } } -TEST(DefaultConfig, BaseUrlSet) { +TEST(ClientConfig, BaseUrlSet) { using namespace wtlgo::network; - const Config::ptr_t config = DefaultConfig::create(); + const Config::ptr_t config = ClientConfig::create(); const std::string test_url = random_string(); @@ -253,75 +253,75 @@ TEST(DefaultConfig, BaseUrlSet) { ASSERT_EQ(config->base_url(), test_url); } -TEST(DefaultConfig, BaseUrlClear) { +TEST(ClientConfig, BaseUrlClear) { using namespace wtlgo::network; const Config::ptr_t config = - DefaultConfig::create()->base_url(random_string()); + ClientConfig::create()->base_url(random_string()); ASSERT_EQ(config, config->clear_base_url()); ASSERT_EQ(config->base_url(), std::nullopt); } -TEST(DefaultConfig, BaseUrlCloneEmpty) { +TEST(ClientConfig, BaseUrlCloneEmpty) { using namespace wtlgo::network; - const Config::cptr_t config = DefaultConfig::create()->clear_base_url(); + const Config::cptr_t config = ClientConfig::create()->clear_base_url(); const Config::cptr_t clone = config->clone(); ASSERT_EQ(clone->base_url(), std::nullopt); } -TEST(DefaultConfig, BaseUrlCloneValue) { +TEST(ClientConfig, BaseUrlCloneValue) { using namespace wtlgo::network; const Config::cptr_t config = - DefaultConfig::create()->base_url(random_string()); + ClientConfig::create()->base_url(random_string()); const Config::cptr_t clone = config->clone(); ASSERT_EQ(clone->base_url(), config->base_url()); ASSERT_NE(clone->base_url()->data(), config->base_url()->data()); } -TEST(DefaultConfig, BaseUrlMergeEmpty) { +TEST(ClientConfig, BaseUrlMergeEmpty) { using namespace wtlgo::network; - const Config::cptr_t lconfig = DefaultConfig::create()->clear_base_url(); - const Config::cptr_t rconfig = DefaultConfig::create()->clear_base_url(); + const Config::cptr_t lconfig = ClientConfig::create()->clear_base_url(); + const Config::cptr_t rconfig = ClientConfig::create()->clear_base_url(); const Config::cptr_t mconfig = lconfig->merge(rconfig); ASSERT_EQ(mconfig->base_url(), std::nullopt); } -TEST(DefaultConfig, BaseUrlMergeRight) { +TEST(ClientConfig, BaseUrlMergeRight) { using namespace wtlgo::network; - const Config::cptr_t lconfig = DefaultConfig::create()->clear_base_url(); + const Config::cptr_t lconfig = ClientConfig::create()->clear_base_url(); const Config::cptr_t rconfig = - DefaultConfig::create()->base_url(random_string()); + ClientConfig::create()->base_url(random_string()); const Config::cptr_t mconfig = lconfig->merge(rconfig); ASSERT_EQ(mconfig->base_url(), rconfig->base_url()); } -TEST(DefaultConfig, BaseUrlMergeLeft) { +TEST(ClientConfig, BaseUrlMergeLeft) { using namespace wtlgo::network; const Config::cptr_t lconfig = - DefaultConfig::create()->base_url(random_string()); - const Config::cptr_t rconfig = DefaultConfig::create()->clear_base_url(); + ClientConfig::create()->base_url(random_string()); + const Config::cptr_t rconfig = ClientConfig::create()->clear_base_url(); const Config::cptr_t mconfig = lconfig->merge(rconfig); ASSERT_EQ(mconfig->base_url(), lconfig->base_url()); } -TEST(DefaultConfig, BaseUrlMergeFull) { +TEST(ClientConfig, BaseUrlMergeFull) { using namespace wtlgo::network; const Config::cptr_t lconfig = - DefaultConfig::create()->base_url(random_string()); + ClientConfig::create()->base_url(random_string()); const Config::cptr_t rconfig = - DefaultConfig::create()->base_url(random_string()); + ClientConfig::create()->base_url(random_string()); const Config::cptr_t mconfig = lconfig->merge(rconfig); ASSERT_EQ(mconfig->base_url(), rconfig->base_url()); From 4d1c0aaa2a02212b2cfc90cda4ee0ee7ed0530aa Mon Sep 17 00:00:00 2001 From: wtlgo Date: Tue, 31 Jan 2023 19:06:20 +0300 Subject: [PATCH 38/46] Add const qualifier --- test/src/HttpHeaders.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/src/HttpHeaders.cpp b/test/src/HttpHeaders.cpp index 7693211..1df012b 100644 --- a/test/src/HttpHeaders.cpp +++ b/test/src/HttpHeaders.cpp @@ -14,14 +14,14 @@ TEST(HttpHeaders, Create) { using namespace wtlgo::network; - Headers::cptr_t headers = HttpHeaders::create(); + const Headers::cptr_t headers = HttpHeaders::create(); ASSERT_NE(headers, nullptr); } TEST(HttpHeaders, Clone) { using namespace wtlgo::network; - Headers::ptr_t headers = HttpHeaders::create(); + const Headers::ptr_t headers = HttpHeaders::create(); for (std::size_t i = 0; i < 50; ++i) { headers->set(random_string(), random_string()); } @@ -40,7 +40,7 @@ TEST(HttpHeaders, Clone) { TEST(HttpHeaders, Set) { using namespace wtlgo::network; - Headers::ptr_t headers = HttpHeaders::create(); + const Headers::ptr_t headers = HttpHeaders::create(); const std::string key = random_string(); const std::string value = random_string(); @@ -71,7 +71,7 @@ TEST(HttpHeaders, Keys) { return res; }(); - Headers::ptr_t headers = HttpHeaders::create(); + const Headers::ptr_t headers = HttpHeaders::create(); for (const auto& header : keys) { headers->set(header, random_string()); } From a3027987b617deae6439600633d93c93d21e3c4e Mon Sep 17 00:00:00 2001 From: wtlgo Date: Tue, 31 Jan 2023 19:32:08 +0300 Subject: [PATCH 39/46] Add header to Config --- include/wtlgo/network/ClientConfig.hpp | 8 +- include/wtlgo/network/Config.hpp | 7 ++ src/ClientConfig.cpp | 29 +++++- src/internal/CopyOnWriteConfig.cpp | 18 ++++ src/internal/CopyOnWriteConfig.hpp | 4 + src/internal/MergedConfig.cpp | 26 ++++++ src/internal/MergedConfig.hpp | 4 + test/src/ClientConfig.cpp | 122 ++++++++++++++++++++++--- test/src/utility.cpp | 5 +- 9 files changed, 205 insertions(+), 18 deletions(-) diff --git a/include/wtlgo/network/ClientConfig.hpp b/include/wtlgo/network/ClientConfig.hpp index d34a667..013febf 100644 --- a/include/wtlgo/network/ClientConfig.hpp +++ b/include/wtlgo/network/ClientConfig.hpp @@ -1,5 +1,5 @@ -#ifndef __WTLGO__NETWORK__DEFAULT_CONFIG__ -#define __WTLGO__NETWORK__DEFAULT_CONFIG__ +#ifndef __WTLGO__NETWORK__CLIENT_CONFIG__ +#define __WTLGO__NETWORK__CLIENT_CONFIG__ #include @@ -33,6 +33,10 @@ class ClientConfig : public Config, Config::ptr_t base_url(Config::url_ref_t) override; Config::ptr_t clear_base_url() override; + Config::headers_opt_t headers() const override; + Config::ptr_t headers(headers_opt_t) override; + Config::ptr_t clear_headers() override; + protected: ClientConfig(); ClientConfig(const Config::cptr_t); diff --git a/include/wtlgo/network/Config.hpp b/include/wtlgo/network/Config.hpp index 57307ec..6c6f184 100644 --- a/include/wtlgo/network/Config.hpp +++ b/include/wtlgo/network/Config.hpp @@ -6,6 +6,7 @@ #include #include +#include namespace wtlgo { namespace network { @@ -35,6 +36,12 @@ struct Config { virtual url_opt_ref_t base_url() const = 0; virtual ptr_t base_url(url_ref_t) = 0; virtual ptr_t clear_base_url() = 0; + + using headers_opt_t = Headers::cptr_t; + + virtual headers_opt_t headers() const = 0; + virtual ptr_t headers(headers_opt_t) = 0; + virtual ptr_t clear_headers() = 0; }; } } diff --git a/src/ClientConfig.cpp b/src/ClientConfig.cpp index 0ce6b2e..bc29936 100644 --- a/src/ClientConfig.cpp +++ b/src/ClientConfig.cpp @@ -16,14 +16,17 @@ struct ClientConfig::Impl { std::optional _url; Config::method_opt_t _method; std::optional _base_url; + Config::headers_opt_t _headers; public: Impl() = default; - Impl(const Impl&) = default; Impl(const Config::cptr_t config) : _url{config->url()}, _method{config->method()}, - _base_url{config->base_url()} {} + _base_url{config->base_url()}, + _headers{([headers = config->headers()] { + return headers ? headers->clone() : nullptr; + })()} {} Config::url_opt_ref_t url() const { return _url; } void url(const Config::url_ref_t url) { _url = url; } @@ -36,6 +39,16 @@ struct ClientConfig::Impl { Config::url_opt_ref_t base_url() const { return _base_url; } void base_url(const Config::url_ref_t url) { _base_url = url; } void clear_base_url() { _base_url = std::nullopt; } + + Config::headers_opt_t headers() const { return _headers; } + void headers(const headers_opt_t headers) { + if (headers) { + _headers = headers->clone(); + } else { + _headers = nullptr; + } + } + void clear_headers() { _headers = nullptr; } }; ClientConfig::~ClientConfig() = default; @@ -92,6 +105,18 @@ Config::ptr_t ClientConfig::clear_base_url() { return shared_from_this(); } +Config::headers_opt_t ClientConfig::headers() const { return impl->headers(); } + +Config::ptr_t ClientConfig::headers(const Config::headers_opt_t headers) { + impl->headers(headers); + return shared_from_this(); +} + +Config::ptr_t ClientConfig::clear_headers() { + impl->clear_headers(); + return shared_from_this(); +} + ClientConfig::ClientConfig() : impl{std::make_unique()} {} ClientConfig::ClientConfig(const Config::cptr_t config) diff --git a/src/internal/CopyOnWriteConfig.cpp b/src/internal/CopyOnWriteConfig.cpp index 2631454..f45726e 100644 --- a/src/internal/CopyOnWriteConfig.cpp +++ b/src/internal/CopyOnWriteConfig.cpp @@ -40,6 +40,10 @@ struct CopyOnWriteConfig::Impl { Config::url_opt_ref_t base_url() const { return cptr()->base_url(); } void base_url(const Config::url_ref_t url) { ptr()->base_url(url); } void clear_base_url() { ptr()->clear_base_url(); } + + Config::headers_opt_t headers() const { return cptr()->headers(); } + void headers(const headers_opt_t headers) { ptr()->headers(headers); } + void clear_headers() { ptr()->clear_headers(); } }; CopyOnWriteConfig::~CopyOnWriteConfig() = default; @@ -95,5 +99,19 @@ Config::ptr_t CopyOnWriteConfig::clear_base_url() { return shared_from_this(); } +Config::headers_opt_t CopyOnWriteConfig::headers() const { + return impl->headers(); +} + +Config::ptr_t CopyOnWriteConfig::headers(const Config::headers_opt_t headers) { + impl->headers(headers); + return shared_from_this(); +} + +Config::ptr_t CopyOnWriteConfig::clear_headers() { + impl->clear_headers(); + return shared_from_this(); +} + CopyOnWriteConfig::CopyOnWriteConfig(const Config::cptr_t config) : impl{std::make_unique(config)} {} diff --git a/src/internal/CopyOnWriteConfig.hpp b/src/internal/CopyOnWriteConfig.hpp index 458b05f..295e768 100644 --- a/src/internal/CopyOnWriteConfig.hpp +++ b/src/internal/CopyOnWriteConfig.hpp @@ -33,6 +33,10 @@ class CopyOnWriteConfig Config::ptr_t base_url(Config::url_ref_t) override; Config::ptr_t clear_base_url() override; + Config::headers_opt_t headers() const override; + Config::ptr_t headers(headers_opt_t) override; + Config::ptr_t clear_headers() override; + protected: CopyOnWriteConfig(Config::cptr_t); diff --git a/src/internal/MergedConfig.cpp b/src/internal/MergedConfig.cpp index 3de57f3..b4b3590 100644 --- a/src/internal/MergedConfig.cpp +++ b/src/internal/MergedConfig.cpp @@ -59,6 +59,20 @@ struct MergedConfig::Impl { lhs->clear_base_url(); rhs->clear_base_url(); } + + Config::headers_opt_t headers() const { + return rhs->headers() ? rhs->headers() : lhs->headers(); + } + + void headers(const headers_opt_t headers) { + lhs->clear_headers(); + rhs->headers(headers); + } + + void clear_headers() { + lhs->clear_headers(); + rhs->clear_headers(); + } }; MergedConfig::~MergedConfig() = default; @@ -114,6 +128,18 @@ Config::ptr_t MergedConfig::clear_base_url() { return shared_from_this(); } +Config::headers_opt_t MergedConfig::headers() const { return impl->headers(); } + +Config::ptr_t MergedConfig::headers(const Config::headers_opt_t headers) { + impl->headers(headers); + return shared_from_this(); +} + +Config::ptr_t MergedConfig::clear_headers() { + impl->clear_headers(); + return shared_from_this(); +} + MergedConfig::MergedConfig(const Config::cptr_t lconfig, const Config::cptr_t rconfig) : impl{std::make_unique(lconfig, rconfig)} {} diff --git a/src/internal/MergedConfig.hpp b/src/internal/MergedConfig.hpp index 61887c1..d1076a8 100644 --- a/src/internal/MergedConfig.hpp +++ b/src/internal/MergedConfig.hpp @@ -33,6 +33,10 @@ class MergedConfig : public Config, Config::ptr_t base_url(Config::url_ref_t) override; Config::ptr_t clear_base_url() override; + Config::headers_opt_t headers() const override; + Config::ptr_t headers(headers_opt_t) override; + Config::ptr_t clear_headers() override; + protected: MergedConfig(Config::cptr_t, Config::cptr_t); diff --git a/test/src/ClientConfig.cpp b/test/src/ClientConfig.cpp index f868d09..b9928e2 100644 --- a/test/src/ClientConfig.cpp +++ b/test/src/ClientConfig.cpp @@ -7,6 +7,8 @@ #include #include +#include +#include TEST(ClientConfig, Create) { using namespace wtlgo::network; @@ -51,8 +53,7 @@ TEST(ClientConfig, UrlSet) { TEST(ClientConfig, UrlClear) { using namespace wtlgo::network; - const Config::ptr_t config = - ClientConfig::create()->url(random_string()); + const Config::ptr_t config = ClientConfig::create()->url(random_string()); ASSERT_EQ(config, config->clear_url()); ASSERT_EQ(config->url(), std::nullopt); @@ -70,8 +71,7 @@ TEST(ClientConfig, UrlCloneEmpty) { TEST(ClientConfig, UrlCloneValue) { using namespace wtlgo::network; - const Config::cptr_t config = - ClientConfig::create()->url(random_string()); + const Config::cptr_t config = ClientConfig::create()->url(random_string()); const Config::cptr_t clone = config->clone(); ASSERT_EQ(clone->url(), config->url()); @@ -92,8 +92,7 @@ TEST(ClientConfig, UrlMergeRight) { using namespace wtlgo::network; const Config::cptr_t lconfig = ClientConfig::create()->clear_url(); - const Config::cptr_t rconfig = - ClientConfig::create()->url(random_string()); + const Config::cptr_t rconfig = ClientConfig::create()->url(random_string()); const Config::cptr_t mconfig = lconfig->merge(rconfig); ASSERT_EQ(mconfig->url(), rconfig->url()); @@ -102,8 +101,7 @@ TEST(ClientConfig, UrlMergeRight) { TEST(ClientConfig, UrlMergeLeft) { using namespace wtlgo::network; - const Config::cptr_t lconfig = - ClientConfig::create()->url(random_string()); + const Config::cptr_t lconfig = ClientConfig::create()->url(random_string()); const Config::cptr_t rconfig = ClientConfig::create()->clear_url(); const Config::cptr_t mconfig = lconfig->merge(rconfig); @@ -113,10 +111,8 @@ TEST(ClientConfig, UrlMergeLeft) { TEST(ClientConfig, UrlMergeFull) { using namespace wtlgo::network; - const Config::cptr_t lconfig = - ClientConfig::create()->url(random_string()); - const Config::cptr_t rconfig = - ClientConfig::create()->url(random_string()); + const Config::cptr_t lconfig = ClientConfig::create()->url(random_string()); + const Config::cptr_t rconfig = ClientConfig::create()->url(random_string()); const Config::cptr_t mconfig = lconfig->merge(rconfig); ASSERT_EQ(mconfig->url(), rconfig->url()); @@ -326,3 +322,105 @@ TEST(ClientConfig, BaseUrlMergeFull) { ASSERT_EQ(mconfig->base_url(), rconfig->base_url()); } + +TEST(ClientConfig, HeadersSet) { + using namespace wtlgo::network; + + const Config::ptr_t config = ClientConfig::create(); + const Headers::cptr_t test_headers = HttpHeaders::create(); + + ASSERT_EQ(config, config->headers(test_headers)); + ASSERT_NE(config->headers(), nullptr); +} + +TEST(ClientConfig, HeadersClear) { + using namespace wtlgo::network; + + const Config::ptr_t config = + ClientConfig::create()->headers(HttpHeaders::create()); + + ASSERT_EQ(config, config->clear_headers()); + ASSERT_EQ(config->headers(), nullptr); +} + +TEST(ClientConfig, HeadersCloneEmpty) { + using namespace wtlgo::network; + + const Config::cptr_t config = ClientConfig::create()->clear_headers(); + const Config::cptr_t clone = config->clone(); + + ASSERT_EQ(clone->headers(), nullptr); +} + +TEST(ClientConfig, HeadersCloneValue) { + using namespace wtlgo::network; + + const std::string test_key = random_string(); + + const Config::cptr_t config = ClientConfig::create()->headers( + HttpHeaders::create()->set(test_key, random_string())); + const Config::cptr_t clone = config->clone(); + + ASSERT_NE(clone->headers(), nullptr); + ASSERT_NE(config->headers(), clone->headers()); + ASSERT_EQ(config->headers()->get(test_key), + clone->headers()->get(test_key)); +} + +TEST(ClientConfig, HeadersMergeEmpty) { + using namespace wtlgo::network; + + const Config::cptr_t lconfig = ClientConfig::create()->clear_headers(); + const Config::cptr_t rconfig = ClientConfig::create()->clear_headers(); + const Config::cptr_t merge = lconfig->merge(rconfig); + + ASSERT_EQ(merge->headers(), nullptr); +} + +TEST(ClientConfig, HeadersMergeLeft) { + using namespace wtlgo::network; + + const std::string test_key = random_string(); + + const Config::cptr_t lconfig = ClientConfig::create()->headers( + HttpHeaders::create()->set(test_key, random_string())); + const Config::cptr_t rconfig = ClientConfig::create()->clear_headers(); + const Config::cptr_t merge = lconfig->merge(rconfig); + + ASSERT_NE(merge->headers(), nullptr); + ASSERT_EQ(merge->headers()->get(test_key), + lconfig->headers()->get(test_key)); +} + +TEST(ClientConfig, HeadersMergeRight) { + using namespace wtlgo::network; + + const std::string test_key = random_string(); + + const Config::cptr_t lconfig = ClientConfig::create()->clear_headers(); + const Config::cptr_t rconfig = ClientConfig::create()->headers( + HttpHeaders::create()->set(test_key, random_string())); + const Config::cptr_t merge = lconfig->merge(rconfig); + + ASSERT_NE(merge->headers(), nullptr); + ASSERT_EQ(merge->headers()->get(test_key), + rconfig->headers()->get(test_key)); +} + +TEST(ClientConfig, HeadersMergeFull) { + using namespace wtlgo::network; + + const std::string test_key = random_string(); + + const Config::cptr_t lconfig = ClientConfig::create()->headers( + HttpHeaders::create()->set(test_key, random_string())); + const Config::cptr_t rconfig = ClientConfig::create()->headers( + HttpHeaders::create()->set(test_key, random_string())); + const Config::cptr_t merge = lconfig->merge(rconfig); + + ASSERT_NE(merge->headers(), nullptr); + ASSERT_NE(merge->headers()->get(test_key), + lconfig->headers()->get(test_key)); + ASSERT_EQ(merge->headers()->get(test_key), + rconfig->headers()->get(test_key)); +} diff --git a/test/src/utility.cpp b/test/src/utility.cpp index 88da74a..0509db3 100644 --- a/test/src/utility.cpp +++ b/test/src/utility.cpp @@ -10,8 +10,9 @@ std::mt19937_64 engine{(std::random_device{})()}; } std::string random_string(const std::size_t max_length, const bool exact) { - std::uniform_int_distribution sdist{0, max_length}; - std::uniform_int_distribution cdist{0, 127}; + std::uniform_int_distribution sdist{1, max_length}; + std::uniform_int_distribution cdist{std::numeric_limits::min(), + std::numeric_limits::max()}; std::string out; std::generate_n(std::back_inserter(out), exact ? max_length : sdist(engine), From a10feef4f54daa0990f8468da23615c835213f92 Mon Sep 17 00:00:00 2001 From: wtlgo Date: Thu, 2 Feb 2023 12:20:31 +0300 Subject: [PATCH 40/46] Create client base --- CMakeLists.txt | 4 ++++ include/wtlgo/network/Client.hpp | 24 ++++++++++++++++++++ include/wtlgo/network/CurlClient.hpp | 33 ++++++++++++++++++++++++++++ src/ClientConfig.cpp | 2 +- src/CurlClient.cpp | 30 +++++++++++++++++++++++++ test/src/CurlClient.cpp | 18 +++++++++++++++ 6 files changed, 110 insertions(+), 1 deletion(-) create mode 100644 include/wtlgo/network/Client.hpp create mode 100644 include/wtlgo/network/CurlClient.hpp create mode 100644 src/CurlClient.cpp create mode 100644 test/src/CurlClient.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index e412c43..99f0ec2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,6 +23,9 @@ set(PUBLIC_HEADERS "include/wtlgo/network/Headers.hpp" "include/wtlgo/network/HttpHeaders.hpp" + + "include/wtlgo/network/Client.hpp" + "include/wtlgo/network/CurlClient.hpp" ) set(SOURCES @@ -30,6 +33,7 @@ set(SOURCES "src/HttpBasicAuth.cpp" "src/ClientConfig.cpp" "src/HttpHeaders.cpp" + "src/CurlClient.cpp" "src/internal/MergedConfig.hpp" "src/internal/MergedConfig.cpp" diff --git a/include/wtlgo/network/Client.hpp b/include/wtlgo/network/Client.hpp new file mode 100644 index 0000000..d456c84 --- /dev/null +++ b/include/wtlgo/network/Client.hpp @@ -0,0 +1,24 @@ +#ifndef __WTLGO__NETWORK__CLIENT__ +#define __WTLGO__NETWORK__CLIENT__ + +#include + +#include + +namespace wtlgo { +namespace network { +struct Client { + using ptr_t = std::shared_ptr; + using cptr_t = std::shared_ptr; + + virtual ~Client() = default; + + using config_ptr_t = Config::cptr_t; + + virtual config_ptr_t config() const = 0; + virtual ptr_t config(config_ptr_t) = 0; +}; +} +} + +#endif diff --git a/include/wtlgo/network/CurlClient.hpp b/include/wtlgo/network/CurlClient.hpp new file mode 100644 index 0000000..dfc07db --- /dev/null +++ b/include/wtlgo/network/CurlClient.hpp @@ -0,0 +1,33 @@ +#ifndef __WTLGO__NETWORK__CURL_CLIENT__ +#define __WTLGO__NETWORK__CURL_CLIENT__ + +#include + +#include + +namespace wtlgo { +namespace network { +class CurlClient : public Client, + public std::enable_shared_from_this { +public: + using ptr_t = std::shared_ptr; + using cptr_t = std::shared_ptr; + + virtual ~CurlClient(); + + [[nodiscard]] static CurlClient::ptr_t create(); + + Client::config_ptr_t config() const override; + Client::ptr_t config(Client::config_ptr_t) override; + +protected: + CurlClient(); + +private: + struct Impl; + const std::unique_ptr impl; +}; +} +} + +#endif diff --git a/src/ClientConfig.cpp b/src/ClientConfig.cpp index bc29936..d0cda89 100644 --- a/src/ClientConfig.cpp +++ b/src/ClientConfig.cpp @@ -54,7 +54,7 @@ struct ClientConfig::Impl { ClientConfig::~ClientConfig() = default; ClientConfig::ptr_t ClientConfig::create() { - return std::shared_ptr{new ClientConfig{}}; + return std::shared_ptr{new ClientConfig}; } ClientConfig::ptr_t ClientConfig::clone(const Config::cptr_t config) { diff --git a/src/CurlClient.cpp b/src/CurlClient.cpp new file mode 100644 index 0000000..fb3a907 --- /dev/null +++ b/src/CurlClient.cpp @@ -0,0 +1,30 @@ +#include + +#include +#include + +using namespace wtlgo::network; + +struct CurlClient::Impl { +private: + config_ptr_t _config = ClientConfig::create(); + +public: + config_ptr_t config() const { return _config; } + void config(const config_ptr_t config) { _config = config->clone(); } +}; + +CurlClient::~CurlClient() = default; + +CurlClient::ptr_t CurlClient::create() { + return std::shared_ptr{new CurlClient}; +} + +Client::config_ptr_t CurlClient::config() const { return impl->config(); } + +Client::ptr_t CurlClient::config(const Client::config_ptr_t config) { + impl->config(); + return shared_from_this(); +} + +CurlClient::CurlClient() : impl{std::make_unique()} {} diff --git a/test/src/CurlClient.cpp b/test/src/CurlClient.cpp new file mode 100644 index 0000000..9885fe4 --- /dev/null +++ b/test/src/CurlClient.cpp @@ -0,0 +1,18 @@ +#include + +#include +#include + +TEST(CurlClient, Create) { + using namespace wtlgo::network; + + const Client::cptr_t client = CurlClient::create(); + ASSERT_NE(client, nullptr); +} + +TEST(CurlClient, InitConfig) { + using namespace wtlgo::network; + + const Client::cptr_t client = CurlClient::create(); + ASSERT_NE(client->config(), nullptr); +} From 6b7557c4cd988c81abf5c4b8477a9340b2ba0e12 Mon Sep 17 00:00:00 2001 From: wtlgo Date: Thu, 2 Feb 2023 15:30:17 +0300 Subject: [PATCH 41/46] Create internal subdir structure --- CMakeLists.txt | 8 ++++---- src/ClientConfig.cpp | 5 +++-- src/internal/{ => config}/CopyOnWriteConfig.cpp | 2 +- src/internal/{ => config}/CopyOnWriteConfig.hpp | 6 ++++-- src/internal/{ => config}/MergedConfig.cpp | 2 +- src/internal/{ => config}/MergedConfig.hpp | 6 ++++-- 6 files changed, 17 insertions(+), 12 deletions(-) rename src/internal/{ => config}/CopyOnWriteConfig.cpp (98%) rename src/internal/{ => config}/CopyOnWriteConfig.hpp (89%) rename src/internal/{ => config}/MergedConfig.cpp (98%) rename src/internal/{ => config}/MergedConfig.hpp (90%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 99f0ec2..722c764 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -35,11 +35,11 @@ set(SOURCES "src/HttpHeaders.cpp" "src/CurlClient.cpp" - "src/internal/MergedConfig.hpp" - "src/internal/MergedConfig.cpp" + "src/internal/config/MergedConfig.hpp" + "src/internal/config/MergedConfig.cpp" - "src/internal/CopyOnWriteConfig.hpp" - "src/internal/CopyOnWriteConfig.cpp" + "src/internal/config/CopyOnWriteConfig.hpp" + "src/internal/config/CopyOnWriteConfig.cpp" ) add_library(Network ${SOURCES}) diff --git a/src/ClientConfig.cpp b/src/ClientConfig.cpp index d0cda89..eb0e338 100644 --- a/src/ClientConfig.cpp +++ b/src/ClientConfig.cpp @@ -4,7 +4,7 @@ #include #include -#include "./internal/MergedConfig.hpp" +#include "./internal/Config/MergedConfig.hpp" #include #include @@ -64,7 +64,8 @@ ClientConfig::ptr_t ClientConfig::clone(const Config::cptr_t config) { Config::ptr_t ClientConfig::clone() const { return clone(shared_from_this()); } Config::ptr_t ClientConfig::merge(const Config::cptr_t rconfig) const { - return internal::MergedConfig::merge(shared_from_this(), rconfig); + using namespace wtlgo::network::internal::config; + return MergedConfig::merge(shared_from_this(), rconfig); } Config::url_opt_ref_t ClientConfig::url() const { return impl->url(); } diff --git a/src/internal/CopyOnWriteConfig.cpp b/src/internal/config/CopyOnWriteConfig.cpp similarity index 98% rename from src/internal/CopyOnWriteConfig.cpp rename to src/internal/config/CopyOnWriteConfig.cpp index f45726e..0627390 100644 --- a/src/internal/CopyOnWriteConfig.cpp +++ b/src/internal/config/CopyOnWriteConfig.cpp @@ -6,7 +6,7 @@ #include "./CopyOnWriteConfig.hpp" using namespace wtlgo::network; -using namespace wtlgo::network::internal; +using namespace wtlgo::network::internal::config; struct CopyOnWriteConfig::Impl { private: diff --git a/src/internal/CopyOnWriteConfig.hpp b/src/internal/config/CopyOnWriteConfig.hpp similarity index 89% rename from src/internal/CopyOnWriteConfig.hpp rename to src/internal/config/CopyOnWriteConfig.hpp index 295e768..b82cc19 100644 --- a/src/internal/CopyOnWriteConfig.hpp +++ b/src/internal/config/CopyOnWriteConfig.hpp @@ -1,5 +1,5 @@ -#ifndef __WTLGO__NETWORK__INTERNAL__COPY_ON_WRITE_CONFIG__ -#define __WTLGO__NETWORK__INTERNAL__COPY_ON_WRITE_CONFIG__ +#ifndef __WTLGO__NETWORK__INTERNAL__CONFIG__COPY_ON_WRITE_CONFIG__ +#define __WTLGO__NETWORK__INTERNAL__CONFIG__COPY_ON_WRITE_CONFIG__ #include #include @@ -7,6 +7,7 @@ namespace wtlgo { namespace network { namespace internal { +namespace config { class CopyOnWriteConfig : public Config, public std::enable_shared_from_this { @@ -47,5 +48,6 @@ class CopyOnWriteConfig } } } +} #endif diff --git a/src/internal/MergedConfig.cpp b/src/internal/config/MergedConfig.cpp similarity index 98% rename from src/internal/MergedConfig.cpp rename to src/internal/config/MergedConfig.cpp index b4b3590..bde0b56 100644 --- a/src/internal/MergedConfig.cpp +++ b/src/internal/config/MergedConfig.cpp @@ -6,7 +6,7 @@ #include using namespace wtlgo::network; -using namespace wtlgo::network::internal; +using namespace wtlgo::network::internal::config; struct MergedConfig::Impl { private: diff --git a/src/internal/MergedConfig.hpp b/src/internal/config/MergedConfig.hpp similarity index 90% rename from src/internal/MergedConfig.hpp rename to src/internal/config/MergedConfig.hpp index d1076a8..d925bed 100644 --- a/src/internal/MergedConfig.hpp +++ b/src/internal/config/MergedConfig.hpp @@ -1,5 +1,5 @@ -#ifndef __WTLGO__NETWORK__INTERNAL__MERGED_CONFIG__ -#define __WTLGO__NETWORK__INTERNAL__MERGED_CONFIG__ +#ifndef __WTLGO__NETWORK__INTERNAL__CONFIG__MERGED_CONFIG__ +#define __WTLGO__NETWORK__INTERNAL__CONFIG__MERGED_CONFIG__ #include #include @@ -7,6 +7,7 @@ namespace wtlgo { namespace network { namespace internal { +namespace config { class MergedConfig : public Config, public std::enable_shared_from_this { public: @@ -47,5 +48,6 @@ class MergedConfig : public Config, } } } +} #endif From 10cefc0311dcb154ba33dae2f656f4bed0dbe37c Mon Sep 17 00:00:00 2001 From: wtlgo Date: Thu, 2 Feb 2023 15:34:36 +0300 Subject: [PATCH 42/46] Create CurlHandler template --- CMakeLists.txt | 4 +++- src/internal/curl/CurlHandler.cpp | 1 + src/internal/curl/CurlHandler.hpp | 14 ++++++++++++++ 3 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 src/internal/curl/CurlHandler.cpp create mode 100644 src/internal/curl/CurlHandler.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 722c764..1faef3e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,9 +37,11 @@ set(SOURCES "src/internal/config/MergedConfig.hpp" "src/internal/config/MergedConfig.cpp" - "src/internal/config/CopyOnWriteConfig.hpp" "src/internal/config/CopyOnWriteConfig.cpp" + + "src/internal/curl/CurlHandler.hpp" + "src/internal/curl/CurlHandler.cpp" ) add_library(Network ${SOURCES}) diff --git a/src/internal/curl/CurlHandler.cpp b/src/internal/curl/CurlHandler.cpp new file mode 100644 index 0000000..096aafc --- /dev/null +++ b/src/internal/curl/CurlHandler.cpp @@ -0,0 +1 @@ +#include "./CurlHandler.hpp" diff --git a/src/internal/curl/CurlHandler.hpp b/src/internal/curl/CurlHandler.hpp new file mode 100644 index 0000000..ef71dc4 --- /dev/null +++ b/src/internal/curl/CurlHandler.hpp @@ -0,0 +1,14 @@ +#ifndef __WTLGO__NETWORK__INTERNAL__CURL__CURL_HANDLER__ +#define __WTLGO__NETWORK__INTERNAL__CURL__CURL_HANDLER__ + +namespace wtlgo { +namespace network { +namespace internal { +namespace curl { +class CurlHandler {}; +} +} +} +} + +#endif From 9d6f1a403e3e5690414e140cc8c4733f4e15ae17 Mon Sep 17 00:00:00 2001 From: wtlgo Date: Thu, 2 Feb 2023 15:46:10 +0300 Subject: [PATCH 43/46] Remove private implementation in internal classes --- src/internal/config/CopyOnWriteConfig.cpp | 77 +++++--------- src/internal/config/CopyOnWriteConfig.hpp | 7 +- src/internal/config/MergedConfig.cpp | 116 +++++++--------------- src/internal/config/MergedConfig.hpp | 4 +- 4 files changed, 69 insertions(+), 135 deletions(-) diff --git a/src/internal/config/CopyOnWriteConfig.cpp b/src/internal/config/CopyOnWriteConfig.cpp index 0627390..3a2e396 100644 --- a/src/internal/config/CopyOnWriteConfig.cpp +++ b/src/internal/config/CopyOnWriteConfig.cpp @@ -8,44 +8,6 @@ using namespace wtlgo::network; using namespace wtlgo::network::internal::config; -struct CopyOnWriteConfig::Impl { -private: - Config::cptr_t solid; - Config::ptr_t liquid; - - void liquify() { - if (!solid) return; - - liquid = ClientConfig::clone(solid); - solid = nullptr; - } - - Config::cptr_t cptr() const { return solid ? solid : liquid; } - Config::ptr_t ptr() { - liquify(); - return liquid; - } - -public: - Impl(const Config::cptr_t config) : solid{config}, liquid{nullptr} {} - - Config::url_opt_ref_t url() const { return cptr()->url(); } - void url(const Config::url_ref_t url) { ptr()->url(url); } - void clear_url() { ptr()->clear_url(); } - - Config::method_opt_t method() const { return cptr()->method(); } - void method(const Config::method_t method) { ptr()->method(method); } - void clear_method() { ptr()->clear_method(); } - - Config::url_opt_ref_t base_url() const { return cptr()->base_url(); } - void base_url(const Config::url_ref_t url) { ptr()->base_url(url); } - void clear_base_url() { ptr()->clear_base_url(); } - - Config::headers_opt_t headers() const { return cptr()->headers(); } - void headers(const headers_opt_t headers) { ptr()->headers(headers); } - void clear_headers() { ptr()->clear_headers(); } -}; - CopyOnWriteConfig::~CopyOnWriteConfig() = default; CopyOnWriteConfig::ptr_t CopyOnWriteConfig::adapt(const Config::cptr_t config) { @@ -60,58 +22,71 @@ Config::ptr_t CopyOnWriteConfig::merge(const Config::cptr_t rconfig) const { return MergedConfig::merge(shared_from_this(), rconfig); } -Config::url_opt_ref_t CopyOnWriteConfig::url() const { return impl->url(); } +Config::url_opt_ref_t CopyOnWriteConfig::url() const { return cptr()->url(); } Config::ptr_t CopyOnWriteConfig::url(const Config::url_ref_t url) { - impl->url(url); + ptr()->url(url); return shared_from_this(); } Config::ptr_t CopyOnWriteConfig::clear_url() { - impl->clear_url(); + ptr()->clear_url(); return shared_from_this(); } Config::method_opt_t CopyOnWriteConfig::method() const { - return impl->method(); + return cptr()->method(); } Config::ptr_t CopyOnWriteConfig::method(const Config::method_t method) { - impl->method(method); + ptr()->method(method); return shared_from_this(); } Config::ptr_t CopyOnWriteConfig::clear_method() { - impl->clear_method(); + ptr()->clear_method(); return shared_from_this(); } Config::url_opt_ref_t CopyOnWriteConfig::base_url() const { - return impl->base_url(); + return cptr()->base_url(); } Config::ptr_t CopyOnWriteConfig::base_url(const Config::url_ref_t url) { - impl->base_url(url); + ptr()->base_url(url); return shared_from_this(); } Config::ptr_t CopyOnWriteConfig::clear_base_url() { - impl->clear_base_url(); + ptr()->clear_base_url(); return shared_from_this(); } Config::headers_opt_t CopyOnWriteConfig::headers() const { - return impl->headers(); + return cptr()->headers(); } Config::ptr_t CopyOnWriteConfig::headers(const Config::headers_opt_t headers) { - impl->headers(headers); + ptr()->headers(headers); return shared_from_this(); } Config::ptr_t CopyOnWriteConfig::clear_headers() { - impl->clear_headers(); + ptr()->clear_headers(); return shared_from_this(); } CopyOnWriteConfig::CopyOnWriteConfig(const Config::cptr_t config) - : impl{std::make_unique(config)} {} + : solid{config}, liquid{nullptr} {} + +Config::cptr_t CopyOnWriteConfig::cptr() const { + return solid ? solid : liquid; +} + +Config::ptr_t CopyOnWriteConfig::ptr() { + if (solid) { + liquid = ClientConfig::clone(solid); + solid = nullptr; + } + + return liquid; +} diff --git a/src/internal/config/CopyOnWriteConfig.hpp b/src/internal/config/CopyOnWriteConfig.hpp index b82cc19..9c29986 100644 --- a/src/internal/config/CopyOnWriteConfig.hpp +++ b/src/internal/config/CopyOnWriteConfig.hpp @@ -42,8 +42,11 @@ class CopyOnWriteConfig CopyOnWriteConfig(Config::cptr_t); private: - struct Impl; - const std::unique_ptr impl; + Config::cptr_t solid; + Config::ptr_t liquid; + + Config::cptr_t cptr() const; + Config::ptr_t ptr(); }; } } diff --git a/src/internal/config/MergedConfig.cpp b/src/internal/config/MergedConfig.cpp index bde0b56..5c29585 100644 --- a/src/internal/config/MergedConfig.cpp +++ b/src/internal/config/MergedConfig.cpp @@ -8,73 +8,6 @@ using namespace wtlgo::network; using namespace wtlgo::network::internal::config; -struct MergedConfig::Impl { -private: - Config::ptr_t lhs; - Config::ptr_t rhs; - -public: - Impl(const Config::cptr_t lhs, const Config::cptr_t rhs) - : lhs{CopyOnWriteConfig::adapt(lhs)}, - rhs{CopyOnWriteConfig::adapt(rhs)} {} - - Config::url_opt_ref_t url() const { - return rhs->url() ? rhs->url() : lhs->url(); - } - - void url(const Config::url_ref_t url) { - lhs->clear_url(); - rhs->url(url); - } - - void clear_url() { - lhs->clear_url(); - rhs->clear_url(); - } - - Config::method_opt_t method() const { - return rhs->method() ? rhs->method() : lhs->method(); - } - - void method(const Config::method_t method) { - lhs->clear_method(); - rhs->method(method); - } - - void clear_method() { - lhs->clear_method(); - rhs->clear_method(); - } - - Config::url_opt_ref_t base_url() const { - return rhs->base_url() ? rhs->base_url() : lhs->base_url(); - } - - void base_url(const Config::url_ref_t url) { - lhs->clear_base_url(); - rhs->base_url(url); - } - - void clear_base_url() { - lhs->clear_base_url(); - rhs->clear_base_url(); - } - - Config::headers_opt_t headers() const { - return rhs->headers() ? rhs->headers() : lhs->headers(); - } - - void headers(const headers_opt_t headers) { - lhs->clear_headers(); - rhs->headers(headers); - } - - void clear_headers() { - lhs->clear_headers(); - rhs->clear_headers(); - } -}; - MergedConfig::~MergedConfig() = default; MergedConfig::ptr_t MergedConfig::merge(const Config::cptr_t lconfig, @@ -90,56 +23,79 @@ Config::ptr_t MergedConfig::merge(const Config::cptr_t rconfig) const { return merge(shared_from_this(), rconfig); } -Config::url_opt_ref_t MergedConfig::url() const { return impl->url(); } +Config::url_opt_ref_t MergedConfig::url() const { + return rhs->url() ? rhs->url() : lhs->url(); +} Config::ptr_t MergedConfig::url(const Config::url_ref_t url) { - impl->url(url); + lhs->clear_url(); + rhs->url(url); + return shared_from_this(); } Config::ptr_t MergedConfig::clear_url() { - impl->clear_url(); + lhs->clear_url(); + rhs->clear_url(); + return shared_from_this(); } -Config::method_opt_t MergedConfig::method() const { return impl->method(); } +Config::method_opt_t MergedConfig::method() const { + return rhs->method() ? rhs->method() : lhs->method(); +} Config::ptr_t MergedConfig::method(const Config::method_t method) { - impl->method(method); + lhs->clear_method(); + rhs->method(method); + return shared_from_this(); } Config::ptr_t MergedConfig::clear_method() { - impl->clear_method(); + lhs->clear_method(); + rhs->clear_method(); + return shared_from_this(); } Config::url_opt_ref_t MergedConfig::base_url() const { - return impl->base_url(); + return rhs->base_url() ? rhs->base_url() : lhs->base_url(); } Config::ptr_t MergedConfig::base_url(const Config::url_ref_t url) { - impl->base_url(url); + lhs->clear_base_url(); + rhs->base_url(url); + return shared_from_this(); } Config::ptr_t MergedConfig::clear_base_url() { - impl->clear_base_url(); + lhs->clear_base_url(); + rhs->clear_base_url(); + return shared_from_this(); } -Config::headers_opt_t MergedConfig::headers() const { return impl->headers(); } +Config::headers_opt_t MergedConfig::headers() const { + return rhs->headers() ? rhs->headers() : lhs->headers(); +} Config::ptr_t MergedConfig::headers(const Config::headers_opt_t headers) { - impl->headers(headers); + lhs->clear_headers(); + rhs->headers(headers); + return shared_from_this(); } Config::ptr_t MergedConfig::clear_headers() { - impl->clear_headers(); + lhs->clear_headers(); + rhs->clear_headers(); + return shared_from_this(); } MergedConfig::MergedConfig(const Config::cptr_t lconfig, const Config::cptr_t rconfig) - : impl{std::make_unique(lconfig, rconfig)} {} + : lhs{CopyOnWriteConfig::adapt(lconfig)}, + rhs{CopyOnWriteConfig::adapt(rconfig)} {} diff --git a/src/internal/config/MergedConfig.hpp b/src/internal/config/MergedConfig.hpp index d925bed..2266753 100644 --- a/src/internal/config/MergedConfig.hpp +++ b/src/internal/config/MergedConfig.hpp @@ -42,8 +42,8 @@ class MergedConfig : public Config, MergedConfig(Config::cptr_t, Config::cptr_t); private: - struct Impl; - const std::unique_ptr impl; + Config::ptr_t lhs; + Config::ptr_t rhs; }; } } From 98039d05cde9cad4259793587c4a9bc5e5acb378 Mon Sep 17 00:00:00 2001 From: wtlgo Date: Thu, 2 Feb 2023 16:04:36 +0300 Subject: [PATCH 44/46] Add CurlHandler Builder template --- src/internal/curl/CurlHandlerBuilder.cpp | 1 + src/internal/curl/CurlHandlerBuilder.hpp | 14 ++++++++++++++ 2 files changed, 15 insertions(+) create mode 100644 src/internal/curl/CurlHandlerBuilder.cpp create mode 100644 src/internal/curl/CurlHandlerBuilder.hpp diff --git a/src/internal/curl/CurlHandlerBuilder.cpp b/src/internal/curl/CurlHandlerBuilder.cpp new file mode 100644 index 0000000..cbca4b1 --- /dev/null +++ b/src/internal/curl/CurlHandlerBuilder.cpp @@ -0,0 +1 @@ +#include "./CurlHandlerBuilder.hpp" \ No newline at end of file diff --git a/src/internal/curl/CurlHandlerBuilder.hpp b/src/internal/curl/CurlHandlerBuilder.hpp new file mode 100644 index 0000000..623b268 --- /dev/null +++ b/src/internal/curl/CurlHandlerBuilder.hpp @@ -0,0 +1,14 @@ +#ifndef __WTLGO__NETWORK__INTERNAL__CURL__CURL_HANDLER_BUILDER__ +#define __WTLGO__NETWORK__INTERNAL__CURL__CURL_HANDLER_BUILDER__ + +namespace wtlgo { +namespace network { +namespace internal { +namespace curl { +class CurlHandlerBuilder {}; +} +} +} +} + +#endif From bc29be7eb367e3d0589434d1dc9a62205b23b410 Mon Sep 17 00:00:00 2001 From: wtlgo Date: Thu, 2 Feb 2023 16:44:30 +0300 Subject: [PATCH 45/46] Implement CurlEasyHandler --- CMakeLists.txt | 7 +++++-- src/internal/curl/CurlEasyHandler.cpp | 18 +++++++++++++++++ src/internal/curl/CurlEasyHandler.hpp | 29 +++++++++++++++++++++++++++ src/internal/curl/CurlHandler.cpp | 1 - src/internal/curl/CurlHandler.hpp | 14 ------------- src/internal/curl/Types.hpp | 19 ++++++++++++++++++ 6 files changed, 71 insertions(+), 17 deletions(-) create mode 100644 src/internal/curl/CurlEasyHandler.cpp create mode 100644 src/internal/curl/CurlEasyHandler.hpp delete mode 100644 src/internal/curl/CurlHandler.cpp delete mode 100644 src/internal/curl/CurlHandler.hpp create mode 100644 src/internal/curl/Types.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 1faef3e..b45c8f3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -40,8 +40,11 @@ set(SOURCES "src/internal/config/CopyOnWriteConfig.hpp" "src/internal/config/CopyOnWriteConfig.cpp" - "src/internal/curl/CurlHandler.hpp" - "src/internal/curl/CurlHandler.cpp" + "src/internal/curl/Types.hpp" + "src/internal/curl/CurlEasyHandler.hpp" + "src/internal/curl/CurlEasyHandler.cpp" + "src/internal/curl/CurlHandlerBuilder.hpp" + "src/internal/curl/CurlHandlerBuilder.cpp" ) add_library(Network ${SOURCES}) diff --git a/src/internal/curl/CurlEasyHandler.cpp b/src/internal/curl/CurlEasyHandler.cpp new file mode 100644 index 0000000..4fe0957 --- /dev/null +++ b/src/internal/curl/CurlEasyHandler.cpp @@ -0,0 +1,18 @@ +#include + +#include "./CurlEasyHandler.hpp" + +using namespace wtlgo::network::internal::curl; + +CurlEasyHandler::CurlEasyHandler() + : _curl{curl_easy_init(), curl_easy_cleanup} {} + +CurlEasyHandler::CurlEasyHandler(const curl_unique_ptr& curl) + : _curl{curl_easy_duphandle(curl.get()), curl_easy_cleanup} {} + +CurlEasyHandler::CurlEasyHandler(const CurlEasyHandler& handler) + : CurlEasyHandler(handler._curl) {} + +CURLcode CurlEasyHandler::perform() const { + return curl_easy_perform(_curl.get()); +} diff --git a/src/internal/curl/CurlEasyHandler.hpp b/src/internal/curl/CurlEasyHandler.hpp new file mode 100644 index 0000000..79dc7c8 --- /dev/null +++ b/src/internal/curl/CurlEasyHandler.hpp @@ -0,0 +1,29 @@ +#ifndef __WTLGO__NETWORK__INTERNAL__CURL__CURL_EASY_HANDLER__ +#define __WTLGO__NETWORK__INTERNAL__CURL__CURL_EASY_HANDLER__ + +#include +#include + +#include "./Types.hpp" + +namespace wtlgo { +namespace network { +namespace internal { +namespace curl { +class CurlEasyHandler { +public: + CurlEasyHandler(); + CurlEasyHandler(const curl_unique_ptr&); + CurlEasyHandler(const CurlEasyHandler&); + + CURLcode perform() const; + +private: + const curl_unique_ptr _curl; +}; +} +} +} +} + +#endif diff --git a/src/internal/curl/CurlHandler.cpp b/src/internal/curl/CurlHandler.cpp deleted file mode 100644 index 096aafc..0000000 --- a/src/internal/curl/CurlHandler.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "./CurlHandler.hpp" diff --git a/src/internal/curl/CurlHandler.hpp b/src/internal/curl/CurlHandler.hpp deleted file mode 100644 index ef71dc4..0000000 --- a/src/internal/curl/CurlHandler.hpp +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef __WTLGO__NETWORK__INTERNAL__CURL__CURL_HANDLER__ -#define __WTLGO__NETWORK__INTERNAL__CURL__CURL_HANDLER__ - -namespace wtlgo { -namespace network { -namespace internal { -namespace curl { -class CurlHandler {}; -} -} -} -} - -#endif diff --git a/src/internal/curl/Types.hpp b/src/internal/curl/Types.hpp new file mode 100644 index 0000000..a71de38 --- /dev/null +++ b/src/internal/curl/Types.hpp @@ -0,0 +1,19 @@ +#ifndef __WTLGO__NETWORK__INTERNAL__CURL__TYPES__ +#define __WTLGO__NETWORK__INTERNAL__CURL__TYPES__ + +#include + +#include + +namespace wtlgo { +namespace network { +namespace internal { +namespace curl { +using curl_shared_ptr = std::shared_ptr; +using curl_unique_ptr = std::unique_ptr; +} +} +} +} + +#endif From 32f243ade80a4f66c58da28fbf209b0c1698f571 Mon Sep 17 00:00:00 2001 From: wtlgo Date: Fri, 3 Feb 2023 11:16:14 +0300 Subject: [PATCH 46/46] Add some methods to CurlEasyHandlerBuilder --- CMakeLists.txt | 4 +- src/internal/curl/CurlEasyHandlerBuilder.cpp | 359 +++++++++++++++++++ src/internal/curl/CurlEasyHandlerBuilder.hpp | 157 ++++++++ src/internal/curl/CurlHandlerBuilder.cpp | 1 - src/internal/curl/CurlHandlerBuilder.hpp | 14 - 5 files changed, 518 insertions(+), 17 deletions(-) create mode 100644 src/internal/curl/CurlEasyHandlerBuilder.cpp create mode 100644 src/internal/curl/CurlEasyHandlerBuilder.hpp delete mode 100644 src/internal/curl/CurlHandlerBuilder.cpp delete mode 100644 src/internal/curl/CurlHandlerBuilder.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index b45c8f3..4273c44 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -43,8 +43,8 @@ set(SOURCES "src/internal/curl/Types.hpp" "src/internal/curl/CurlEasyHandler.hpp" "src/internal/curl/CurlEasyHandler.cpp" - "src/internal/curl/CurlHandlerBuilder.hpp" - "src/internal/curl/CurlHandlerBuilder.cpp" + "src/internal/curl/CurlEasyHandlerBuilder.hpp" + "src/internal/curl/CurlEasyHandlerBuilder.cpp" ) add_library(Network ${SOURCES}) diff --git a/src/internal/curl/CurlEasyHandlerBuilder.cpp b/src/internal/curl/CurlEasyHandlerBuilder.cpp new file mode 100644 index 0000000..ee813ac --- /dev/null +++ b/src/internal/curl/CurlEasyHandlerBuilder.cpp @@ -0,0 +1,359 @@ +#include +#include + +#include + +#include "./CurlEasyHandler.hpp" +#include "./CurlEasyHandlerBuilder.hpp" + +using namespace wtlgo::network::internal::curl; + +CurlEasyHandlerBuilder::CurlEasyHandlerBuilder() + : _curl{curl_easy_init(), curl_easy_cleanup} {} + +CurlEasyHandler CurlEasyHandlerBuilder::build() const { return {_curl}; } + +CurlEasyHandlerBuilder& CurlEasyHandlerBuilder::verbose(const bool onoff) { + curl_easy_setopt(_curl.get(), CURLOPT_VERBOSE, static_cast(onoff)); + return *this; +} + +CurlEasyHandlerBuilder& CurlEasyHandlerBuilder::header(const bool onoff) { + curl_easy_setopt(_curl.get(), CURLOPT_HEADER, static_cast(onoff)); + return *this; +} + +CurlEasyHandlerBuilder& CurlEasyHandlerBuilder::no_progress(const bool onoff) { + curl_easy_setopt(_curl.get(), CURLOPT_NOPROGRESS, static_cast(onoff)); + return *this; +} + +CurlEasyHandlerBuilder& CurlEasyHandlerBuilder::no_signal(const bool onoff) { + curl_easy_setopt(_curl.get(), CURLOPT_NOSIGNAL, static_cast(onoff)); + return *this; +} + +CurlEasyHandlerBuilder& CurlEasyHandlerBuilder::wildcard_match( + const bool onoff) { + curl_easy_setopt(_curl.get(), CURLOPT_WILDCARDMATCH, + static_cast(onoff)); + return *this; +} + +CurlEasyHandlerBuilder& CurlEasyHandlerBuilder::write_function( + const write_function_t write_callback) { + curl_easy_setopt(_curl.get(), CURLOPT_WRITEFUNCTION, write_callback); + return *this; +} + +CurlEasyHandlerBuilder& CurlEasyHandlerBuilder::write_data( + void* const pointer) { + curl_easy_setopt(_curl.get(), CURLOPT_WRITEDATA, pointer); + return *this; +} + +CurlEasyHandlerBuilder& CurlEasyHandlerBuilder::read_function( + const read_function_t read_callback) { + curl_easy_setopt(_curl.get(), CURLOPT_READFUNCTION, read_callback); + return *this; +} + +CurlEasyHandlerBuilder& CurlEasyHandlerBuilder::read_data(void* const pointer) { + curl_easy_setopt(_curl.get(), CURLOPT_READDATA, pointer); + return *this; +} + +CurlEasyHandlerBuilder& CurlEasyHandlerBuilder::io_ctl_function( + const io_ctl_function_t ioctl_callback) { + curl_easy_setopt(_curl.get(), CURLOPT_IOCTLFUNCTION, ioctl_callback); + return *this; +} + +CurlEasyHandlerBuilder& CurlEasyHandlerBuilder::io_ctl_data( + void* const pointer) { + curl_easy_setopt(_curl.get(), CURLOPT_IOCTLDATA, pointer); + return *this; +} + +CurlEasyHandlerBuilder& CurlEasyHandlerBuilder::seek_function( + const seek_function_t seek_callback) { + curl_easy_setopt(_curl.get(), CURLOPT_SEEKFUNCTION, seek_callback); + return *this; +} + +CurlEasyHandlerBuilder& CurlEasyHandlerBuilder::seek_data(void* const pointer) { + curl_easy_setopt(_curl.get(), CURLOPT_SEEKDATA, pointer); + return *this; +} + +CurlEasyHandlerBuilder& CurlEasyHandlerBuilder::sock_function( + const sock_function_t sock_callback) { + curl_easy_setopt(_curl.get(), CURLOPT_SOCKOPTFUNCTION, sock_callback); + return *this; +} + +CurlEasyHandlerBuilder& CurlEasyHandlerBuilder::sock_data(void* const pointer) { + curl_easy_setopt(_curl.get(), CURLOPT_SOCKOPTDATA, pointer); + return *this; +} + +CurlEasyHandlerBuilder& CurlEasyHandlerBuilder::open_socket_function( + const open_socket_function_t opensocket_callback) { + curl_easy_setopt(_curl.get(), CURLOPT_OPENSOCKETFUNCTION, + opensocket_callback); + return *this; +} + +CurlEasyHandlerBuilder& CurlEasyHandlerBuilder::open_socket_data( + void* const pointer) { + curl_easy_setopt(_curl.get(), CURLOPT_OPENSOCKETDATA, pointer); + return *this; +} + +CurlEasyHandlerBuilder& CurlEasyHandlerBuilder::close_socket_function( + const close_socket_function_t closesocket_callback) { + curl_easy_setopt(_curl.get(), CURLOPT_CLOSESOCKETFUNCTION, + closesocket_callback); + return *this; +} + +CurlEasyHandlerBuilder& CurlEasyHandlerBuilder::close_socket_data( + void* const pointer) { + curl_easy_setopt(_curl.get(), CURLOPT_CLOSESOCKETDATA, pointer); + return *this; +} + +CurlEasyHandlerBuilder& CurlEasyHandlerBuilder::xfer_info_function( + const xfer_info_function_t progress_callback) { + curl_easy_setopt(_curl.get(), CURLOPT_XFERINFOFUNCTION, progress_callback); + return *this; +} + +CurlEasyHandlerBuilder& CurlEasyHandlerBuilder::xfer_info_data( + void* const pointer) { + curl_easy_setopt(_curl.get(), CURLOPT_XFERINFODATA, pointer); + return *this; +} + +CurlEasyHandlerBuilder& CurlEasyHandlerBuilder::header_function( + const header_function_t header_callback) { + curl_easy_setopt(_curl.get(), CURLOPT_HEADERFUNCTION, header_callback); + return *this; +} + +CurlEasyHandlerBuilder& CurlEasyHandlerBuilder::header_data( + void* const pointer) { + curl_easy_setopt(_curl.get(), CURLOPT_HEADERDATA, pointer); + return *this; +} + +CurlEasyHandlerBuilder& CurlEasyHandlerBuilder::debug_function( + const debug_function_t debug_callback) { + curl_easy_setopt(_curl.get(), CURLOPT_DEBUGFUNCTION, debug_callback); + return *this; +} + +CurlEasyHandlerBuilder& CurlEasyHandlerBuilder::debug_data( + void* const pointer) { + curl_easy_setopt(_curl.get(), CURLOPT_DEBUGDATA, pointer); + return *this; +} + +CurlEasyHandlerBuilder& CurlEasyHandlerBuilder::ssl_ctx_function( + const ssl_ctx_function_t ssl_ctx_callback) { + curl_easy_setopt(_curl.get(), CURLOPT_SSL_CTX_FUNCTION, ssl_ctx_callback); + return *this; +} + +CurlEasyHandlerBuilder& CurlEasyHandlerBuilder::ssl_ctx_data( + void* const pointer) { + curl_easy_setopt(_curl.get(), CURLOPT_SSL_CTX_DATA, pointer); + return *this; +} + +CurlEasyHandlerBuilder& CurlEasyHandlerBuilder::interleave_function( + const interleave_function_t interleave_callback) { + curl_easy_setopt(_curl.get(), CURLOPT_INTERLEAVEFUNCTION, + interleave_callback); + return *this; +} + +CurlEasyHandlerBuilder& CurlEasyHandlerBuilder::interleave_data( + void* const pointer) { + curl_easy_setopt(_curl.get(), CURLOPT_INTERLEAVEDATA, pointer); + return *this; +} + +CurlEasyHandlerBuilder& CurlEasyHandlerBuilder::chunk_bgn_function( + const chunk_bgn_function_t chunk_bgn_callback) { + curl_easy_setopt(_curl.get(), CURLOPT_CHUNK_BGN_FUNCTION, + chunk_bgn_callback); + return *this; +} + +CurlEasyHandlerBuilder& CurlEasyHandlerBuilder::chunk_end_function( + const chunk_end_function_t chunk_end_callback) { + curl_easy_setopt(_curl.get(), CURLOPT_CHUNK_END_FUNCTION, + chunk_end_callback); + return *this; +} + +CurlEasyHandlerBuilder& CurlEasyHandlerBuilder::chunk_data( + void* const pointer) { + curl_easy_setopt(_curl.get(), CURLOPT_INTERLEAVEDATA, pointer); + return *this; +} + +CurlEasyHandlerBuilder& CurlEasyHandlerBuilder::fnmatch_function( + const fnmatch_function_t fnmatch_callback) { + curl_easy_setopt(_curl.get(), CURLOPT_FNMATCH_FUNCTION, fnmatch_callback); + return *this; +} + +CurlEasyHandlerBuilder& CurlEasyHandlerBuilder::fnmatch_data( + void* const pointer) { + curl_easy_setopt(_curl.get(), CURLOPT_FNMATCH_DATA, pointer); + return *this; +} + +CurlEasyHandlerBuilder& CurlEasyHandlerBuilder::supress_connect_headers( + const bool onoff) { + curl_easy_setopt(_curl.get(), CURLOPT_SUPPRESS_CONNECT_HEADERS, + static_cast(onoff)); + return *this; +} + +CurlEasyHandlerBuilder& CurlEasyHandlerBuilder::resolver_start_function( + const resolver_start_function_t resolver_start_cb) { + curl_easy_setopt(_curl.get(), CURLOPT_RESOLVER_START_FUNCTION, + resolver_start_cb); + return *this; +} + +CurlEasyHandlerBuilder& CurlEasyHandlerBuilder::resolver_start_data( + void* const pointer) { + curl_easy_setopt(_curl.get(), CURLOPT_RESOLVER_START_DATA, pointer); + return *this; +} + +CurlEasyHandlerBuilder& CurlEasyHandlerBuilder::prereq_function( + const prereq_function_t prereq_callback) { + curl_easy_setopt(_curl.get(), CURLOPT_PREREQFUNCTION, prereq_callback); + return *this; +} + +CurlEasyHandlerBuilder& CurlEasyHandlerBuilder::prereq_data( + void* const pointer) { + curl_easy_setopt(_curl.get(), CURLOPT_PREREQDATA, pointer); + return *this; +} + +CurlEasyHandlerBuilder& CurlEasyHandlerBuilder::error_buffer(char* const buf) { + curl_easy_setopt(_curl.get(), CURLOPT_ERRORBUFFER, buf); + return *this; +} + +CurlEasyHandlerBuilder& CurlEasyHandlerBuilder::std_err(FILE* const stream) { + curl_easy_setopt(_curl.get(), CURLOPT_STDERR, stream); + return *this; +} + +CurlEasyHandlerBuilder& CurlEasyHandlerBuilder::fail_on_error(const bool fail) { + curl_easy_setopt(_curl.get(), CURLOPT_FAILONERROR, static_cast(fail)); + return *this; +} + +CurlEasyHandlerBuilder& CurlEasyHandlerBuilder::keep_sending_on_error( + const bool keep_sending) { + curl_easy_setopt(_curl.get(), CURLOPT_KEEP_SENDING_ON_ERROR, + static_cast(keep_sending)); + return *this; +} + +CurlEasyHandlerBuilder& CurlEasyHandlerBuilder::url(const std::string& url) { + curl_easy_setopt(_curl.get(), CURLOPT_URL, url.c_str()); + return *this; +} + +CurlEasyHandlerBuilder& CurlEasyHandlerBuilder::path_as_is(const bool leaveit) { + curl_easy_setopt(_curl.get(), CURLOPT_PATH_AS_IS, + static_cast(leaveit)); + return *this; +} + +CurlEasyHandlerBuilder& CurlEasyHandlerBuilder::protocols(const long bitmask) { + curl_easy_setopt(_curl.get(), CURLOPT_PROTOCOLS, bitmask); + return *this; +} + +CurlEasyHandlerBuilder& CurlEasyHandlerBuilder::protocols_str( + const std::string& spec) { + curl_easy_setopt(_curl.get(), CURLOPT_PROTOCOLS_STR, spec.c_str()); + return *this; +} + +CurlEasyHandlerBuilder& CurlEasyHandlerBuilder::redir_protocols( + const long bitmask) { + curl_easy_setopt(_curl.get(), CURLOPT_REDIR_PROTOCOLS, bitmask); + return *this; +} + +CurlEasyHandlerBuilder& CurlEasyHandlerBuilder::redir_protocols_str( + const std::string& spec) { + curl_easy_setopt(_curl.get(), CURLOPT_PROTOCOLS_STR, spec.c_str()); + return *this; +} + +CurlEasyHandlerBuilder& CurlEasyHandlerBuilder::default_protocol( + const std::string& protocol) { + curl_easy_setopt(_curl.get(), CURLOPT_DEFAULT_PROTOCOL, protocol.c_str()); + return *this; +} + +CurlEasyHandlerBuilder& CurlEasyHandlerBuilder::proxy( + const std::string& proxy) { + curl_easy_setopt(_curl.get(), CURLOPT_PROXY, proxy.c_str()); + return *this; +} + +CurlEasyHandlerBuilder& CurlEasyHandlerBuilder::pre_proxy( + const std::string& preproxy) { + curl_easy_setopt(_curl.get(), CURLOPT_PRE_PROXY, preproxy.c_str()); + return *this; +} + +CurlEasyHandlerBuilder& CurlEasyHandlerBuilder::proxy_port( + const std::uint16_t port) { + curl_easy_setopt(_curl.get(), CURLOPT_PROXYPORT, static_cast(port)); + return *this; +} + +CurlEasyHandlerBuilder& CurlEasyHandlerBuilder::proxy_type(const long type) { + curl_easy_setopt(_curl.get(), CURLOPT_PROXYPORT, type); + return *this; +} + +CurlEasyHandlerBuilder& CurlEasyHandlerBuilder::no_proxy( + const std::string& noproxy) { + curl_easy_setopt(_curl.get(), CURLOPT_NOPROXY, noproxy.c_str()); + return *this; +} + +CurlEasyHandlerBuilder& CurlEasyHandlerBuilder::http_proxy_tunnel( + const bool tunnel) { + curl_easy_setopt(_curl.get(), CURLOPT_HTTPPROXYTUNNEL, + static_cast(tunnel)); + return *this; +} + +CurlEasyHandlerBuilder& CurlEasyHandlerBuilder::connect_to( + curl_slist* const connect_to) { + curl_easy_setopt(_curl.get(), CURLOPT_CONNECT_TO, connect_to); + return *this; +} + +CurlEasyHandlerBuilder& CurlEasyHandlerBuilder::socks5_auth( + const long bitmask) { + curl_easy_setopt(_curl.get(), CURLOPT_SOCKS5_AUTH, bitmask); + return *this; +} diff --git a/src/internal/curl/CurlEasyHandlerBuilder.hpp b/src/internal/curl/CurlEasyHandlerBuilder.hpp new file mode 100644 index 0000000..2f93ca7 --- /dev/null +++ b/src/internal/curl/CurlEasyHandlerBuilder.hpp @@ -0,0 +1,157 @@ +#ifndef __WTLGO__NETWORK__INTERNAL__CURL__CURL_EASY_HANDLER_BUILDER__ +#define __WTLGO__NETWORK__INTERNAL__CURL__CURL_EASY_HANDLER_BUILDER__ + +#include +#include +#include + +#include "./Types.hpp" +#include "./CurlEasyHandler.hpp" + +namespace wtlgo { +namespace network { +namespace internal { +namespace curl { +class CurlEasyHandlerBuilder { +public: + CurlEasyHandlerBuilder(); + + CurlEasyHandler build() const; + + CurlEasyHandlerBuilder& verbose(bool onoff); + CurlEasyHandlerBuilder& header(bool onoff); + CurlEasyHandlerBuilder& no_progress(bool onoff); + CurlEasyHandlerBuilder& no_signal(bool onoff); + CurlEasyHandlerBuilder& wildcard_match(bool onoff); + + using write_function_t = std::size_t (*)(char* ptr, std::size_t size, + std::size_t nmemb, void* userdata); + CurlEasyHandlerBuilder& write_function(write_function_t write_callback); + CurlEasyHandlerBuilder& write_data(void* pointer); + + using read_function_t = std::size_t (*)(char* buffer, std::size_t size, + std::size_t nitems, void* userdata); + CurlEasyHandlerBuilder& read_function(read_function_t read_callback); + CurlEasyHandlerBuilder& read_data(void* pointer); + + using io_ctl_function_t = curlioerr (*)(CURL* handle, curliocmd cmd, + void* clientp); + CurlEasyHandlerBuilder& io_ctl_function(io_ctl_function_t ioctl_callback); + CurlEasyHandlerBuilder& io_ctl_data(void* pointer); + + using seek_function_t = int (*)(void* userp, curl_off_t offset, int origin); + CurlEasyHandlerBuilder& seek_function(seek_function_t seek_callback); + CurlEasyHandlerBuilder& seek_data(void* pointer); + + using sock_function_t = int (*)(void* clientp, curl_socket_t curlfd, + curlsocktype purpose); + CurlEasyHandlerBuilder& sock_function(sock_function_t sock_callback); + CurlEasyHandlerBuilder& sock_data(void* pointer); + + using open_socket_function_t = curl_socket_t (*)(void* clientp, + curlsocktype purpose, + curl_sockaddr* address); + CurlEasyHandlerBuilder& open_socket_function( + open_socket_function_t opensocket_callback); + CurlEasyHandlerBuilder& open_socket_data(void* pointer); + + using close_socket_function_t = curl_socket_t (*)(void* clientp, + curlsocktype purpose, + curl_sockaddr* address); + CurlEasyHandlerBuilder& close_socket_function( + close_socket_function_t closesocket_callback); + CurlEasyHandlerBuilder& close_socket_data(void* pointer); + + using xfer_info_function_t = int (*)(void* clientp, curl_off_t dltotal, + curl_off_t dlnow, curl_off_t ultotal, + curl_off_t ulnow); + CurlEasyHandlerBuilder& xfer_info_function( + xfer_info_function_t progress_callback); + CurlEasyHandlerBuilder& xfer_info_data(void* pointer); + + using header_function_t = std::size_t (*)(char* buffer, std::size_t size, + std::size_t nitems, + void* userdata); + CurlEasyHandlerBuilder& header_function(header_function_t header_callback); + CurlEasyHandlerBuilder& header_data(void* pointer); + + using debug_function_t = int (*)(CURL* handle, curl_infotype type, + char* data, std::size_t size, + void* userptr); + CurlEasyHandlerBuilder& debug_function(debug_function_t debug_callback); + CurlEasyHandlerBuilder& debug_data(void* pointer); + + using ssl_ctx_function_t = CURLcode (*)(CURL* curl, void* ssl_ctx, + void* userptr); + CurlEasyHandlerBuilder& ssl_ctx_function( + ssl_ctx_function_t ssl_ctx_callback); + CurlEasyHandlerBuilder& ssl_ctx_data(void* pointer); + + using interleave_function_t = std::size_t (*)(void* ptr, std::size_t size, + std::size_t nmemb, + void* userdata); + CurlEasyHandlerBuilder& interleave_function( + interleave_function_t interleave_callback); + CurlEasyHandlerBuilder& interleave_data(void* pointer); + + using chunk_bgn_function_t = long (*)(const void* transfer_info, void* ptr, + int remains); + using chunk_end_function_t = long (*)(void* ptr); + CurlEasyHandlerBuilder& chunk_bgn_function( + chunk_bgn_function_t chunk_bgn_callback); + CurlEasyHandlerBuilder& chunk_end_function( + chunk_end_function_t chunk_end_callback); + CurlEasyHandlerBuilder& chunk_data(void* pointer); + + using fnmatch_function_t = int (*)(void* ptr, const char* pattern, + const char* string); + CurlEasyHandlerBuilder& fnmatch_function( + fnmatch_function_t fnmatch_callback); + CurlEasyHandlerBuilder& fnmatch_data(void* pointer); + + CurlEasyHandlerBuilder& supress_connect_headers(bool onoff); + + using resolver_start_function_t = int (*)(void* resolver_state, + void* reserved, void* userdata); + CurlEasyHandlerBuilder& resolver_start_function( + resolver_start_function_t resolver_start_cb); + CurlEasyHandlerBuilder& resolver_start_data(void* pointer); + + using prereq_function_t = int (*)(void* clientp, char* conn_primary_ip, + char* conn_local_ip, + int conn_primary_port, + int conn_local_port); + CurlEasyHandlerBuilder& prereq_function(prereq_function_t prereq_callback); + CurlEasyHandlerBuilder& prereq_data(void* pointer); + + CurlEasyHandlerBuilder& error_buffer(char* buf); + CurlEasyHandlerBuilder& std_err(FILE* stream); + CurlEasyHandlerBuilder& fail_on_error(bool fail); + CurlEasyHandlerBuilder& keep_sending_on_error(bool keep_sending); + + CurlEasyHandlerBuilder& url(const std::string& url); + CurlEasyHandlerBuilder& path_as_is(bool leaveit); + CurlEasyHandlerBuilder& protocols(long bitmask); + CurlEasyHandlerBuilder& protocols_str(const std::string& spec); + CurlEasyHandlerBuilder& redir_protocols(long bitmask); + CurlEasyHandlerBuilder& redir_protocols_str(const std::string& spec); + CurlEasyHandlerBuilder& default_protocol(const std::string& protocol); + CurlEasyHandlerBuilder& proxy(const std::string& proxy); + CurlEasyHandlerBuilder& pre_proxy(const std::string& preproxy); + CurlEasyHandlerBuilder& proxy_port(std::uint16_t port); + CurlEasyHandlerBuilder& proxy_type(long type); + CurlEasyHandlerBuilder& no_proxy(const std::string& noproxy); + CurlEasyHandlerBuilder& http_proxy_tunnel(bool tunnel); + CurlEasyHandlerBuilder& connect_to(curl_slist* connect_to); + CurlEasyHandlerBuilder& socks5_auth(long bitmask); + + // TODO: https://curl.se/libcurl/c/curl_easy_setopt.html +private: + const curl_unique_ptr _curl; +}; +} +} +} +} + +#endif diff --git a/src/internal/curl/CurlHandlerBuilder.cpp b/src/internal/curl/CurlHandlerBuilder.cpp deleted file mode 100644 index cbca4b1..0000000 --- a/src/internal/curl/CurlHandlerBuilder.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "./CurlHandlerBuilder.hpp" \ No newline at end of file diff --git a/src/internal/curl/CurlHandlerBuilder.hpp b/src/internal/curl/CurlHandlerBuilder.hpp deleted file mode 100644 index 623b268..0000000 --- a/src/internal/curl/CurlHandlerBuilder.hpp +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef __WTLGO__NETWORK__INTERNAL__CURL__CURL_HANDLER_BUILDER__ -#define __WTLGO__NETWORK__INTERNAL__CURL__CURL_HANDLER_BUILDER__ - -namespace wtlgo { -namespace network { -namespace internal { -namespace curl { -class CurlHandlerBuilder {}; -} -} -} -} - -#endif