forked from lix-project/lix
libstore: remove FiletransferRequest::head
add a method to FileTransfer that provides this functionality instead.
Change-Id: Ic1933a5df76a109c248c9c5efea065356b20a6f9
This commit is contained in:
parent
9f682204b5
commit
220251ba51
|
@ -48,6 +48,7 @@ struct curlFileTransfer : public FileTransfer
|
||||||
FileTransferResult result;
|
FileTransferResult result;
|
||||||
Activity act;
|
Activity act;
|
||||||
std::optional<std::string> uploadData;
|
std::optional<std::string> uploadData;
|
||||||
|
bool noBody = false; // \equiv HTTP HEAD, don't download data
|
||||||
bool done = false; // whether either the success or failure function has been called
|
bool done = false; // whether either the success or failure function has been called
|
||||||
std::packaged_task<FileTransferResult(std::exception_ptr, FileTransferResult)> callback;
|
std::packaged_task<FileTransferResult(std::exception_ptr, FileTransferResult)> callback;
|
||||||
std::function<void(TransferItem &, std::string_view data)> dataCallback;
|
std::function<void(TransferItem &, std::string_view data)> dataCallback;
|
||||||
|
@ -92,7 +93,8 @@ struct curlFileTransfer : public FileTransfer
|
||||||
ActivityId parentAct,
|
ActivityId parentAct,
|
||||||
std::invocable<std::exception_ptr> auto callback,
|
std::invocable<std::exception_ptr> auto callback,
|
||||||
std::function<void(TransferItem &, std::string_view data)> dataCallback,
|
std::function<void(TransferItem &, std::string_view data)> dataCallback,
|
||||||
std::optional<std::string> uploadData
|
std::optional<std::string> uploadData,
|
||||||
|
bool noBody
|
||||||
)
|
)
|
||||||
: fileTransfer(fileTransfer)
|
: fileTransfer(fileTransfer)
|
||||||
, request(request)
|
, request(request)
|
||||||
|
@ -100,6 +102,7 @@ struct curlFileTransfer : public FileTransfer
|
||||||
fmt(uploadData ? "uploading '%s'" : "downloading '%s'", request.uri),
|
fmt(uploadData ? "uploading '%s'" : "downloading '%s'", request.uri),
|
||||||
{request.uri}, parentAct)
|
{request.uri}, parentAct)
|
||||||
, uploadData(std::move(uploadData))
|
, uploadData(std::move(uploadData))
|
||||||
|
, noBody(noBody)
|
||||||
, callback([cb{std::move(callback)}] (std::exception_ptr ex, FileTransferResult r) {
|
, callback([cb{std::move(callback)}] (std::exception_ptr ex, FileTransferResult r) {
|
||||||
cb(ex);
|
cb(ex);
|
||||||
return r;
|
return r;
|
||||||
|
@ -299,7 +302,7 @@ struct curlFileTransfer : public FileTransfer
|
||||||
if (settings.downloadSpeed.get() > 0)
|
if (settings.downloadSpeed.get() > 0)
|
||||||
curl_easy_setopt(req, CURLOPT_MAX_RECV_SPEED_LARGE, (curl_off_t) (settings.downloadSpeed.get() * 1024));
|
curl_easy_setopt(req, CURLOPT_MAX_RECV_SPEED_LARGE, (curl_off_t) (settings.downloadSpeed.get() * 1024));
|
||||||
|
|
||||||
if (request.head)
|
if (noBody)
|
||||||
curl_easy_setopt(req, CURLOPT_NOBODY, 1);
|
curl_easy_setopt(req, CURLOPT_NOBODY, 1);
|
||||||
|
|
||||||
if (uploadData) {
|
if (uploadData) {
|
||||||
|
@ -661,17 +664,18 @@ struct curlFileTransfer : public FileTransfer
|
||||||
|
|
||||||
std::future<FileTransferResult> enqueueDownload(const FileTransferRequest & request) override
|
std::future<FileTransferResult> enqueueDownload(const FileTransferRequest & request) override
|
||||||
{
|
{
|
||||||
return enqueueFileTransfer(request, std::nullopt);
|
return enqueueFileTransfer(request, std::nullopt, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::future<FileTransferResult>
|
std::future<FileTransferResult>
|
||||||
enqueueUpload(const FileTransferRequest & request, std::string data) override
|
enqueueUpload(const FileTransferRequest & request, std::string data) override
|
||||||
{
|
{
|
||||||
return enqueueFileTransfer(request, std::move(data));
|
return enqueueFileTransfer(request, std::move(data), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::future<FileTransferResult>
|
std::future<FileTransferResult> enqueueFileTransfer(
|
||||||
enqueueFileTransfer(const FileTransferRequest & request, std::optional<std::string> data)
|
const FileTransferRequest & request, std::optional<std::string> data, bool noBody
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return enqueueFileTransfer(
|
return enqueueFileTransfer(
|
||||||
request,
|
request,
|
||||||
|
@ -681,14 +685,16 @@ struct curlFileTransfer : public FileTransfer
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{},
|
{},
|
||||||
std::move(data)
|
std::move(data),
|
||||||
|
noBody
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::future<FileTransferResult> enqueueFileTransfer(const FileTransferRequest & request,
|
std::future<FileTransferResult> enqueueFileTransfer(const FileTransferRequest & request,
|
||||||
std::invocable<std::exception_ptr> auto callback,
|
std::invocable<std::exception_ptr> auto callback,
|
||||||
std::function<void(TransferItem &, std::string_view data)> dataCallback,
|
std::function<void(TransferItem &, std::string_view data)> dataCallback,
|
||||||
std::optional<std::string> data
|
std::optional<std::string> data,
|
||||||
|
bool noBody
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
/* Ugly hack to support s3:// URIs. */
|
/* Ugly hack to support s3:// URIs. */
|
||||||
|
@ -724,11 +730,26 @@ struct curlFileTransfer : public FileTransfer
|
||||||
getCurActivity(),
|
getCurActivity(),
|
||||||
std::move(callback),
|
std::move(callback),
|
||||||
std::move(dataCallback),
|
std::move(dataCallback),
|
||||||
std::move(data)
|
std::move(data),
|
||||||
|
noBody
|
||||||
))
|
))
|
||||||
->callback.get_future();
|
->callback.get_future();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool exists(std::string_view uri) override
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
enqueueFileTransfer(FileTransferRequest{uri}, std::nullopt, true).get();
|
||||||
|
return true;
|
||||||
|
} catch (FileTransferError & e) {
|
||||||
|
/* S3 buckets return 403 if a file doesn't exist and the
|
||||||
|
bucket is unlistable, so treat 403 as 404. */
|
||||||
|
if (e.error == FileTransfer::NotFound || e.error == FileTransfer::Forbidden)
|
||||||
|
return false;
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
box_ptr<Source> download(FileTransferRequest && request) override
|
box_ptr<Source> download(FileTransferRequest && request) override
|
||||||
{
|
{
|
||||||
struct State {
|
struct State {
|
||||||
|
@ -776,7 +797,8 @@ struct curlFileTransfer : public FileTransfer
|
||||||
state->data.append(data);
|
state->data.append(data);
|
||||||
state->avail.notify_one();
|
state->avail.notify_one();
|
||||||
},
|
},
|
||||||
std::nullopt
|
std::nullopt,
|
||||||
|
false
|
||||||
);
|
);
|
||||||
|
|
||||||
struct InnerSource : Source
|
struct InnerSource : Source
|
||||||
|
|
|
@ -58,7 +58,6 @@ struct FileTransferRequest
|
||||||
Headers headers;
|
Headers headers;
|
||||||
std::string expectedETag;
|
std::string expectedETag;
|
||||||
bool verifyTLS = true;
|
bool verifyTLS = true;
|
||||||
bool head = false;
|
|
||||||
|
|
||||||
FileTransferRequest(std::string_view uri)
|
FileTransferRequest(std::string_view uri)
|
||||||
: uri(uri) { }
|
: uri(uri) { }
|
||||||
|
@ -96,6 +95,18 @@ struct FileTransfer
|
||||||
virtual std::future<FileTransferResult>
|
virtual std::future<FileTransferResult>
|
||||||
enqueueUpload(const FileTransferRequest & request, std::string data) = 0;
|
enqueueUpload(const FileTransferRequest & request, std::string data) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether the given URI exists. For historical reasons this function
|
||||||
|
* treats HTTP 403 responses like HTTP 404 responses and returns `false` for
|
||||||
|
* both. This was originally done to handle unlistable S3 buckets, which may
|
||||||
|
* return 403 (not 404) if the reuqested object doesn't exist in the bucket.
|
||||||
|
*
|
||||||
|
* ## Bugs
|
||||||
|
*
|
||||||
|
* S3 objects are downloaded completely to answer this request.
|
||||||
|
*/
|
||||||
|
virtual bool exists(std::string_view uri) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Download a file, returning its contents through a source. Will not return
|
* Download a file, returning its contents through a source. Will not return
|
||||||
* before the transfer has fully started, ensuring that any errors thrown by
|
* before the transfer has fully started, ensuring that any errors thrown by
|
||||||
|
|
|
@ -114,15 +114,8 @@ protected:
|
||||||
checkEnabled();
|
checkEnabled();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
FileTransferRequest request{makeURI(path)};
|
return getFileTransfer()->exists(makeURI(path));
|
||||||
request.head = true;
|
|
||||||
getFileTransfer()->enqueueDownload(request).get();
|
|
||||||
return true;
|
|
||||||
} catch (FileTransferError & e) {
|
} catch (FileTransferError & e) {
|
||||||
/* S3 buckets return 403 if a file doesn't exist and the
|
|
||||||
bucket is unlistable, so treat 403 as 404. */
|
|
||||||
if (e.error == FileTransfer::NotFound || e.error == FileTransfer::Forbidden)
|
|
||||||
return false;
|
|
||||||
maybeDisable();
|
maybeDisable();
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue