diff --git a/src/opdsrequestmanager.cpp b/src/opdsrequestmanager.cpp index 3cde96f0..cb09afbc 100644 --- a/src/opdsrequestmanager.cpp +++ b/src/opdsrequestmanager.cpp @@ -1,5 +1,10 @@ #include "opdsrequestmanager.h" #include "kiwixapp.h" +#include + +namespace { +constexpr int kMaxRedirects = 5; +} OpdsRequestManager::OpdsRequestManager() { @@ -21,6 +26,44 @@ int OpdsRequestManager::getCatalogPort() : 443; } +// Helper to handle replies and follow redirects +void OpdsRequestManager::handleReply(QNetworkReply* reply, std::function finalHandler, int redirectCount) { + QVariant redirectAttr = reply->attribute(QNetworkRequest::RedirectionTargetAttribute); + if (redirectAttr.isValid() && redirectCount < kMaxRedirects) { + QUrl redirectUrl = redirectAttr.toUrl(); + // Make absolute if needed + if (redirectUrl.isRelative()) { + redirectUrl = reply->url().resolved(redirectUrl); + } + qInfo() << "Following redirect" << redirectCount + 1 << "to:" << redirectUrl.toString(); + reply->deleteLater(); + QNetworkRequest newRequest(redirectUrl); + QNetworkReply* newReply = m_networkManager.get(newRequest); + connect(newReply, &QNetworkReply::finished, this, [=]() { + handleReply(newReply, finalHandler, redirectCount + 1); + }); + return; + } + // No redirect, or max redirects reached + if (redirectAttr.isValid() && redirectCount >= kMaxRedirects) { + qWarning() << "Redirect limit (" << kMaxRedirects << ") reached. Reporting error."; + // Set a custom property to indicate redirect limit reached + reply->setProperty("redirectLimitReached", true); + // Optionally, abort the reply to set an error + reply->abort(); + } + if (redirectCount > 0) { + qInfo() << "Completed after" << redirectCount << "redirects"; + } + finalHandler(reply); +} + +// New method to allow requests to arbitrary URLs (for redirects) +QNetworkReply* OpdsRequestManager::opdsResponseFromUrl(const QUrl &url) { + QNetworkRequest request(url); + return m_networkManager.get(request); +} + void OpdsRequestManager::doUpdate(const QString& currentLanguage, const QString& categoryFilter) { QUrlQuery query; @@ -43,7 +86,7 @@ void OpdsRequestManager::doUpdate(const QString& currentLanguage, const QString& auto mp_reply = opdsResponseFromPath("/catalog/v2/entries", query); connect(mp_reply, &QNetworkReply::finished, this, [=]() { - receiveContent(mp_reply); + handleReply(mp_reply, [this](QNetworkReply* r) { receiveContent(r); }, 0); }); } @@ -65,7 +108,7 @@ void OpdsRequestManager::getLanguagesFromOpds() { auto mp_reply = opdsResponseFromPath("/catalog/v2/languages"); connect(mp_reply, &QNetworkReply::finished, this, [=]() { - receiveLanguages(mp_reply); + handleReply(mp_reply, [this](QNetworkReply* r) { receiveLanguages(r); }, 0); }); } @@ -73,7 +116,7 @@ void OpdsRequestManager::getCategoriesFromOpds() { auto mp_reply = opdsResponseFromPath("/catalog/v2/categories"); connect(mp_reply, &QNetworkReply::finished, this, [=]() { - receiveCategories(mp_reply); + handleReply(mp_reply, [this](QNetworkReply* r) { receiveCategories(r); }, 0); }); } diff --git a/src/opdsrequestmanager.h b/src/opdsrequestmanager.h index b14f9a29..d33af38c 100644 --- a/src/opdsrequestmanager.h +++ b/src/opdsrequestmanager.h @@ -18,15 +18,20 @@ class OpdsRequestManager : public QObject void doUpdate(const QString& currentLanguage, const QString& categoryFilter); void getLanguagesFromOpds(); void getCategoriesFromOpds(); + QNetworkReply* opdsResponseFromUrl(const QUrl &url); private: QNetworkAccessManager m_networkManager; QNetworkReply* opdsResponseFromPath(const QString &path, const QUrlQuery &query = QUrlQuery()); + void handleNetworkReply(QNetworkReply* reply, void (OpdsRequestManager::*finalHandler)(QNetworkReply*), int redirectCount); + void handleReply(QNetworkReply* reply, std::function finalHandler, int redirectCount); + static constexpr int MAX_REDIRECTS = 5; signals: void requestReceived(const QString&); void languagesReceived(const QString&); void categoriesReceived(const QString&); + void requestError(const QString& errorMessage); public slots: void receiveContent(QNetworkReply*); @@ -39,3 +44,5 @@ public slots: }; #endif // OPDSREQUESTMANAGER_H + +