http: Always use/require progress in requests.

This fixes several cases where we weren't passing cancel flags
consistently.
This commit is contained in:
Unknown W. Brackets
2021-05-01 11:20:05 -07:00
parent f762fbc53d
commit 3379f33882
9 changed files with 69 additions and 59 deletions
+28 -33
View File
@@ -243,35 +243,35 @@ void DeChunk(Buffer *inbuffer, Buffer *outbuffer, int contentLength, float *prog
}
}
int Client::GET(const char *resource, Buffer *output, std::vector<std::string> &responseHeaders, float *progress, bool *cancelled) {
int Client::GET(const char *resource, Buffer *output, std::vector<std::string> &responseHeaders, RequestProgress *progress) {
const char *otherHeaders =
"Accept: */*\r\n"
"Accept-Encoding: gzip\r\n";
int err = SendRequest("GET", resource, otherHeaders, progress, cancelled);
int err = SendRequest("GET", resource, otherHeaders, progress);
if (err < 0) {
return err;
}
net::Buffer readbuf;
int code = ReadResponseHeaders(&readbuf, responseHeaders, progress, cancelled);
int code = ReadResponseHeaders(&readbuf, responseHeaders, progress);
if (code < 0) {
return code;
}
err = ReadResponseEntity(&readbuf, responseHeaders, output, progress, cancelled);
err = ReadResponseEntity(&readbuf, responseHeaders, output, progress);
if (err < 0) {
return err;
}
return code;
}
int Client::GET(const char *resource, Buffer *output, float *progress, bool *cancelled) {
int Client::GET(const char *resource, Buffer *output, RequestProgress *progress) {
std::vector<std::string> responseHeaders;
int code = GET(resource, output, responseHeaders, progress, cancelled);
int code = GET(resource, output, responseHeaders, progress);
return code;
}
int Client::POST(const char *resource, const std::string &data, const std::string &mime, Buffer *output, float *progress) {
int Client::POST(const char *resource, const std::string &data, const std::string &mime, Buffer *output, RequestProgress *progress) {
char otherHeaders[2048];
if (mime.empty()) {
snprintf(otherHeaders, sizeof(otherHeaders), "Content-Length: %lld\r\n", (long long)data.size());
@@ -297,18 +297,16 @@ int Client::POST(const char *resource, const std::string &data, const std::strin
return code;
}
int Client::POST(const char *resource, const std::string &data, Buffer *output, float *progress) {
int Client::POST(const char *resource, const std::string &data, Buffer *output, RequestProgress *progress) {
return POST(resource, data, "", output, progress);
}
int Client::SendRequest(const char *method, const char *resource, const char *otherHeaders, float *progress, bool *cancelled) {
return SendRequestWithData(method, resource, "", otherHeaders, progress, cancelled);
int Client::SendRequest(const char *method, const char *resource, const char *otherHeaders, RequestProgress *progress) {
return SendRequestWithData(method, resource, "", otherHeaders, progress);
}
int Client::SendRequestWithData(const char *method, const char *resource, const std::string &data, const char *otherHeaders, float *progress, bool *cancelled) {
if (progress) {
*progress = 0.01f;
}
int Client::SendRequestWithData(const char *method, const char *resource, const std::string &data, const char *otherHeaders, RequestProgress *progress) {
progress->progress = 0.01f;
net::Buffer buffer;
const char *tpl =
@@ -325,20 +323,20 @@ int Client::SendRequestWithData(const char *method, const char *resource, const
userAgent_.c_str(),
otherHeaders ? otherHeaders : "");
buffer.Append(data);
bool flushed = buffer.FlushSocket(sock(), dataTimeout_);
bool flushed = buffer.FlushSocket(sock(), dataTimeout_, progress->cancelled);
if (!flushed) {
return -1; // TODO error code.
}
return 0;
}
int Client::ReadResponseHeaders(net::Buffer *readbuf, std::vector<std::string> &responseHeaders, float *progress, bool *cancelled) {
int Client::ReadResponseHeaders(net::Buffer *readbuf, std::vector<std::string> &responseHeaders, RequestProgress *progress) {
// Snarf all the data we can into RAM. A little unsafe but hey.
static constexpr float CANCEL_INTERVAL = 0.25f;
bool ready = false;
double endTimeout = time_now_d() + dataTimeout_;
while (!ready) {
if (cancelled && *cancelled)
if (progress->cancelled && *progress->cancelled)
return -1;
ready = fd_util::WaitUntilReady(sock(), CANCEL_INTERVAL, false);
if (!ready && time_now_d() > endTimeout) {
@@ -385,7 +383,7 @@ int Client::ReadResponseHeaders(net::Buffer *readbuf, std::vector<std::string> &
return code;
}
int Client::ReadResponseEntity(net::Buffer *readbuf, const std::vector<std::string> &responseHeaders, Buffer *output, float *progress, bool *cancelled) {
int Client::ReadResponseEntity(net::Buffer *readbuf, const std::vector<std::string> &responseHeaders, Buffer *output, RequestProgress *progress) {
bool gzip = false;
bool chunked = false;
int contentLength = 0;
@@ -417,25 +415,25 @@ int Client::ReadResponseEntity(net::Buffer *readbuf, const std::vector<std::stri
contentLength = 0;
}
if (!contentLength && progress) {
if (!contentLength) {
// Content length is unknown.
// Set progress to 1% so it looks like something is happening...
*progress = 0.1f;
progress->progress = 0.1f;
}
if (!contentLength || !progress) {
if (!contentLength) {
// No way to know how far along we are. Let's just not update the progress counter.
if (!readbuf->ReadAllWithProgress(sock(), contentLength, nullptr, cancelled))
if (!readbuf->ReadAllWithProgress(sock(), contentLength, nullptr, progress->cancelled))
return -1;
} else {
// Let's read in chunks, updating progress between each.
if (!readbuf->ReadAllWithProgress(sock(), contentLength, progress, cancelled))
if (!readbuf->ReadAllWithProgress(sock(), contentLength, &progress->progress, progress->cancelled))
return -1;
}
// output now contains the rest of the reply. Dechunk it.
if (chunked) {
DeChunk(readbuf, output, contentLength, progress);
DeChunk(readbuf, output, contentLength, &progress->progress);
} else {
output->Append(*readbuf);
}
@@ -447,21 +445,18 @@ int Client::ReadResponseEntity(net::Buffer *readbuf, const std::vector<std::stri
bool result = decompress_string(compressed, &decompressed);
if (!result) {
ERROR_LOG(IO, "Error decompressing using zlib");
if (progress)
*progress = 0.0f;
progress->progress = 0.0f;
return -1;
}
output->Append(decompressed);
}
if (progress) {
*progress = 1.0f;
}
progress->progress = 1.0f;
return 0;
}
Download::Download(const std::string &url, const std::string &outfile)
: url_(url), outfile_(outfile) {
: progress_(&cancelled_), url_(url), outfile_(outfile) {
}
Download::~Download() {
@@ -482,7 +477,7 @@ void Download::Join() {
void Download::SetFailed(int code) {
failed_ = true;
progress_ = 1.0f;
progress_.progress = 1.0f;
completed_ = true;
}
@@ -511,7 +506,7 @@ int Download::PerformGET(const std::string &url) {
return -1;
}
return client.GET(fileUrl.Resource().c_str(), &buffer_, responseHeaders_, &progress_, &cancelled_);
return client.GET(fileUrl.Resource().c_str(), &buffer_, responseHeaders_, &progress_);
}
std::string Download::RedirectLocation(const std::string &baseUrl) {
@@ -565,7 +560,7 @@ void Download::Do() {
resultCode_ = resultCode;
}
progress_ = 1.0f;
progress_.progress = 1.0f;
// Set this last to ensure no race conditions when checking Done. Users must always check
// Done before looking at the result code.