Handle redirections more nicely

* Log redirections in accordance with logging settings
* Load self-signed certificate as needed
This commit is contained in:
Martchus 2023-12-30 20:11:34 +01:00
parent ddd4f6b411
commit c1284331be
4 changed files with 24 additions and 4 deletions

View File

@ -778,13 +778,13 @@ void SyncthingConnection::continueConnecting()
* only do the cleanup of previous certificates but not emit any errors.
* \returns Returns whether a certificate could be loaded.
*/
bool SyncthingConnection::loadSelfSignedCertificate()
bool SyncthingConnection::loadSelfSignedCertificate(const QUrl &url)
{
// ensure current exceptions for self-signed certificates are cleared
m_expectedSslErrors.clear();
// not required when not using secure connection
const QUrl syncthingUrl(m_syncthingUrl);
const auto syncthingUrl = url.isEmpty() ? m_syncthingUrl : url;
if (!syncthingUrl.scheme().endsWith(QChar('s'))) {
return false;
}

View File

@ -180,7 +180,7 @@ public:
const QList<QSslError> &expectedSslErrors() const;
public Q_SLOTS:
bool loadSelfSignedCertificate();
bool loadSelfSignedCertificate(const QUrl &url = QUrl());
bool applySettings(Data::SyncthingConnectionSettings &connectionSettings);
// methods to initiate/close connection
@ -337,6 +337,7 @@ private Q_SLOTS:
void handleFatalConnectionError();
void handleAdditionalRequestCanceled();
void handleSslErrors(const QList<QSslError> &errors);
void handleRedirection(const QUrl &url);
void recalculateStatus();
QString configPath() const;
QByteArray changeConfigVerb() const;

View File

@ -63,6 +63,7 @@ QNetworkReply *SyncthingConnection::requestData(const QString &path, const QUrlQ
#ifndef LIB_SYNCTHING_CONNECTOR_CONNECTION_MOCKED
auto *const reply = networkAccessManager().get(prepareRequest(path, query, rest, longPolling));
QObject::connect(reply, &QNetworkReply::sslErrors, this, &SyncthingConnection::handleSslErrors);
QObject::connect(reply, &QNetworkReply::redirected, this, &SyncthingConnection::handleRedirection);
if (loggingFlags() & SyncthingConnectionLoggingFlags::ApiCalls) {
cerr << Phrases::Info << "Querying API: GET " << reply->url().toString().toStdString() << Phrases::EndFlush;
}
@ -188,6 +189,24 @@ void SyncthingConnection::handleSslErrors(const QList<QSslError> &errors)
}
}
/*!
* \brief Handles redirections.
* \remarks The redirect policy will decide whether to follow the redirection or not.
* This function merely handles logging and loading the certificate in case this
* hasn't happened before (e.g. a redirection from http to https).
*/
void SyncthingConnection::handleRedirection(const QUrl &url)
{
if (m_loggingFlags & SyncthingConnectionLoggingFlags::ApiReplies) {
const auto urlStr = url.toString().toUtf8();
cerr << Phrases::Info << "Got redirected to: " << std::string_view(urlStr.data(), static_cast<std::string_view::size_type>(urlStr.size()))
<< Phrases::EndFlush;
}
if (m_expectedSslErrors.isEmpty() && url.scheme().endsWith(QChar('s'))) {
loadSelfSignedCertificate(url);
}
}
/*!
* \brief Handles the specified \a reply; invoked by the prepareReply() functions.
*/

View File

@ -188,7 +188,7 @@ void MiscTests::testConnectionSettingsAndLoadingSelfSignedCert()
bool errorOccured = false;
const function<void(const QString &)> errorHandler
= [&errorOccured](const QString &message) { errorOccured |= message == QStringLiteral("Unable to load certificate used by Syncthing."); };
waitForSignals(bind(&SyncthingConnection::loadSelfSignedCertificate, &connection), 1,
waitForSignals(bind(&SyncthingConnection::loadSelfSignedCertificate, &connection, QUrl()), 1,
signalInfo(&connection, &SyncthingConnection::error, errorHandler, &errorOccured));
settings.expectedSslErrors.clear();
CPPUNIT_ASSERT(!connection.applySettings(settings));