From 83d8e7c4d0a932bc0acb2e10d7afa32ea02ccc36 Mon Sep 17 00:00:00 2001 From: George Tokmaji Date: Thu, 9 Nov 2023 11:06:44 +0100 Subject: [PATCH] C4HTTPClient::Uri: Refactor parsing so that all clonk-style URIs work --- src/C4HTTPClient.cpp | 57 ++++++++++++++++++++++++++----------- src/C4HTTPClient.h | 9 ++++++ src/C4Network2Reference.cpp | 2 +- 3 files changed, 51 insertions(+), 17 deletions(-) diff --git a/src/C4HTTPClient.cpp b/src/C4HTTPClient.cpp index d0ce03ad8..a99ae9266 100644 --- a/src/C4HTTPClient.cpp +++ b/src/C4HTTPClient.cpp @@ -59,27 +59,20 @@ void C4HTTPClient::Uri::CURLUDeleter::operator()(CURLU * const uri) C4HTTPClient::Uri::Uri(const std::string &serverAddress, const std::uint16_t port) : uri{ThrowIfFailed(curl_url(), "curl_url failed")} { - CURLUcode urlError{curl_url_set(uri.get(), CURLUPART_URL, serverAddress.c_str(), 0)}; - if (urlError == CURLUE_UNSUPPORTED_SCHEME) + ThrowIfFailed(curl_url_set(uri.get(), CURLUPART_URL, serverAddress.c_str(), 0) == CURLUE_OK, "malformed URL"); + + if (port > 0) { - urlError = curl_url_set(uri.get(), CURLUPART_URL, std::format("http://{}", serverAddress).c_str(), 0); + SetPort(port); } +} - ThrowIfFailed(urlError == CURLUE_OK, "malformed URL"); - +C4HTTPClient::Uri::Uri(std::unique_ptr uri, const std::uint16_t port) + : uri{std::move(uri)} +{ if (port > 0) { - char *portString; - const auto errGetPort = curl_url_get(uri.get(), CURLUPART_PORT, &portString, 0); - curl_free(portString); - if (errGetPort == CURLUE_NO_PORT) - { - ThrowIfFailed(curl_url_set(uri.get(), CURLUPART_PORT, std::to_string(port).c_str(), 0) == CURLUE_OK, "curl_url_set PORT failed"); - } - else - { - ThrowIfFailed(errGetPort == CURLUE_OK, "curl_url_get PORT failed"); - } + SetPort(port); } } @@ -101,6 +94,38 @@ std::string C4HTTPClient::Uri::GetUriAsString() const return string; } +C4HTTPClient::Uri C4HTTPClient::Uri::ParseOldStyle(const std::string &serverAddress, const std::uint16_t port) +{ + std::unique_ptr uri{ThrowIfFailed(curl_url(), "curl_url failed")}; + + CURLUcode result{curl_url_set(uri.get(), CURLUPART_URL, serverAddress.c_str(), 0)}; + + if (result == CURLUE_BAD_SCHEME || result == CURLUE_UNSUPPORTED_SCHEME) + { + result = curl_url_set(uri.get(), CURLUPART_URL, std::format("http://{}", serverAddress).c_str(), 0); + } + + ThrowIfFailed(result == CURLUE_OK, "malformed URL"); + + return {std::move(uri), port}; +} + +void C4HTTPClient::Uri::SetPort(const std::uint16_t port) +{ + char *portString; + const auto errGetPort = curl_url_get(uri.get(), CURLUPART_PORT, &portString, 0); + curl_free(portString); + + if (errGetPort == CURLUE_NO_PORT) + { + ThrowIfFailed(curl_url_set(uri.get(), CURLUPART_PORT, std::to_string(port).c_str(), 0) == CURLUE_OK, "curl_url_set PORT failed"); + } + else + { + ThrowIfFailed(errGetPort == CURLUE_OK, "curl_url_get PORT failed"); + } +} + C4HTTPClient::C4HTTPClient() : shareHandle{ThrowIfFailed(curl_share_init(), "curl_share_init failed")} { diff --git a/src/C4HTTPClient.h b/src/C4HTTPClient.h index 78237c035..7c147ec9f 100644 --- a/src/C4HTTPClient.h +++ b/src/C4HTTPClient.h @@ -67,12 +67,21 @@ class C4HTTPClient public: Uri(const std::string &serverAddress, std::uint16_t port = 0); + private: + Uri(std::unique_ptr uri, std::uint16_t port = 0); + public: std::string GetServerAddress() const; std::string GetUriAsString() const; auto get() const { return uri.get(); } + public: + [[nodiscard]] static Uri ParseOldStyle(const std::string &serverAddress, std::uint16_t port = 0); + + private: + void SetPort(std::uint16_t port); + private: std::unique_ptr uri; }; diff --git a/src/C4Network2Reference.cpp b/src/C4Network2Reference.cpp index 4c9547166..ee155d4ec 100644 --- a/src/C4Network2Reference.cpp +++ b/src/C4Network2Reference.cpp @@ -287,7 +287,7 @@ void C4Network2HTTPClient::Clear() bool C4Network2HTTPClient::SetServer(const std::string_view serverAddress, const std::uint16_t defaultPort) try { - const C4HTTPClient::Uri uri{std::string{serverAddress}, defaultPort}; + const auto uri = C4HTTPClient::Uri::ParseOldStyle(std::string{serverAddress}, defaultPort); url = uri.GetUriAsString(); serverName = uri.GetServerAddress(); return true;