forked from lix-project/lix
HttpBinaryCacheStore: Support upsertFile with PUT.
Some servers, such as Artifactory, allow uploading with PUT and BASIC auth. This allows nix copy to work to upload binaries to those servers. Worked on together with @adelbertc
This commit is contained in:
parent
e09161d05c
commit
1d5d277ac7
|
@ -22,6 +22,7 @@
|
|||
#include <thread>
|
||||
#include <cmath>
|
||||
#include <random>
|
||||
#include <algorithm>
|
||||
|
||||
using namespace std::string_literals;
|
||||
|
||||
|
@ -91,6 +92,8 @@ struct CurlDownloader : public Downloader
|
|||
{
|
||||
if (!request.expectedETag.empty())
|
||||
requestHeaders = curl_slist_append(requestHeaders, ("If-None-Match: " + request.expectedETag).c_str());
|
||||
if (!request.mimeType.empty())
|
||||
requestHeaders = curl_slist_append(requestHeaders, ("Content-Type: " + request.mimeType).c_str());
|
||||
}
|
||||
|
||||
~DownloadItem()
|
||||
|
@ -185,6 +188,22 @@ struct CurlDownloader : public Downloader
|
|||
return 0;
|
||||
}
|
||||
|
||||
size_t readOffset = 0;
|
||||
int readCallback(char *buffer, size_t size, size_t nitems)
|
||||
{
|
||||
if (readOffset == request.data->length())
|
||||
return 0;
|
||||
auto count = std::min(size * nitems, request.data->length() - readOffset);
|
||||
memcpy(buffer, request.data->data() + readOffset, count);
|
||||
readOffset += count;
|
||||
return count;
|
||||
}
|
||||
|
||||
static int readCallbackWrapper(char *buffer, size_t size, size_t nitems, void * userp)
|
||||
{
|
||||
return ((DownloadItem *) userp)->readCallback(buffer, size, nitems);
|
||||
}
|
||||
|
||||
long lowSpeedTimeout = 300;
|
||||
|
||||
void init()
|
||||
|
@ -225,6 +244,13 @@ struct CurlDownloader : public Downloader
|
|||
if (request.head)
|
||||
curl_easy_setopt(req, CURLOPT_NOBODY, 1);
|
||||
|
||||
if (request.data) {
|
||||
curl_easy_setopt(req, CURLOPT_UPLOAD, 1L);
|
||||
curl_easy_setopt(req, CURLOPT_READFUNCTION, readCallbackWrapper);
|
||||
curl_easy_setopt(req, CURLOPT_READDATA, this);
|
||||
curl_easy_setopt(req, CURLOPT_INFILESIZE_LARGE, (curl_off_t) request.data->length());
|
||||
}
|
||||
|
||||
if (request.verifyTLS) {
|
||||
if (settings.caFile != "")
|
||||
curl_easy_setopt(req, CURLOPT_CAINFO, settings.caFile.c_str());
|
||||
|
@ -265,7 +291,7 @@ struct CurlDownloader : public Downloader
|
|||
}
|
||||
|
||||
if (code == CURLE_OK &&
|
||||
(httpStatus == 200 || httpStatus == 304 || httpStatus == 226 /* FTP */ || httpStatus == 0 /* other protocol */))
|
||||
(httpStatus == 200 || httpStatus == 201 || httpStatus == 204 || httpStatus == 304 || httpStatus == 226 /* FTP */ || httpStatus == 0 /* other protocol */))
|
||||
{
|
||||
result.cached = httpStatus == 304;
|
||||
done = true;
|
||||
|
|
|
@ -18,9 +18,11 @@ struct DownloadRequest
|
|||
unsigned int baseRetryTimeMs = 250;
|
||||
ActivityId parentAct;
|
||||
bool decompress = true;
|
||||
std::shared_ptr<std::string> data;
|
||||
std::string mimeType;
|
||||
|
||||
DownloadRequest(const std::string & uri)
|
||||
: uri(uri), parentAct(curActivity) { }
|
||||
DownloadRequest(const std::string & uri, std::shared_ptr<std::string> data = nullptr, std::string mimeType = "")
|
||||
: uri(uri), parentAct(curActivity), data(std::move(data)), mimeType(std::move(mimeType)) { }
|
||||
};
|
||||
|
||||
struct DownloadResult
|
||||
|
|
|
@ -67,7 +67,13 @@ protected:
|
|||
const std::string & data,
|
||||
const std::string & mimeType) override
|
||||
{
|
||||
throw UploadToHTTP("uploading to an HTTP binary cache is not supported");
|
||||
auto data_ = std::make_shared<string>(data);
|
||||
auto req = DownloadRequest(cacheUri + "/" + path, data_, mimeType);
|
||||
try {
|
||||
getDownloader()->download(req);
|
||||
} catch (DownloadError & e) {
|
||||
throw UploadToHTTP(format("uploading to HTTP binary cache at %1% not supported: %2%") % cacheUri % e.msg());
|
||||
}
|
||||
}
|
||||
|
||||
void getFile(const std::string & path,
|
||||
|
|
Loading…
Reference in a new issue