summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPaul Cristian Sarbu <paul.cristian.sarbu@huawei.com>2023-11-06 17:44:48 +0100
committerPaul Cristian Sarbu <paul.cristian.sarbu@huawei.com>2023-11-14 13:35:01 +0100
commitaf2409ef15993d97df342115b34799cc56558015 (patch)
tree7f78a954cc1b0dfdf210acb7b5d9f507386ae0a8 /src
parent8d656639aa07a9677a7c4c1ce8ce0a68287d99e5 (diff)
downloadjustbuild-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.cpp46
-rw-r--r--src/other_tools/utils/curl_url_handle.hpp11
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!