mirror of
https://github.com/NixOS/nix.git
synced 2025-11-09 03:56:01 +01:00
fix(libutil/tarfile): normalize legacy HTTP Content-Encoding names
Nix failed to download files served with `Content-Encoding: x-gzip` because libarchive doesn't recognize the legacy `x-*` compression format names. Per RFC 9110 §8.4.1.3, HTTP recipients should treat these as equivalent to their standard counterparts. Adds `normalizeCompressionMethod()` to map legacy encoding names before passing to libarchive: - `x-gzip` → `gzip` - `x-compress` → `compress` - `x-bzip2` → `bzip2`
This commit is contained in:
parent
da637a05da
commit
1667782c67
2 changed files with 46 additions and 1 deletions
|
|
@ -74,6 +74,30 @@ TEST(decompress, decompressInvalidInputThrowsCompressionError)
|
||||||
ASSERT_THROW(decompress(method, str), CompressionError);
|
ASSERT_THROW(decompress(method, str), CompressionError);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------------
|
||||||
|
* legacy HTTP Content-Encoding names (RFC 9110)
|
||||||
|
* --------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
TEST(decompress, decompressXGzipCompressed)
|
||||||
|
{
|
||||||
|
// Test that x-gzip (legacy HTTP Content-Encoding) works like gzip
|
||||||
|
auto str = "slfja;sljfklsa;jfklsjfkl;sdjfkl;sadjfkl;sdjf;lsdfjsadlf";
|
||||||
|
auto compressedData = compress("gzip", str);
|
||||||
|
auto o = decompress("x-gzip", compressedData);
|
||||||
|
|
||||||
|
ASSERT_EQ(o, str);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(decompress, decompressXBzip2Compressed)
|
||||||
|
{
|
||||||
|
// Test that x-bzip2 (legacy HTTP Content-Encoding) works like bzip2
|
||||||
|
auto str = "slfja;sljfklsa;jfklsjfkl;sdjfkl;sadjfkl;sdjf;lsdfjsadlf";
|
||||||
|
auto compressedData = compress("bzip2", str);
|
||||||
|
auto o = decompress("x-bzip2", compressedData);
|
||||||
|
|
||||||
|
ASSERT_EQ(o, str);
|
||||||
|
}
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------------
|
/* ----------------------------------------------------------------------------
|
||||||
* compression sinks
|
* compression sinks
|
||||||
* --------------------------------------------------------------------------*/
|
* --------------------------------------------------------------------------*/
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,26 @@ void TarArchive::check(int err, const std::string & reason)
|
||||||
checkLibArchive(archive, err, reason);
|
checkLibArchive(archive, err, reason);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @brief Normalize compression method names from legacy HTTP Content-Encoding values.
|
||||||
|
///
|
||||||
|
/// Per RFC 9110 Section 8.4.1.3, HTTP recipients should treat legacy "x-*" compression
|
||||||
|
/// names as equivalent to their standard counterparts:
|
||||||
|
/// - "x-gzip" is equivalent to "gzip"
|
||||||
|
/// - "x-compress" is equivalent to "compress"
|
||||||
|
///
|
||||||
|
/// This function maps these legacy names to their libarchive-compatible equivalents.
|
||||||
|
static std::string normalizeCompressionMethod(const std::string & method)
|
||||||
|
{
|
||||||
|
if (method == "x-gzip")
|
||||||
|
return "gzip";
|
||||||
|
else if (method == "x-compress")
|
||||||
|
return "compress";
|
||||||
|
else if (method == "x-bzip2")
|
||||||
|
return "bzip2";
|
||||||
|
else
|
||||||
|
return method;
|
||||||
|
}
|
||||||
|
|
||||||
/// @brief Get filter_code from its name.
|
/// @brief Get filter_code from its name.
|
||||||
///
|
///
|
||||||
/// libarchive does not provide a convenience function like archive_write_add_filter_by_name but for reading.
|
/// libarchive does not provide a convenience function like archive_write_add_filter_by_name but for reading.
|
||||||
|
|
@ -59,9 +79,10 @@ void TarArchive::check(int err, const std::string & reason)
|
||||||
/// hand-rolling the equivalent function that is better implemented in libarchive.
|
/// hand-rolling the equivalent function that is better implemented in libarchive.
|
||||||
int getArchiveFilterCodeByName(const std::string & method)
|
int getArchiveFilterCodeByName(const std::string & method)
|
||||||
{
|
{
|
||||||
|
auto normalizedMethod = normalizeCompressionMethod(method);
|
||||||
auto * ar = archive_write_new();
|
auto * ar = archive_write_new();
|
||||||
auto cleanup = Finally{[&ar]() { checkLibArchive(ar, archive_write_close(ar), "failed to close archive: %s"); }};
|
auto cleanup = Finally{[&ar]() { checkLibArchive(ar, archive_write_close(ar), "failed to close archive: %s"); }};
|
||||||
auto err = archive_write_add_filter_by_name(ar, method.c_str());
|
auto err = archive_write_add_filter_by_name(ar, normalizedMethod.c_str());
|
||||||
checkLibArchive(ar, err, "failed to get libarchive filter by name: %s");
|
checkLibArchive(ar, err, "failed to get libarchive filter by name: %s");
|
||||||
auto code = archive_filter_code(ar, 0);
|
auto code = archive_filter_code(ar, 0);
|
||||||
return code;
|
return code;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue