From f1968ea38e51201b37962a9cfd80775989a56d46 Mon Sep 17 00:00:00 2001 From: Bernardo Meurer Costa Date: Thu, 23 Oct 2025 05:03:16 +0000 Subject: [PATCH 1/3] refactor(libstore): replace HTTP method boolean flags with enum Replace the individual boolean flags (head, post) with a unified HttpMethod enum struct in FileTransferRequest. --- src/libfetchers/git-lfs-fetch.cc | 2 +- src/libstore/filetransfer.cc | 4 ++-- src/libstore/http-binary-cache-store.cc | 2 +- .../include/nix/store/filetransfer.hh | 21 ++++++++++++++++--- 4 files changed, 22 insertions(+), 7 deletions(-) diff --git a/src/libfetchers/git-lfs-fetch.cc b/src/libfetchers/git-lfs-fetch.cc index 9688daa4a..aee1163bb 100644 --- a/src/libfetchers/git-lfs-fetch.cc +++ b/src/libfetchers/git-lfs-fetch.cc @@ -209,7 +209,7 @@ std::vector Fetch::fetchUrls(const std::vector & pointe auto url = api.endpoint + "/objects/batch"; const auto & authHeader = api.authHeader; FileTransferRequest request(parseURL(url)); - request.post = true; + request.method = HttpMethod::POST; Headers headers; if (authHeader.has_value()) headers.push_back({"Authorization", *authHeader}); diff --git a/src/libstore/filetransfer.cc b/src/libstore/filetransfer.cc index b9e52e7d5..c2c2a86c4 100644 --- a/src/libstore/filetransfer.cc +++ b/src/libstore/filetransfer.cc @@ -384,11 +384,11 @@ struct curlFileTransfer : public FileTransfer if (settings.downloadSpeed.get() > 0) curl_easy_setopt(req, CURLOPT_MAX_RECV_SPEED_LARGE, (curl_off_t) (settings.downloadSpeed.get() * 1024)); - if (request.head) + if (request.method == HttpMethod::HEAD) curl_easy_setopt(req, CURLOPT_NOBODY, 1); if (request.data) { - if (request.post) { + if (request.method == HttpMethod::POST) { curl_easy_setopt(req, CURLOPT_POST, 1L); curl_easy_setopt(req, CURLOPT_POSTFIELDSIZE_LARGE, (curl_off_t) request.data->length()); } else { diff --git a/src/libstore/http-binary-cache-store.cc b/src/libstore/http-binary-cache-store.cc index 9567aec2f..5c455dd04 100644 --- a/src/libstore/http-binary-cache-store.cc +++ b/src/libstore/http-binary-cache-store.cc @@ -139,7 +139,7 @@ protected: try { FileTransferRequest request(makeRequest(path)); - request.head = true; + request.method = HttpMethod::HEAD; getFileTransfer()->download(request); return true; } catch (FileTransferError & e) { diff --git a/src/libstore/include/nix/store/filetransfer.hh b/src/libstore/include/nix/store/filetransfer.hh index 2b86f6ac9..286014517 100644 --- a/src/libstore/include/nix/store/filetransfer.hh +++ b/src/libstore/include/nix/store/filetransfer.hh @@ -83,6 +83,15 @@ extern FileTransferSettings fileTransferSettings; extern const unsigned int RETRY_TIME_MS_DEFAULT; +/** + * HTTP methods supported by FileTransfer. + */ +enum struct HttpMethod { + GET, + HEAD, + POST, +}; + /** * Username and optional password for HTTP basic authentication. * These are used with curl's CURLOPT_USERNAME and CURLOPT_PASSWORD options @@ -99,8 +108,7 @@ struct FileTransferRequest VerbatimURL uri; Headers headers; std::string expectedETag; - bool head = false; - bool post = false; + HttpMethod method = HttpMethod::GET; size_t tries = fileTransferSettings.tries; unsigned int baseRetryTimeMs = RETRY_TIME_MS_DEFAULT; ActivityId parentAct; @@ -129,7 +137,14 @@ struct FileTransferRequest std::string verb() const { - return data ? "upload" : "download"; + switch (method) { + case HttpMethod::HEAD: + case HttpMethod::GET: + return "download"; + case HttpMethod::POST: + return "upload"; + } + unreachable(); } private: From d924374bf22176263409c3ad49982aad4e906b2f Mon Sep 17 00:00:00 2001 From: Bernardo Meurer Costa Date: Thu, 23 Oct 2025 20:48:21 +0000 Subject: [PATCH 2/3] docs(libstore): document verb() method returns verb root for gerund form Add documentation to FileTransferRequest::verb() explaining that it returns a verb root intended to be concatenated with "ing" to form the gerund. --- src/libstore/include/nix/store/filetransfer.hh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/libstore/include/nix/store/filetransfer.hh b/src/libstore/include/nix/store/filetransfer.hh index 286014517..a9ed05dc8 100644 --- a/src/libstore/include/nix/store/filetransfer.hh +++ b/src/libstore/include/nix/store/filetransfer.hh @@ -135,6 +135,11 @@ struct FileTransferRequest { } + /** + * Returns the verb root for logging purposes. + * The returned string is intended to be concatenated with "ing" to form the gerund, + * e.g., "download" + "ing" -> "downloading", "upload" + "ing" -> "uploading". + */ std::string verb() const { switch (method) { From afe5ed879f7015e62bcf431f0bdf70093af63ca5 Mon Sep 17 00:00:00 2001 From: Bernardo Meurer Costa Date: Tue, 21 Oct 2025 09:02:36 +0000 Subject: [PATCH 3/3] feat(libstore): add DELETE method support to FileTransfer Add support for HTTP DELETE requests to FileTransfer infrastructure: This enables S3 multipart upload abort functionality via DELETE requests to S3 endpoints. --- src/libstore/filetransfer.cc | 8 ++++++++ src/libstore/include/nix/store/filetransfer.hh | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/src/libstore/filetransfer.cc b/src/libstore/filetransfer.cc index c2c2a86c4..9fd7a967b 100644 --- a/src/libstore/filetransfer.cc +++ b/src/libstore/filetransfer.cc @@ -387,6 +387,9 @@ struct curlFileTransfer : public FileTransfer if (request.method == HttpMethod::HEAD) curl_easy_setopt(req, CURLOPT_NOBODY, 1); + if (request.method == HttpMethod::DELETE) + curl_easy_setopt(req, CURLOPT_CUSTOMREQUEST, "DELETE"); + if (request.data) { if (request.method == HttpMethod::POST) { curl_easy_setopt(req, CURLOPT_POST, 1L); @@ -919,6 +922,11 @@ FileTransferResult FileTransfer::upload(const FileTransferRequest & request) return enqueueFileTransfer(request).get(); } +FileTransferResult FileTransfer::deleteResource(const FileTransferRequest & request) +{ + return enqueueFileTransfer(request).get(); +} + void FileTransfer::download( FileTransferRequest && request, Sink & sink, std::function resultCallback) { diff --git a/src/libstore/include/nix/store/filetransfer.hh b/src/libstore/include/nix/store/filetransfer.hh index a9ed05dc8..402ee4900 100644 --- a/src/libstore/include/nix/store/filetransfer.hh +++ b/src/libstore/include/nix/store/filetransfer.hh @@ -90,6 +90,7 @@ enum struct HttpMethod { GET, HEAD, POST, + DELETE, }; /** @@ -148,6 +149,8 @@ struct FileTransferRequest return "download"; case HttpMethod::POST: return "upload"; + case HttpMethod::DELETE: + return "delet"; } unreachable(); } @@ -221,6 +224,11 @@ struct FileTransfer */ FileTransferResult upload(const FileTransferRequest & request); + /** + * Synchronously delete a resource. + */ + FileTransferResult deleteResource(const FileTransferRequest & request); + /** * Download a file, writing its data to a sink. The sink will be * invoked on the thread of the caller.