From dd4a2c17593283456884db18fa32ea01851fd2c5 Mon Sep 17 00:00:00 2001 From: eldritch horrors Date: Wed, 29 May 2024 20:51:37 +0200 Subject: libstore: fix http abuses no longer working while refactoring the curl wrapper we inadvertently broken the immutable flake protocol, because the immutable flake protocol accumulates headers across the entire redirect chain instead of using only the headers given in the final response of the chain. this is a problem because Some Known Providers Of Flake Infrastructure set rel=immutable link headers only in the penultimate entry of the redirect chain, and curl does not regard it as worth returning to us via its response header enumeration mechanisms. fixes https://git.lix.systems/lix-project/lix/issues/358 Change-Id: I645c3932b465cde848bd6a3565925a1e3cbcdda0 --- tests/unit/libstore/filetransfer.cc | 53 +++++++++++++++++++++++++++++++++---- 1 file changed, 48 insertions(+), 5 deletions(-) (limited to 'tests') diff --git a/tests/unit/libstore/filetransfer.cc b/tests/unit/libstore/filetransfer.cc index 684697c69..0e5c0965e 100644 --- a/tests/unit/libstore/filetransfer.cc +++ b/tests/unit/libstore/filetransfer.cc @@ -23,10 +23,19 @@ using namespace std::chrono_literals; +namespace { + +struct Reply { + std::string status, headers; + std::function content; +}; + +} + namespace nix { static std::tuple -serveHTTP(std::string_view status, std::string_view headers, std::function content) +serveHTTP(std::vector replies) { AutoCloseFD listener(::socket(AF_INET6, SOCK_STREAM, 0)); if (!listener) { @@ -52,7 +61,7 @@ serveHTTP(std::string_view status, std::string_view headers, std::function +serveHTTP(std::string status, std::string headers, std::function content) +{ + return serveHTTP({{{status, headers, content}}}); +} + TEST(FileTransfer, exceptionAbortsDownload) { struct Done @@ -166,4 +183,30 @@ TEST(FileTransfer, NOT_ON_DARWIN(handlesContentEncoding)) ft->download(FileTransferRequest(fmt("http://[::1]:%d/index", port)), sink); EXPECT_EQ(sink.s, original); } + +TEST(FileTransfer, usesIntermediateLinkHeaders) +{ + auto [port, srv] = serveHTTP({ + {"301 ok", + "location: /second\r\n" + "content-length: 0\r\n", + [] { return ""; }}, + {"307 ok", + "location: /third\r\n" + "content-length: 0\r\n", + [] { return ""; }}, + {"307 ok", + "location: /fourth\r\n" + "link: ; rel=\"immutable\"\r\n" + "content-length: 0\r\n", + [] { return ""; }}, + {"200 ok", "content-length: 1\r\n", [] { return "a"; }}, + }); + auto ft = makeFileTransfer(); + FileTransferRequest req(fmt("http://[::1]:%d/first", port)); + req.baseRetryTimeMs = 0; + auto result = ft->download(req); + ASSERT_EQ(result.immutableUrl, "http://foo"); +} + } -- cgit v1.2.3