refactor: use Net tasks for github api download

Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
This commit is contained in:
Rachel Powers 2023-06-02 15:15:25 -07:00
parent 5d03919b59
commit 98174b7a37
No known key found for this signature in database
GPG Key ID: E10E321EB160949B
5 changed files with 90 additions and 56 deletions

View File

@ -584,6 +584,7 @@ set(PRISMUPDATER_SOURCES
updater/prismupdater/UpdaterDialogs.h
updater/prismupdater/UpdaterDialogs.cpp
updater/prismupdater/GitHubRelease.h
Json.h
Json.cpp
FileSystem.h
@ -595,6 +596,31 @@ set(PRISMUPDATER_SOURCES
Version.h
Version.cpp
Markdown.h
# Time
MMCTime.h
MMCTime.cpp
net/ByteArraySink.h
net/ChecksumValidator.h
net/Download.cpp
net/Download.h
net/FileSink.cpp
net/FileSink.h
net/HttpMetaCache.cpp
net/HttpMetaCache.h
net/Logging.h
net/Logging.cpp
net/NetAction.h
net/NetJob.cpp
net/NetJob.h
net/NetUtils.h
net/Sink.h
net/Validator.h
net/HeaderProxy.h
net/RawHeaderProxy.h
)
######## Logging categories ########
@ -1125,6 +1151,7 @@ endif()
add_library(Launcher_logic STATIC ${LOGIC_SOURCES} ${LAUNCHER_SOURCES} ${LAUNCHER_UI} ${LAUNCHER_RESOURCES})
target_compile_definitions(Launcher_logic PUBLIC LAUNCHER_APPLICATION)
target_include_directories(Launcher_logic PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
target_compile_definitions(Launcher_logic PUBLIC LAUNCHER_APPLICATION)
target_link_libraries(Launcher_logic
systeminfo
Launcher_murmur2
@ -1202,7 +1229,7 @@ install(TARGETS ${Launcher_Name}
if(WIN32 OR (DEFINED Launcher_BUILD_UPDATER AND Launcher_BUILD_UPDATER) )
# Updater
add_library(prism_updater_logic STATIC ${PRISMUPDATER_SOURCES} ${PRISMUPDATER_UI})
add_library(prism_updater_logic STATIC ${PRISMUPDATER_SOURCES} ${TASKS_SOURCES} ${PRISMUPDATER_UI})
target_include_directories(prism_updater_logic PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
target_link_libraries(prism_updater_logic
systeminfo
@ -1213,6 +1240,7 @@ if(WIN32 OR (DEFINED Launcher_BUILD_UPDATER AND Launcher_BUILD_UPDATER) )
Qt${QT_VERSION_MAJOR}::Network
${Launcher_QT_LIBS}
cmark::cmark
Katabasis
)
add_executable("${Launcher_Name}_updater" WIN32 updater/prismupdater/updater_main.cpp)

View File

@ -131,13 +131,12 @@ void Download::executeTask()
return;
}
#if defined (LAUNCHER_APPLICATION)
auto user_agent = APPLICATION->getUserAgent();
#if defined(LAUNCHER_APPLICATION)
auto user_agent = APPLICATION->getUserAgent().toUtf8();
#else
auto user_agent = BuildConfig.USER_AGENT;
auto user_agent = BuildConfig.USER_AGENT.toUtf8();
#endif
request.setHeader(QNetworkRequest::UserAgentHeader, user_agent.toUtf8());
request.setHeader(QNetworkRequest::UserAgentHeader, user_agent);
for ( auto& header_proxy : m_headerProxies ) {
header_proxy->writeHeaders(request);

View File

@ -59,6 +59,7 @@ class Download : public NetAction {
public:
~Download() override = default;
#if defined(LAUNCHER_APPLICATION)
static auto makeCached(QUrl url, MetaEntryPtr entry, Options options = Option::NoOptions) -> Download::Ptr;
static auto makeByteArray(QUrl url, std::shared_ptr<QByteArray> output, Options options = Option::NoOptions) -> Download::Ptr;
static auto makeFile(QUrl url, QString path, Options options = Option::NoOptions) -> Download::Ptr;

View File

@ -34,7 +34,9 @@
#include <QMessageBox>
#include <QNetworkRequest>
#include <QNetworkProxy>
#include <QProcess>
#include <memory>
#include <qglobal.h>
#include <sys.h>
@ -74,6 +76,9 @@ namespace fs = ghc::filesystem;
#include "Json.h"
#include "StringUtils.h"
#include "net/Download.h"
#include "net/RawHeaderProxy.h"
/** output to the log file */
void appDebugOutput(QtMsgType type, const QMessageLogContext& context, const QString& msg)
{
@ -205,8 +210,7 @@ PrismUpdaterApp::PrismUpdaterApp(int& argc, char** argv) : QApplication(argc, ar
}
#endif
}
m_network = new QNetworkAccessManager();
{ // setup logging
static const QString logBase = BuildConfig.LAUNCHER_NAME + "Updater" + (m_checkOnly ? "-CheckOnly" : "") + "-%0.log";
auto moveFile = [](const QString& oldName, const QString& newName) {
@ -292,6 +296,8 @@ PrismUpdaterApp::PrismUpdaterApp(int& argc, char** argv) : QApplication(argc, ar
qDebug() << "<> Log initialized.";
}
{ // log debug program info
qDebug() << qPrintable(BuildConfig.LAUNCHER_DISPLAYNAME) << "Updater"
<< ", (c) 2022-2023 " << qPrintable(QString(BuildConfig.LAUNCHER_COPYRIGHT).replace("\n", ", "));
@ -310,7 +316,14 @@ PrismUpdaterApp::PrismUpdaterApp(int& argc, char** argv) : QApplication(argc, ar
qDebug() << "<> Paths set.";
}
loadReleaseList();
{ // network
m_network = makeShared<QNetworkAccessManager>(new QNetworkAccessManager());
qDebug() << "Detecting proxy settings...";
QNetworkProxy proxy = QNetworkProxy::applicationProxy();
m_network->setProxy(proxy);
}
QMetaObject::invokeMethod(this, &PrismUpdaterApp::loadReleaseList, Qt::QueuedConnection);
}
PrismUpdaterApp::~PrismUpdaterApp()
@ -329,9 +342,6 @@ PrismUpdaterApp::~PrismUpdaterApp()
}
#endif
m_network->deleteLater();
if (m_reply)
m_reply->deleteLater();
}
void PrismUpdaterApp::fail(const QString& reason)
@ -460,7 +470,7 @@ GitHubRelease PrismUpdaterApp::selectRelease()
} else {
releases = newerReleases();
}
if (releases.isEmpty())
return {};
@ -530,34 +540,40 @@ void PrismUpdaterApp::downloadReleasePage(const QString& api_url, int page)
{
int per_page = 30;
auto page_url = QString("%1?per_page=%2&page=%3").arg(api_url).arg(QString::number(per_page)).arg(QString::number(page));
QNetworkRequest request(page_url);
request.setRawHeader("Accept", "application/vnd.github+json");
request.setRawHeader("X-GitHub-Api-Version", "2022-11-28");
auto responce = std::make_shared<QByteArray>();
auto download = Net::Download::makeByteArray(page_url, responce.get());
download->setNetwork(m_network);
m_current_url = page_url;
QNetworkReply* rep = m_network->get(request);
m_reply = rep;
auto responce = new QByteArray();
connect(rep, &QNetworkReply::finished, this, [this, responce, per_page, api_url, page]() {
int num_found = parseReleasePage(responce);
delete responce;
auto githup_api_headers = new Net::RawHeaderProxy();
githup_api_headers->addHeaders({
{ "Accept", "application/vnd.github+json" },
{ "X-GitHub-Api-Version", "2022-11-28" },
});
download->addHeaderProxy(githup_api_headers);
connect(download.get(), &Net::Download::succeeded, this, [this, responce, per_page, api_url, page]() {
int num_found = parseReleasePage(responce.get());
if (!(num_found < per_page)) { // there may be more, fetch next page
downloadReleasePage(api_url, page + 1);
} else {
run();
}
});
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) // QNetworkReply::errorOccurred added in 5.15
connect(rep, &QNetworkReply::errorOccurred, this, &PrismUpdaterApp::downloadError);
#else
connect(rep, QOverload<QNetworkReply::NetworkError>::of(&QNetworkReply::error), this, &WindowsUpdaterApp::downloadError);
#endif
connect(rep, &QNetworkReply::sslErrors, this, &PrismUpdaterApp::sslErrors);
connect(rep, &QNetworkReply::readyRead, this, [this, responce]() {
auto data = m_reply->readAll();
responce->append(data);
connect(download.get(), &Net::Download::failed, this, &PrismUpdaterApp::downloadError);
m_current_task.reset(download);
connect(download.get(), &Net::Download::finished, this, [this](){
qDebug() << "Download" << m_current_task->getUid().toString() << "finsihed";
m_current_task.reset();
m_current_url = "";
});
QCoreApplication::processEvents();
QMetaObject::invokeMethod(download.get(), &Task::start, Qt::QueuedConnection);
}
int PrismUpdaterApp::parseReleasePage(const QByteArray* responce)
@ -624,24 +640,7 @@ bool PrismUpdaterApp::needUpdate(const GitHubRelease& release)
return current_ver < release.version;
}
void PrismUpdaterApp::downloadError(QNetworkReply::NetworkError error)
void PrismUpdaterApp::downloadError(QString reason)
{
if (error == QNetworkReply::OperationCanceledError) {
abort(QString("Aborted %1").arg(m_reply->url().toString()));
} else {
fail(QString("Network request Failed: %1 with reason %2").arg(m_reply->url().toString()).arg(error));
}
}
void PrismUpdaterApp::sslErrors(const QList<QSslError>& errors)
{
int i = 1;
QString err_msg;
for (auto error : errors) {
err_msg.append(QString("Network request %1 SSL Error %2: %3\n").arg(m_reply->url().toString()).arg(i).arg(error.errorString()));
auto cert = error.certificate();
err_msg.append(QString("Certificate in question:\n%1").arg(cert.toText()));
i++;
}
fail(err_msg);
fail(QString("Network request Failed: %1 with reason %2").arg(m_current_url).arg(reason));
}

View File

@ -36,6 +36,10 @@
#include <QUrl>
#include <memory>
#include "QObjectPtr.h"
#include "net/Download.h"
#define PRISM_EXTERNAL_EXE
#include "FileSystem.h"
@ -58,7 +62,7 @@ class PrismUpdaterApp : public QApplication {
void showFatalErrorMessage(const QString& title, const QString& content);
void loadPrismVersionFromExe(const QString& exe_path);
void downloadReleasePage(const QString& api_url, int page);
int parseReleasePage(const QByteArray* responce);
GitHubRelease getLatestRelease();
@ -69,8 +73,10 @@ class PrismUpdaterApp : public QApplication {
QList<GitHubRelease> newerReleases();
QList<GitHubRelease> nonDraftReleases();
void downloadError(QNetworkReply::NetworkError error);
void sslErrors(const QList<QSslError>& errors);
public slots:
void downloadError(QString reason);
private:
const QString& root() { return m_rootPath; }
@ -95,8 +101,9 @@ class PrismUpdaterApp : public QApplication {
QString m_prismGitCommit;
Status m_status = Status::Starting;
QNetworkAccessManager* m_network;
QNetworkReply* m_reply;
shared_qobject_ptr<QNetworkAccessManager> m_network;
QString m_current_url;
Task::Ptr m_current_task;
QList<GitHubRelease> m_releases;
public: