network jobs: Refactor the redirect handling in AbdtractNetworkJob

Move the redirect handling from CheckServerJob to AbstractNetworkJob, so we can
later use it in any job  (in preparation for task #2614)
This commit is contained in:
Olivier Goffart 2014-12-16 11:27:02 +01:00
parent 9a13ec736d
commit 3ee14164db
4 changed files with 32 additions and 28 deletions

View file

@ -148,7 +148,7 @@ void OwncloudSetupWizard::slotDetermineAuthType(const QString &urlString)
account->setUrl(url); account->setUrl(url);
// Set fake credentials beforfe we check what credential it actually is. // Set fake credentials beforfe we check what credential it actually is.
account->setCredentials(CredentialsFactory::create("dummy")); account->setCredentials(CredentialsFactory::create("dummy"));
CheckServerJob *job = new CheckServerJob(_ocWizard->account(), false, this); CheckServerJob *job = new CheckServerJob(_ocWizard->account(), this);
job->setIgnoreCredentialFailure(true); job->setIgnoreCredentialFailure(true);
connect(job, SIGNAL(instanceFound(QUrl,QVariantMap)), SLOT(slotOwnCloudFoundAuth(QUrl,QVariantMap))); connect(job, SIGNAL(instanceFound(QUrl,QVariantMap)), SLOT(slotOwnCloudFoundAuth(QUrl,QVariantMap)));
connect(job, SIGNAL(instanceNotFound(QNetworkReply*)), SLOT(slotNoOwnCloudFoundAuth(QNetworkReply*))); connect(job, SIGNAL(instanceNotFound(QNetworkReply*)), SLOT(slotNoOwnCloudFoundAuth(QNetworkReply*)));

View file

@ -75,7 +75,7 @@ void ConnectionValidator::checkConnection()
// gets replied to. // gets replied to.
slotCheckAuthentication(); slotCheckAuthentication();
} else { } else {
CheckServerJob *checkJob = new CheckServerJob(_account, false, this); CheckServerJob *checkJob = new CheckServerJob(_account, this);
checkJob->setIgnoreCredentialFailure(true); checkJob->setIgnoreCredentialFailure(true);
connect(checkJob, SIGNAL(instanceFound(QUrl,QVariantMap)), SLOT(slotStatusFound(QUrl,QVariantMap))); connect(checkJob, SIGNAL(instanceFound(QUrl,QVariantMap)), SLOT(slotStatusFound(QUrl,QVariantMap)));
connect(checkJob, SIGNAL(networkError(QNetworkReply*)), SLOT(slotNoStatusFound(QNetworkReply*))); connect(checkJob, SIGNAL(networkError(QNetworkReply*)), SLOT(slotNoStatusFound(QNetworkReply*)));

View file

@ -46,10 +46,12 @@ AbstractNetworkJob::AbstractNetworkJob(Account *account, const QString &path, QO
: QObject(parent) : QObject(parent)
, _duration(0) , _duration(0)
, _timedout(false) , _timedout(false)
, _followRedirects(false)
, _ignoreCredentialFailure(false) , _ignoreCredentialFailure(false)
, _reply(0) , _reply(0)
, _account(account) , _account(account)
, _path(path) , _path(path)
, _redirectCount(0)
{ {
_timer.setSingleShot(true); _timer.setSingleShot(true);
_timer.setInterval(OwncloudPropagator::httpTimeout() * 1000); // default to 5 minutes. _timer.setInterval(OwncloudPropagator::httpTimeout() * 1000); // default to 5 minutes.
@ -164,6 +166,28 @@ void AbstractNetworkJob::slotFinished()
_responseTimestamp = QString::fromAscii(_reply->rawHeader("Date")); _responseTimestamp = QString::fromAscii(_reply->rawHeader("Date"));
_duration = _durationTimer.elapsed(); _duration = _durationTimer.elapsed();
if (_followRedirects) {
// ### the qWarnings here should be exported via displayErrors() so they
// ### can be presented to the user if the job executor has a GUI
QUrl requestedUrl = reply()->request().url();
QUrl redirectUrl = reply()->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl();
if (!redirectUrl.isEmpty()) {
_redirectCount++;
if (requestedUrl.scheme() == QLatin1String("https") &&
redirectUrl.scheme() == QLatin1String("http")) {
qWarning() << this << "HTTPS->HTTP downgrade detected!";
} else if (requestedUrl == redirectUrl || _redirectCount >= maxRedirects()) {
qWarning() << this << "Redirect loop detected!";
} else {
resetTimeout();
setReply(getRequest(redirectUrl));
setupConnections(reply());
return;
}
}
}
bool discard = finished(); bool discard = finished();
AbstractCredentials *creds = _account->credentials(); AbstractCredentials *creds = _account->credentials();
if (!creds->stillValid(_reply) &&! _ignoreCredentialFailure if (!creds->stillValid(_reply) &&! _ignoreCredentialFailure
@ -367,12 +391,11 @@ const char statusphpC[] = "status.php";
const char owncloudDirC[] = "owncloud/"; const char owncloudDirC[] = "owncloud/";
} }
CheckServerJob::CheckServerJob(Account *account, bool followRedirect, QObject *parent) CheckServerJob::CheckServerJob(Account *account, QObject *parent)
: AbstractNetworkJob(account, QLatin1String(statusphpC) , parent) : AbstractNetworkJob(account, QLatin1String(statusphpC) , parent)
, _followRedirects(followRedirect)
, _subdirFallback(false) , _subdirFallback(false)
, _redirectCount(0)
{ {
_followRedirects = true;
setIgnoreCredentialFailure(true); setIgnoreCredentialFailure(true);
} }
@ -413,25 +436,6 @@ bool CheckServerJob::finished()
{ {
account()->setSslConfiguration(reply()->sslConfiguration()); account()->setSslConfiguration(reply()->sslConfiguration());
// ### the qDebugs here should be exported via displayErrors() so they
// ### can be presented to the user if the job executor has a GUI
QUrl requestedUrl = reply()->request().url();
QUrl redirectUrl = reply()->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl();
if (!redirectUrl.isEmpty()) {
_redirectCount++;
if (requestedUrl.scheme() == QLatin1String("https") &&
redirectUrl.scheme() == QLatin1String("http")) {
qDebug() << Q_FUNC_INFO << "HTTPS->HTTP downgrade detected!";
} else if (requestedUrl == redirectUrl || _redirectCount >= maxRedirects()) {
qDebug() << Q_FUNC_INFO << "Redirect loop detected!";
} else {
resetTimeout();
setReply(getRequest(redirectUrl));
setupConnections(reply());
return false;
}
}
// The serverInstalls to /owncloud. Let's try that if the file wasn't found // The serverInstalls to /owncloud. Let's try that if the file wasn't found
// at the original location // at the original location
if ((reply()->error() == QNetworkReply::ContentNotFoundError) && (!_subdirFallback)) { if ((reply()->error() == QNetworkReply::ContentNotFoundError) && (!_subdirFallback)) {
@ -467,7 +471,7 @@ bool CheckServerJob::finished()
emit instanceFound(reply()->url(), status); emit instanceFound(reply()->url(), status);
} else { } else {
qDebug() << "No proper answer on " << requestedUrl; qDebug() << "No proper answer on " << reply()->url();
emit instanceNotFound(reply()); emit instanceNotFound(reply());
} }
} }

View file

@ -94,6 +94,7 @@ protected:
QElapsedTimer _durationTimer; QElapsedTimer _durationTimer;
quint64 _duration; quint64 _duration;
bool _timedout; // set to true when the timeout slot is recieved bool _timedout; // set to true when the timeout slot is recieved
bool _followRedirects;
public: public:
// Timeout workarounds (Because of PHP session locking) // Timeout workarounds (Because of PHP session locking)
@ -111,6 +112,7 @@ private:
Account *_account; Account *_account;
QString _path; QString _path;
QTimer _timer; QTimer _timer;
int _redirectCount;
}; };
/** /**
@ -189,7 +191,7 @@ private slots:
class OWNCLOUDSYNC_EXPORT CheckServerJob : public AbstractNetworkJob { class OWNCLOUDSYNC_EXPORT CheckServerJob : public AbstractNetworkJob {
Q_OBJECT Q_OBJECT
public: public:
explicit CheckServerJob(Account *account, bool followRedirect = false, QObject *parent = 0); explicit CheckServerJob(Account *account, QObject *parent = 0);
void start() Q_DECL_OVERRIDE; void start() Q_DECL_OVERRIDE;
static QString version(const QVariantMap &info); static QString version(const QVariantMap &info);
@ -206,9 +208,7 @@ private slots:
virtual void slotTimeout() Q_DECL_OVERRIDE; virtual void slotTimeout() Q_DECL_OVERRIDE;
private: private:
bool _followRedirects;
bool _subdirFallback; bool _subdirFallback;
int _redirectCount;
}; };