From 7c716b9716559eb5c2bcdbe72355678bde30c87e Mon Sep 17 00:00:00 2001 From: eldritch horrors Date: Sun, 27 Oct 2024 18:27:11 +0100 Subject: [PATCH] libstore: use effective transfer url for retries do not retread the entire redirection path if we've seen the end of the road. this avoids silently downloading wrong data, and notifies us when a url we've received data from turns into a redirect when retrying. for reasons of simplicity we don't turn of libcurl redirects on retries. if we did that we'd have to conditionally process http status codes, which sounds annoying and would make the header callback even more of a mess. Change-Id: Ide0c0512ef9b2579350101246d654a2375541a39 --- src/libstore/filetransfer.cc | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/libstore/filetransfer.cc b/src/libstore/filetransfer.cc index 24cc67d8a..c75e7a627 100644 --- a/src/libstore/filetransfer.cc +++ b/src/libstore/filetransfer.cc @@ -167,8 +167,19 @@ struct curlFileTransfer : public FileTransfer char * effectiveUriCStr = nullptr; curl_easy_getinfo(req, CURLINFO_EFFECTIVE_URL, &effectiveUriCStr); - if (effectiveUriCStr) + if (effectiveUriCStr) { + if (!result.effectiveUri.empty() && result.effectiveUri != effectiveUriCStr) { + throw FileTransferError( + Misc, + {}, + "uri %s changed final destination from %s to %s during transfer", + uri, + result.effectiveUri, + effectiveUriCStr + ); + } result.effectiveUri = effectiveUriCStr; + } result.cached = getHTTPStatus() == 304; @@ -307,6 +318,10 @@ struct curlFileTransfer : public FileTransfer curl_easy_setopt(req, CURLOPT_DEBUGFUNCTION, TransferItem::debugCallback); } + // use the effective URI of the previous transfer for retries. this avoids + // some silent corruption if a redirect changes between starting and retry. + const auto & uri = result.effectiveUri.empty() ? this->uri : result.effectiveUri; + curl_easy_setopt(req, CURLOPT_URL, uri.c_str()); curl_easy_setopt(req, CURLOPT_FOLLOWLOCATION, 1L); curl_easy_setopt(req, CURLOPT_MAXREDIRS, 10);