diff options
author | Paul Cristian Sarbu <paul.cristian.sarbu@huawei.com> | 2023-11-06 17:44:48 +0100 |
---|---|---|
committer | Paul Cristian Sarbu <paul.cristian.sarbu@huawei.com> | 2023-11-14 13:35:01 +0100 |
commit | af2409ef15993d97df342115b34799cc56558015 (patch) | |
tree | 7f78a954cc1b0dfdf210acb7b5d9f507386ae0a8 /src | |
parent | 8d656639aa07a9677a7c4c1ce8ce0a68287d99e5 (diff) | |
download | justbuild-af2409ef15993d97df342115b34799cc56558015.tar.gz |
curl_url_handle: Add method to replace the hostname of a URL
Also adds a section in the curl_url test suite.
Diffstat (limited to 'src')
-rw-r--r-- | src/other_tools/utils/curl_url_handle.cpp | 46 | ||||
-rw-r--r-- | src/other_tools/utils/curl_url_handle.hpp | 11 |
2 files changed, 57 insertions, 0 deletions
diff --git a/src/other_tools/utils/curl_url_handle.cpp b/src/other_tools/utils/curl_url_handle.cpp index 90102e0b..5722a1cb 100644 --- a/src/other_tools/utils/curl_url_handle.cpp +++ b/src/other_tools/utils/curl_url_handle.cpp @@ -788,3 +788,49 @@ auto CurlURLHandle::NoproxyStringMatches(std::string const& no_proxy) noexcept return std::nullopt; } } + +auto CurlURLHandle::ReplaceHostname(std::string const& url, + std::string const& hostname) noexcept + -> std::optional<std::string> { + try { + // We should not guess the scheme based on current hostname, as it may + // cause the URL with the new hostname to falsely fail; we set + // use_default_scheme instead. Additionally, we set use_no_authority to + // false as the given URL MUST already have a hostname to be replaced. + if (auto parsed_url = CreatePermissive(url, + false /*use_guess_scheme*/, + true /*use_default_scheme*/, + true /*use_non_support_scheme*/, + false /*use_no_authority*/, + true /*use_path_as_is*/, + true /*use_allow_space*/, + true /*ignore_fatal*/)) { + if (*parsed_url == nullptr) { + return std::nullopt; + } + auto rc = curl_url_set(parsed_url.value()->handle_.get(), + CURLUPART_HOST, + hostname.c_str(), + 0U); + if (rc != CURLUE_OK) { + Logger::Log(LogLevel::Debug, + "CurlURLHandle: setting hostname {} in URL {} " + "failed with:\n{}", + hostname, + url, + curl_url_strerror(rc)); + return std::nullopt; + } + return parsed_url.value()->GetURL(false /*use_default_port*/, + true /*use_default_scheme*/, + false /*use_no_default_port*/, + true /*ignore_fatal*/); + } + } catch (std::exception const& ex) { + Logger::Log(LogLevel::Debug, + "CurlURLHandle: Replacing URL hostname failed unexpectedly " + "with:\n{}", + ex.what()); + } + return std::nullopt; +} diff --git a/src/other_tools/utils/curl_url_handle.hpp b/src/other_tools/utils/curl_url_handle.hpp index dfd278d7..5648a535 100644 --- a/src/other_tools/utils/curl_url_handle.hpp +++ b/src/other_tools/utils/curl_url_handle.hpp @@ -154,6 +154,17 @@ class CurlURLHandle { [[nodiscard]] auto NoproxyStringMatches( std::string const& no_proxy) noexcept -> std::optional<bool>; + /// \brief Tries to replace the hostname of a given URL. This is done by + /// parsing the URL with minimal validity checks, replacing the original + /// hostname with the one given, then putting the new URL back together. + /// \note The given URL MUST have a hostname for this to succeed. + /// \note A missing scheme field will be set to "https://" and a missing + /// path field will be set to "/". + /// \returns The new URL or nullopt on errors. This method is never fatal. + [[nodiscard]] static auto ReplaceHostname( + std::string const& url, + std::string const& hostname) noexcept -> std::optional<std::string>; + private: // IMPORTANT: the CurlContext must be initialized before any curl // object! |