HTTPDownloader: Add owner tracking to requests

Allow finer-grained cancellation.
This commit is contained in:
Stenzek
2026-05-23 16:29:07 +10:00
parent cf62df552b
commit 5b446d702a
11 changed files with 183 additions and 77 deletions
+5 -5
View File
@@ -882,9 +882,9 @@ uint32_t Achievements::ClientReadMemory(uint32_t address, uint8_t* buffer, uint3
void Achievements::ClientServerCall(const rc_api_request_t* request, rc_client_server_callback_t callback,
void* callback_data, rc_client_t* client)
{
HTTPDownloader::Request::Callback hd_callback = [callback, callback_data](s32 status_code, const Error& error,
const std::string& content_type,
HTTPDownloader::Request::Data data) {
HTTPDownloader::Request::Callback hd_callback = [callback, callback_data](s32 status_code, Error& error,
std::string& content_type,
HTTPDownloader::Request::Data& data) {
if (status_code != HTTPDownloader::HTTP_STATUS_OK)
ERROR_LOG("Server call failed: {}", error.GetDescription());
@@ -904,12 +904,12 @@ void Achievements::ClientServerCall(const rc_api_request_t* request, rc_client_s
{
// const auto pd = std::string_view(request->post_data);
// Log_DevFmt("Server POST: {}", pd.substr(0, std::min<size_t>(pd.length(), 10)));
downloader->CreatePostRequest(request->url, request->post_data, std::move(hd_callback), nullptr, headers,
downloader->CreatePostRequest(request->url, request->post_data, &s_state, std::move(hd_callback), nullptr, headers,
SERVER_CALL_TIMEOUT);
}
else
{
downloader->CreateRequest(request->url, std::move(hd_callback), nullptr, headers, SERVER_CALL_TIMEOUT);
downloader->CreateRequest(request->url, &s_state, std::move(hd_callback), nullptr, headers, SERVER_CALL_TIMEOUT);
}
}
+4 -4
View File
@@ -1855,10 +1855,10 @@ bool GameList::DownloadCovers(const std::vector<std::string>& url_templates, boo
std::string filename = Path::URLDecode(url);
if (HTTPDownloader* const downloader = HTTPCache::GetDownloader(error))
{
downloader->CreateRequest(std::move(url), [use_serial, &save_callback, entry_path = std::move(entry_path),
filename = std::move(filename)](s32 status_code, const Error& error,
const std::string& content_type,
HTTPDownloader::Request::Data data) {
downloader->CreateRequest(
std::move(url), &s_state,
[use_serial, &save_callback, entry_path = std::move(entry_path), filename = std::move(filename)](
s32 status_code, Error& error, std::string& content_type, HTTPDownloader::Request::Data& data) {
if (status_code != HTTPDownloader::HTTP_STATUS_OK || data.empty())
{
ERROR_LOG("Download for {} failed: {}", Path::GetFileName(filename), error.GetDescription());
+17 -15
View File
@@ -11,8 +11,8 @@
#include "core/core.h"
#include "util/http_downloader.h"
#include "util/http_cache.h"
#include "util/http_downloader.h"
#include "util/translation.h"
#include "common/assert.h"
@@ -359,22 +359,23 @@ void AutoUpdaterDialog::queueUpdateCheck(bool display_errors, bool ignore_skippe
}
ensureHttpPollingActive();
m_http->CreateRequest(LATEST_TAG_URL,
[this, display_errors](s32 status_code, const Error& error, const std::string& content_type,
std::vector<u8> response) {
getLatestTagComplete(status_code, error, std::move(response), display_errors);
});
m_http->CreateRequest(
LATEST_TAG_URL, this,
[this, display_errors](s32 status_code, Error& error, std::string& content_type, std::vector<u8>& response) {
getLatestTagComplete(status_code, error, response, display_errors);
});
}
void AutoUpdaterDialog::queueGetLatestRelease()
{
ensureHttpPollingActive();
std::string url = fmt::format(LATEST_RELEASE_URL, getCurrentUpdateTag());
m_http->CreateRequest(std::move(url), std::bind(&AutoUpdaterDialog::getLatestReleaseComplete, this,
std::placeholders::_1, std::placeholders::_2, std::placeholders::_4));
m_http->CreateRequest(std::move(url), this,
std::bind(&AutoUpdaterDialog::getLatestReleaseComplete, this, std::placeholders::_1,
std::placeholders::_2, std::placeholders::_4));
}
void AutoUpdaterDialog::getLatestTagComplete(s32 status_code, const Error& error, std::vector<u8> response,
void AutoUpdaterDialog::getLatestTagComplete(s32 status_code, Error& error, std::vector<u8>& response,
bool display_errors)
{
if (handleCancelledRequest(status_code))
@@ -441,7 +442,7 @@ void AutoUpdaterDialog::getLatestTagComplete(s32 status_code, const Error& error
emit updateCheckCompleted(false);
}
void AutoUpdaterDialog::getLatestReleaseComplete(s32 status_code, const Error& error, std::vector<u8> response)
void AutoUpdaterDialog::getLatestReleaseComplete(s32 status_code, Error& error, std::vector<u8>& response)
{
if (handleCancelledRequest(status_code))
return;
@@ -521,11 +522,12 @@ void AutoUpdaterDialog::queueGetChanges()
{
ensureHttpPollingActive();
std::string url = fmt::format(CHANGES_URL, g_scm_hash_str, getCurrentUpdateTag());
m_http->CreateRequest(std::move(url), std::bind(&AutoUpdaterDialog::getChangesComplete, this, std::placeholders::_1,
std::placeholders::_2, std::placeholders::_4));
m_http->CreateRequest(std::move(url), this,
std::bind(&AutoUpdaterDialog::getChangesComplete, this, std::placeholders::_1,
std::placeholders::_2, std::placeholders::_4));
}
void AutoUpdaterDialog::getChangesComplete(s32 status_code, const Error& error, std::vector<u8> response)
void AutoUpdaterDialog::getChangesComplete(s32 status_code, Error& error, std::vector<u8>& response)
{
std::string_view error_message;
@@ -607,8 +609,8 @@ void AutoUpdaterDialog::downloadUpdateClicked()
ensureHttpPollingActive();
m_http->CreateRequest(
m_download_url.toStdString(),
[this](s32 status_code, const Error& error, const std::string&, std::vector<u8> response) {
m_download_url.toStdString(), this,
[this](s32 status_code, Error& error, std::string&, std::vector<u8>& response) {
m_download_progress_callback->SetStatusText(TRANSLATE_SV("AutoUpdaterWindow", "Processing Update..."));
m_download_progress_callback->SetProgressRange(1);
m_download_progress_callback->SetProgressValue(1);
+3 -3
View File
@@ -71,11 +71,11 @@ private:
bool updateNeeded() const;
void getLatestTagComplete(s32 status_code, const Error& error, std::vector<u8> response, bool display_errors);
void getLatestReleaseComplete(s32 status_code, const Error& error, std::vector<u8> response);
void getLatestTagComplete(s32 status_code, Error& error, std::vector<u8>& response, bool display_errors);
void getLatestReleaseComplete(s32 status_code, Error& error, std::vector<u8>& response);
void queueGetChanges();
void getChangesComplete(s32 status_code, const Error& error, std::vector<u8> response);
void getChangesComplete(s32 status_code, Error& error, std::vector<u8>& response);
bool processUpdate(const std::vector<u8>& update_data);
+4 -5
View File
@@ -738,7 +738,7 @@ void QtHost::DownloadFile(QWidget* parent, std::string url, std::string path,
QtAsyncTaskWithProgressDialog::create(
parent, TRANSLATE_SV("QtHost", "File Download"), status_text, false, true, 0, 0, 0.0f, true,
[url = std::move(url), path = std::move(path),
[parent, url = std::move(url), path = std::move(path),
completion_callback = std::move(completion_callback)](ProgressCallback* const progress) mutable {
Error error;
bool result = false;
@@ -746,9 +746,8 @@ void QtHost::DownloadFile(QWidget* parent, std::string url, std::string path,
{
result = true;
downloader->CreateRequest(
std::move(url),
[&result, &error, &path](s32 status_code, const Error& http_error, const std::string&,
std::vector<u8> hdata) {
std::move(url), parent,
[&result, &error, &path](s32 status_code, Error& http_error, std::string&, std::vector<u8>& hdata) {
if (status_code != HTTPDownloader::HTTP_STATUS_OK)
{
error.SetString(http_error.GetDescription());
@@ -766,7 +765,7 @@ void QtHost::DownloadFile(QWidget* parent, std::string url, std::string path,
}
// Block until completion.
HTTPCache::WaitForAllRequests();
HTTPCache::WaitForAllRequestsFromOwner(parent);
QtAsyncTaskWithProgressDialog::CompletionCallback ret;
if (completion_callback)
+29 -5
View File
@@ -135,12 +135,36 @@ void HTTPCache::WaitForAllRequests()
s_locals.downloader->WaitForAllRequests();
}
void HTTPCache::WaitForAllRequestsFromOwner(const void* owner)
{
if (s_locals.downloader)
s_locals.downloader->WaitForAllRequestsFromOwner(owner);
}
void HTTPCache::WaitForAllRequestsWithYield(std::function<void()> before_sleep_cb, std::function<void()> after_sleep_cb)
{
if (s_locals.downloader)
s_locals.downloader->WaitForAllRequestsWithYield(std::move(before_sleep_cb), std::move(after_sleep_cb));
}
void HTTPCache::WaitForAllRequestsFromOwnerWithYield(const void* owner, std::function<void()> before_sleep_cb,
std::function<void()> after_sleep_cb)
{
if (s_locals.downloader)
{
s_locals.downloader->WaitForAllRequestsFromOwnerWithYield(owner, std::move(before_sleep_cb),
std::move(after_sleep_cb));
}
}
void HTTPCache::CancelRequestsForOwner(const void* owner)
{
if (!s_locals.downloader)
return;
s_locals.downloader->CancelRequestsForOwner(owner);
}
HTTPDownloader* HTTPCache::GetDownloader(Error* create_error)
{
if (s_locals.downloader) [[likely]]
@@ -261,11 +285,11 @@ bool HTTPCache::QueueDownload(std::string_view url, FetchCallback callback, Erro
DEV_LOG("Cache miss for URL '{}', downloading...", url);
downloader->CreateRequest(std::string(url), [url = std::string(url)](s32 status_code, const Error& error,
const std::string& content_type,
HTTPDownloader::Request::Data data) {
DownloadCallback(url, status_code, error, content_type, std::move(data));
});
downloader->CreateRequest(std::string(url), &s_locals,
[url = std::string(url)](s32 status_code, Error& error, std::string& content_type,
HTTPDownloader::Request::Data& data) {
DownloadCallback(url, status_code, error, content_type, std::move(data));
});
return true;
}
+10 -4
View File
@@ -53,6 +53,11 @@ std::string GetUserAgent();
/// Shuts down the HTTP cache, releasing the downloader and cache archive.
void Shutdown();
/// Returns a pointer to the shared HTTP downloader, creating it on first use.
/// If @p create_error is non-null, creation details are written there on failure; if null, creation
/// is skipped after the first failed attempt.
HTTPDownloader* GetDownloader(Error* create_error = nullptr);
/// Returns true if idle updates are necessary (e.g. outstanding requests).
bool IsDownloaderActive();
@@ -61,14 +66,15 @@ void PollRequests();
/// Waits for all requests to finish.
void WaitForAllRequests();
void WaitForAllRequestsFromOwner(const void* owner);
/// Waits for all requests to finish, periodically yielding to allow other tasks to run.
void WaitForAllRequestsWithYield(std::function<void()> before_sleep_cb, std::function<void()> after_sleep_cb);
void WaitForAllRequestsFromOwnerWithYield(const void* owner, std::function<void()> before_sleep_cb,
std::function<void()> after_sleep_cb);
/// Returns a locked pointer to the shared HTTP downloader, creating it on first use.
/// If @p create_error is non-null, creation details are written there on failure; if null, creation
/// is skipped after the first failed attempt.
HTTPDownloader* GetDownloader(Error* create_error = nullptr);
/// Cancels all outstanding requests for the specified owner.
void CancelRequestsForOwner(const void* owner);
/// Returns a locked pointer to the shared cache archive, opening it on first use.
CacheArchivePtr GetCacheArchive();
+80 -13
View File
@@ -24,9 +24,10 @@ HTTPDownloader::HTTPDownloader()
HTTPDownloader::~HTTPDownloader() = default;
HTTPDownloader::Request::Request(HTTPDownloader* parent, Type type, std::string url, std::string post_data,
Callback callback, ProgressCallback* progress, u16 timeout_seconds)
: parent(parent), callback(std::move(callback)), progress(progress), url(std::move(url)),
HTTPDownloader::Request::Request(HTTPDownloader* parent, const void* owner, Type type, std::string url,
std::string post_data, Callback callback, ProgressCallback* progress,
u16 timeout_seconds)
: parent(parent), owner(owner), callback(std::move(callback)), progress(progress), url(std::move(url)),
post_data(std::move(post_data)), type(type), timeout_seconds(timeout_seconds)
{
// set progress state to indeterminate until we know the size
@@ -47,23 +48,24 @@ void HTTPDownloader::SetMaxActiveRequests(u32 max_active_requests)
m_max_active_requests = max_active_requests;
}
void HTTPDownloader::CreateRequest(std::string url, Request::Callback callback,
void HTTPDownloader::CreateRequest(std::string url, const void* owner, Request::Callback callback,
ProgressCallback* progress /* = nullptr */, HeaderList additional_headers /* = */,
std::optional<u16> timeout_seconds /* = */)
{
Request* req = InternalCreateRequest(Request::Type::Get, std::move(url), {}, std::move(callback), progress,
Request* req = InternalCreateRequest(Request::Type::Get, std::move(url), {}, owner, std::move(callback), progress,
timeout_seconds.value_or(m_default_timeout), additional_headers);
DebugAssert(req);
StartOrAddRequest(req);
}
void HTTPDownloader::CreatePostRequest(std::string url, std::string post_data, Request::Callback callback,
ProgressCallback* progress /* = nullptr */,
void HTTPDownloader::CreatePostRequest(std::string url, std::string post_data, const void* owner,
Request::Callback callback, ProgressCallback* progress /* = nullptr */,
HeaderList additional_headers /* = */,
std::optional<u16> timeout_seconds /* = */)
{
Request* req = InternalCreateRequest(Request::Type::Post, std::move(url), std::move(post_data), std::move(callback),
progress, timeout_seconds.value_or(m_default_timeout), additional_headers);
Request* req =
InternalCreateRequest(Request::Type::Post, std::move(url), std::move(post_data), owner, std::move(callback),
progress, timeout_seconds.value_or(m_default_timeout), additional_headers);
DebugAssert(req);
StartOrAddRequest(req);
}
@@ -112,7 +114,7 @@ void HTTPDownloader::LockedPollRequests(std::unique_lock<std::mutex>& lock)
lock.unlock();
req->error.SetStringFmt("Request timed out after {} seconds.", req->timeout_seconds);
req->callback(HTTP_STATUS_TIMEOUT, req->error, std::string(), Request::Data());
req->callback(HTTP_STATUS_TIMEOUT, req->error, req->content_type, req->data);
CloseRequest(req);
@@ -130,7 +132,7 @@ void HTTPDownloader::LockedPollRequests(std::unique_lock<std::mutex>& lock)
lock.unlock();
req->error.SetStringView("Request was cancelled.");
req->callback(HTTP_STATUS_CANCELLED, req->error, std::string(), Request::Data());
req->callback(HTTP_STATUS_CANCELLED, req->error, req->content_type, req->data);
CloseRequest(req);
@@ -168,7 +170,7 @@ void HTTPDownloader::LockedPollRequests(std::unique_lock<std::mutex>& lock)
else if (req->status_code < 0)
DEV_LOG("Request failed with error {}", req->error.GetDescription());
req->callback(req->status_code, req->error, req->content_type, std::move(req->data));
req->callback(req->status_code, req->error, req->content_type, req->data);
CloseRequest(req);
lock.lock();
}
@@ -240,6 +242,51 @@ void HTTPDownloader::WaitForAllRequestsWithYield(std::function<void()> before_sl
}
}
void HTTPDownloader::WaitForAllRequestsFromOwner(const void* owner)
{
if (!owner)
{
WaitForAllRequests();
return;
}
std::unique_lock lock(m_pending_http_request_lock);
while (std::ranges::any_of(m_pending_http_requests, [owner](const Request* req) { return req->owner == owner; }))
{
// Don't burn too much CPU.
Timer::NanoSleep(WAIT_FOR_ALL_REQUESTS_POLL_INTERVAL_NS);
LockedPollRequests(lock);
}
}
void HTTPDownloader::WaitForAllRequestsFromOwnerWithYield(const void* owner, std::function<void()> before_sleep_cb,
std::function<void()> after_sleep_cb)
{
if (!owner)
{
WaitForAllRequestsWithYield(std::move(before_sleep_cb), std::move(after_sleep_cb));
return;
}
std::unique_lock lock(m_pending_http_request_lock);
while (std::ranges::any_of(m_pending_http_requests, [owner](const Request* req) { return req->owner == owner; }))
{
// Don't burn too much CPU.
if (before_sleep_cb)
{
lock.unlock();
before_sleep_cb();
}
Timer::NanoSleep(WAIT_FOR_ALL_REQUESTS_POLL_INTERVAL_NS);
if (after_sleep_cb)
{
after_sleep_cb();
lock.lock();
}
LockedPollRequests(lock);
}
}
void HTTPDownloader::LockedAddRequest(Request* request)
{
m_pending_http_requests.push_back(request);
@@ -263,7 +310,21 @@ bool HTTPDownloader::HasAnyRequests()
return !m_pending_http_requests.empty();
}
bool HTTPDownloader::HasAnyRequestsFromOwner(const void* owner)
{
if (!owner)
return HasAnyRequests();
std::unique_lock lock(m_pending_http_request_lock);
return std::ranges::any_of(m_pending_http_requests, [owner](const Request* req) { return req->owner == owner; });
}
void HTTPDownloader::CancelAllRequests()
{
CancelRequestsForOwner(nullptr);
}
void HTTPDownloader::CancelRequestsForOwner(const void* owner)
{
std::unique_lock lock(m_pending_http_request_lock);
@@ -277,6 +338,12 @@ void HTTPDownloader::CancelAllRequests()
for (size_t index = 0; index < m_pending_http_requests.size();)
{
Request* req = m_pending_http_requests[index];
if (owner && req->owner != owner)
{
index++;
continue;
}
const Request::State req_state = req->state.load(std::memory_order_acquire);
// can't cancel a request in pending stage
@@ -296,7 +363,7 @@ void HTTPDownloader::CancelAllRequests()
lock.unlock();
req->error.SetStringView("Request was cancelled.");
req->callback(HTTP_STATUS_CANCELLED, req->error, std::string(), Request::Data());
req->callback(HTTP_STATUS_CANCELLED, req->error, req->content_type, req->data);
CloseRequest(req);
+14 -8
View File
@@ -36,8 +36,7 @@ public:
struct Request
{
using Data = std::vector<u8>;
using Callback =
std::function<void(s32 status_code, const Error& error, const std::string& content_type, Data data)>;
using Callback = std::function<void(s32 status_code, Error& error, std::string& content_type, Data& data)>;
enum class Type : u8
{
@@ -54,11 +53,12 @@ public:
Complete,
};
Request(HTTPDownloader* parent, Type type, std::string url, std::string post_data, Callback callback,
ProgressCallback* progress, u16 timeout_seconds);
Request(HTTPDownloader* parent, const void* owner, Type type, std::string url, std::string post_data,
Callback callback, ProgressCallback* progress, u16 timeout_seconds);
virtual ~Request();
HTTPDownloader* parent;
const void* owner;
Callback callback;
ProgressCallback* progress;
std::string url;
@@ -85,19 +85,25 @@ public:
void SetDefaultTimeout(u16 timeout_seconds);
void SetMaxActiveRequests(u32 max_active_requests);
void CreateRequest(std::string url, Request::Callback callback, ProgressCallback* progress = nullptr,
HeaderList additional_headers = {}, std::optional<u16> timeout_seconds = {});
void CreatePostRequest(std::string url, std::string post_data, Request::Callback callback,
void CreateRequest(std::string url, const void* owner, Request::Callback callback,
ProgressCallback* progress = nullptr, HeaderList additional_headers = {},
std::optional<u16> timeout_seconds = {});
void CreatePostRequest(std::string url, std::string post_data, const void* owner, Request::Callback callback,
ProgressCallback* progress = nullptr, HeaderList additional_headers = {},
std::optional<u16> timeout_seconds = {});
bool PollRequests();
void WaitForAllRequests();
void WaitForAllRequestsWithYield(std::function<void()> before_sleep_cb, std::function<void()> after_sleep_cb);
void WaitForAllRequestsFromOwner(const void* owner);
void WaitForAllRequestsFromOwnerWithYield(const void* owner, std::function<void()> before_sleep_cb,
std::function<void()> after_sleep_cb);
bool HasAnyRequests();
bool HasAnyRequestsFromOwner(const void* owner);
void CancelAllRequests();
void CancelRequestsForOwner(const void* owner);
protected:
virtual Request* InternalCreateRequest(Request::Type type, std::string url, std::string post_data,
virtual Request* InternalCreateRequest(Request::Type type, std::string url, std::string post_data, const void* owner,
Request::Callback callback, ProgressCallback* progress, u16 timeout_seconds,
HeaderList additional_headers) = 0;
+7 -6
View File
@@ -30,8 +30,8 @@ public:
bool Initialize(std::string user_agent, Error* error);
protected:
Request* InternalCreateRequest(Request::Type type, std::string url, std::string post_data, Request::Callback callback,
ProgressCallback* progress, u16 timeout_seconds,
Request* InternalCreateRequest(Request::Type type, std::string url, std::string post_data, const void* owner,
Request::Callback callback, ProgressCallback* progress, u16 timeout_seconds,
HeaderList additional_headers) override;
bool StartRequest(HTTPDownloader::Request* request) override;
void CloseRequest(HTTPDownloader::Request* request) override;
@@ -171,12 +171,13 @@ HTTPDownloaderCurl::Request::~Request()
}
HTTPDownloader::Request* HTTPDownloaderCurl::InternalCreateRequest(Request::Type type, std::string url,
std::string post_data, Request::Callback callback,
std::string post_data, const void* owner,
Request::Callback callback,
ProgressCallback* progress, u16 timeout_seconds,
HeaderList additional_headers)
{
Request* req =
new Request(this, type, std::move(url), std::move(post_data), std::move(callback), progress, timeout_seconds);
Request* req = new Request(this, owner, type, std::move(url), std::move(post_data), std::move(callback), progress,
timeout_seconds);
for (const char* header : additional_headers)
req->header_list = curl_slist_append(req->header_list, header);
@@ -303,7 +304,7 @@ bool HTTPDownloaderCurl::StartRequest(HTTPDownloader::Request* request)
{
ERROR_LOG("curl_easy_init() failed");
req->error.SetStringView("curl_easy_init() failed");
req->callback(HTTP_STATUS_ERROR, req->error, std::string(), req->data);
req->callback(HTTP_STATUS_ERROR, req->error, req->content_type, req->data);
delete req;
return false;
}
+10 -9
View File
@@ -24,8 +24,8 @@ public:
bool Initialize(std::string user_agent, Error* error);
protected:
Request* InternalCreateRequest(Request::Type type, std::string url, std::string post_data, Request::Callback callback,
ProgressCallback* progress, u16 timeout_seconds,
Request* InternalCreateRequest(Request::Type type, std::string url, std::string post_data, const void* owner,
Request::Callback callback, ProgressCallback* progress, u16 timeout_seconds,
HeaderList additional_headers) override;
bool StartRequest(HTTPDownloader::Request* request) override;
void CloseRequest(HTTPDownloader::Request* request) override;
@@ -261,12 +261,13 @@ void CALLBACK HTTPDownloaderWinHttp::HTTPStatusCallback(HINTERNET hRequest, DWOR
}
HTTPDownloader::Request* HTTPDownloaderWinHttp::InternalCreateRequest(Request::Type type, std::string url,
std::string post_data, Request::Callback callback,
std::string post_data, const void* owner,
Request::Callback callback,
ProgressCallback* progress, u16 timeout_seconds,
HeaderList additional_headers)
{
Request* req =
new Request(this, type, std::move(url), std::move(post_data), std::move(callback), progress, timeout_seconds);
Request* req = new Request(this, owner, type, std::move(url), std::move(post_data), std::move(callback), progress,
timeout_seconds);
if (!additional_headers.empty())
{
@@ -307,7 +308,7 @@ bool HTTPDownloaderWinHttp::StartRequest(HTTPDownloader::Request* request)
const DWORD err = GetLastError();
ERROR_LOG("WinHttpCrackUrl() failed: {}", err);
req->error.SetWin32("WinHttpCrackUrl() failed: ", err);
req->callback(HTTP_STATUS_ERROR, req->error, std::string(), req->data);
req->callback(HTTP_STATUS_ERROR, req->error, req->content_type, req->data);
delete req;
return false;
}
@@ -321,7 +322,7 @@ bool HTTPDownloaderWinHttp::StartRequest(HTTPDownloader::Request* request)
const DWORD err = GetLastError();
ERROR_LOG("Failed to start HTTP request for '{}': {}", req->url, err);
req->error.SetWin32("WinHttpConnect() failed: ", err);
req->callback(HTTP_STATUS_ERROR, req->error, std::string(), req->data);
req->callback(HTTP_STATUS_ERROR, req->error, req->content_type, req->data);
delete req;
return false;
}
@@ -335,7 +336,7 @@ bool HTTPDownloaderWinHttp::StartRequest(HTTPDownloader::Request* request)
const DWORD err = GetLastError();
ERROR_LOG("WinHttpOpenRequest() failed: {}", err);
req->error.SetWin32("WinHttpOpenRequest() failed: ", err);
req->callback(HTTP_STATUS_ERROR, req->error, std::string(), req->data);
req->callback(HTTP_STATUS_ERROR, req->error, req->content_type, req->data);
WinHttpCloseHandle(req->hConnection);
delete req;
return false;
@@ -349,7 +350,7 @@ bool HTTPDownloaderWinHttp::StartRequest(HTTPDownloader::Request* request)
const DWORD err = GetLastError();
ERROR_LOG("WinHttpAddRequestHeaders() failed: {}", err);
req->error.SetWin32("WinHttpAddRequestHeaders() failed: ", err);
req->callback(HTTP_STATUS_ERROR, req->error, std::string(), req->data);
req->callback(HTTP_STATUS_ERROR, req->error, req->content_type, req->data);
WinHttpCloseHandle(req->hRequest);
WinHttpCloseHandle(req->hConnection);
delete req;