1
1
Fork 0
mirror of https://github.com/NixOS/nix.git synced 2025-11-08 19:46:02 +01:00

feat(libstore/s3-binary-cache-store): implement createMultipartUpload()

POST to key with `?uploads` query parameter, optionally set
`Content-Encoding` header, parse `uploadId` from XML response using
regex
This commit is contained in:
Bernardo Meurer Costa 2025-10-24 23:53:39 +00:00
parent ac8b1efcf9
commit 4b6d07d642
No known key found for this signature in database

View file

@ -4,6 +4,7 @@
#include <cassert>
#include <ranges>
#include <regex>
namespace nix {
@ -27,6 +28,15 @@ public:
private:
ref<S3BinaryCacheStoreConfig> s3Config;
/**
* Creates a multipart upload for large objects to S3.
*
* @see
* https://docs.aws.amazon.com/AmazonS3/latest/API/API_CreateMultipartUpload.html#API_CreateMultipartUpload_RequestSyntax
*/
std::string createMultipartUpload(
std::string_view key, std::string_view mimeType, std::optional<std::string_view> contentEncoding);
/**
* Abort a multipart upload
*
@ -45,6 +55,39 @@ void S3BinaryCacheStore::upsertFile(
HttpBinaryCacheStore::upsertFile(path, istream, mimeType, sizeHint);
}
std::string S3BinaryCacheStore::createMultipartUpload(
std::string_view key, std::string_view mimeType, std::optional<std::string_view> contentEncoding)
{
auto req = makeRequest(key);
// setupForS3() converts s3:// to https:// but strips query parameters
// So we call it first, then add our multipart parameters
req.setupForS3();
auto url = req.uri.parsed();
url.query["uploads"] = "";
req.uri = VerbatimURL(url);
req.method = HttpMethod::POST;
req.data = "";
req.mimeType = mimeType;
if (contentEncoding) {
req.headers.emplace_back("Content-Encoding", *contentEncoding);
}
auto result = getFileTransfer()->enqueueFileTransfer(req).get();
std::regex uploadIdRegex("<UploadId>([^<]+)</UploadId>");
std::smatch match;
if (std::regex_search(result.data, match, uploadIdRegex)) {
return match[1];
}
throw Error("S3 CreateMultipartUpload response missing <UploadId>");
}
void S3BinaryCacheStore::abortMultipartUpload(std::string_view key, std::string_view uploadId)
{
auto req = makeRequest(key);