1
1
Fork 0
mirror of https://github.com/NixOS/nix.git synced 2025-11-16 07:22:43 +01:00

lib{store,fetchers}: Pass URLs specified directly verbatim to FileTransferRequest

The URL should not be normalized before handing it off to cURL, because
builtin fetchers like fetchTarball/fetchurl are expected to work with
arbitrary URLs, that might not be RFC3986 compliant. For those cases
Nix should not normalize URLs, though validation is fine. ParseURL and
cURL are supposed to match the set of acceptable URLs, since they implement
the same RFC.
This commit is contained in:
Sergei Zimmerman 2025-09-01 00:35:31 +03:00
parent 2746985d90
commit e548700010
No known key found for this signature in database
8 changed files with 84 additions and 14 deletions

View file

@ -341,4 +341,63 @@ ParsedURL fixGitURL(const std::string & url);
*/
bool isValidSchemeName(std::string_view scheme);
/**
* Either a ParsedURL or a verbatim string, but the string must be a valid
* ParsedURL. This is necessary because in certain cases URI must be passed
* verbatim (e.g. in builtin fetchers), since those are specified by the user.
* In those cases normalizations performed by the ParsedURL might be surprising
* and undesirable, since Nix must be a universal client that has to work with
* various broken services that might interpret URLs in quirky and non-standard ways.
*
* One of those examples is space-as-plus encoding that is very widespread, but it's
* not strictly RFC3986 compliant. We must preserve that information verbatim.
*
* Though we perform parsing and validation for internal needs.
*/
struct ValidURL : private ParsedURL
{
std::optional<std::string> encoded;
ValidURL(std::string str)
: ParsedURL(parseURL(str, /*lenient=*/false))
, encoded(std::move(str))
{
}
ValidURL(std::string_view str)
: ValidURL(std::string{str})
{
}
ValidURL(ParsedURL parsed)
: ParsedURL{std::move(parsed)}
{
}
/**
* Get the encoded URL (if specified) verbatim or encode the parsed URL.
*/
std::string to_string() const
{
return encoded.or_else([&]() -> std::optional<std::string> { return ParsedURL::to_string(); }).value();
}
const ParsedURL & parsed() const &
{
return *this;
}
std::string_view scheme() const &
{
return ParsedURL::scheme;
}
const auto & path() const &
{
return ParsedURL::path;
}
};
std::ostream & operator<<(std::ostream & os, const ValidURL & url);
} // namespace nix

View file

@ -434,4 +434,10 @@ bool isValidSchemeName(std::string_view s)
return std::regex_match(s.begin(), s.end(), regex, std::regex_constants::match_default);
}
std::ostream & operator<<(std::ostream & os, const ValidURL & url)
{
os << url.to_string();
return os;
}
} // namespace nix