summaryrefslogtreecommitdiffstats
path: root/src/network/access
diff options
context:
space:
mode:
authorTimur Pocheptsov <timur.pocheptsov@qt.io>2017-01-02 15:47:15 +0100
committerTimur Pocheptsov <timur.pocheptsov@qt.io>2017-01-19 04:34:03 +0000
commit231259c3d519a55880563b12f5796723fa99e522 (patch)
treeaea3205f73e08803a7d52cb2581cf67c4266f7bf /src/network/access
parent45f80a52c2d01ba14f550e48e32d95748a3ff444 (diff)
Add a user-controlled auto-redirect policy
With this new policy, after emitting 'redirected', QNetworkReplyHttpImpl waits for client code to decide if QNAM should follow this redirect or not. The client can either allow this redirect by emitting 'redirectAllowed' or abort the reply. Task-number: QTPM-236 Change-Id: Ia04619f6bd1f0caa477833ae859b24033027b2e1 Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io> Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
Diffstat (limited to 'src/network/access')
-rw-r--r--src/network/access/qhttpnetworkconnection.cpp2
-rw-r--r--src/network/access/qnetworkreply.cpp14
-rw-r--r--src/network/access/qnetworkreply.h1
-rw-r--r--src/network/access/qnetworkreplyhttpimpl.cpp21
-rw-r--r--src/network/access/qnetworkreplyhttpimpl_p.h3
-rw-r--r--src/network/access/qnetworkrequest.cpp10
-rw-r--r--src/network/access/qnetworkrequest.h3
7 files changed, 48 insertions, 6 deletions
diff --git a/src/network/access/qhttpnetworkconnection.cpp b/src/network/access/qhttpnetworkconnection.cpp
index e5c6c2f81c..327eaf91bc 100644
--- a/src/network/access/qhttpnetworkconnection.cpp
+++ b/src/network/access/qhttpnetworkconnection.cpp
@@ -567,6 +567,8 @@ QUrl QHttpNetworkConnectionPrivate::parseRedirectResponse(QAbstractSocket *socke
return QUrl();
}
break;
+ case QNetworkRequest::UserVerifiedRedirectsPolicy:
+ break;
default:
Q_ASSERT(!"Unexpected redirect policy");
}
diff --git a/src/network/access/qnetworkreply.cpp b/src/network/access/qnetworkreply.cpp
index b35cfe03d7..17990f02f5 100644
--- a/src/network/access/qnetworkreply.cpp
+++ b/src/network/access/qnetworkreply.cpp
@@ -305,6 +305,20 @@ QNetworkReplyPrivate::QNetworkReplyPrivate()
*/
/*!
+ \fn void QNetworkReply::redirectAllowed()
+ \since 5.9
+
+ When client code handling the redirected() signal has verified the new URL,
+ it emits this signal to allow the redirect to go ahead. This protocol applies
+ to network requests whose redirects policy is set to
+ QNetworkRequest::UserVerifiedRedirectsPolicy.
+
+ \sa QNetworkRequest::UserVerifiedRedirectsPolicy
+ QNetworkAccessManager::setRedirectsPolicy(),
+ QNetworkRequest::RedirectsPolicyAttribute
+*/
+
+/*!
\fn void QNetworkReply::metaDataChanged()
\omit FIXME: Update name? \endomit
diff --git a/src/network/access/qnetworkreply.h b/src/network/access/qnetworkreply.h
index 1419db8597..d858e07d84 100644
--- a/src/network/access/qnetworkreply.h
+++ b/src/network/access/qnetworkreply.h
@@ -163,6 +163,7 @@ Q_SIGNALS:
void preSharedKeyAuthenticationRequired(QSslPreSharedKeyAuthenticator *authenticator);
#endif
void redirected(const QUrl &url);
+ void redirectAllowed();
void uploadProgress(qint64 bytesSent, qint64 bytesTotal);
void downloadProgress(qint64 bytesReceived, qint64 bytesTotal);
diff --git a/src/network/access/qnetworkreplyhttpimpl.cpp b/src/network/access/qnetworkreplyhttpimpl.cpp
index 03ed596586..19f424b35f 100644
--- a/src/network/access/qnetworkreplyhttpimpl.cpp
+++ b/src/network/access/qnetworkreplyhttpimpl.cpp
@@ -824,12 +824,16 @@ void QNetworkReplyHttpImplPrivate::postRequest(const QNetworkRequest &newHttpReq
QObject::connect(delegate, SIGNAL(redirected(QUrl,int,int)),
q, SLOT(onRedirected(QUrl,int,int)),
Qt::QueuedConnection);
+
+ QObject::connect(q, SIGNAL(redirectAllowed()), q, SLOT(followRedirect()),
+ Qt::QueuedConnection);
+
#ifndef QT_NO_SSL
QObject::connect(delegate, SIGNAL(sslConfigurationChanged(QSslConfiguration)),
q, SLOT(replySslConfigurationChanged(QSslConfiguration)),
Qt::QueuedConnection);
#endif
- // Those need to report back, therefire BlockingQueuedConnection
+ // Those need to report back, therefore BlockingQueuedConnection
QObject::connect(delegate, SIGNAL(authenticationRequired(QHttpNetworkRequest,QAuthenticator*)),
q, SLOT(httpAuthenticationRequired(QHttpNetworkRequest,QAuthenticator*)),
Qt::BlockingQueuedConnection);
@@ -1121,19 +1125,26 @@ void QNetworkReplyHttpImplPrivate::onRedirected(const QUrl &redirectUrl, int htt
if (httpRequest.isFollowRedirects()) // update the reply's url as it could've changed
url = redirectUrl;
- QNetworkRequest redirectRequest = createRedirectRequest(originalRequest, redirectUrl, maxRedirectsRemaining);
+ redirectRequest = createRedirectRequest(originalRequest, redirectUrl, maxRedirectsRemaining);
operation = getRedirectOperation(operation, httpStatus);
+ if (httpRequest.redirectsPolicy() != QNetworkRequest::UserVerifiedRedirectsPolicy)
+ followRedirect();
+
+ emit q->redirected(redirectUrl);
+}
+
+void QNetworkReplyHttpImplPrivate::followRedirect()
+{
+ Q_Q(QNetworkReplyHttpImpl);
+
cookedHeaders.clear();
if (managerPrivate->thread)
managerPrivate->thread->disconnect();
- // Recurse
QMetaObject::invokeMethod(q, "start", Qt::QueuedConnection,
Q_ARG(QNetworkRequest, redirectRequest));
-
- emit q->redirected(redirectUrl);
}
void QNetworkReplyHttpImplPrivate::checkForRedirect(const int statusCode)
diff --git a/src/network/access/qnetworkreplyhttpimpl_p.h b/src/network/access/qnetworkreplyhttpimpl_p.h
index 255c23006e..9383149124 100644
--- a/src/network/access/qnetworkreplyhttpimpl_p.h
+++ b/src/network/access/qnetworkreplyhttpimpl_p.h
@@ -136,6 +136,7 @@ public:
Q_PRIVATE_SLOT(d_func(), void _q_cacheSaveDeviceAboutToClose())
Q_PRIVATE_SLOT(d_func(), void _q_metaDataChanged())
Q_PRIVATE_SLOT(d_func(), void onRedirected(const QUrl &, int, int))
+ Q_PRIVATE_SLOT(d_func(), void followRedirect())
#ifndef QT_NO_SSL
protected:
@@ -212,6 +213,7 @@ public:
QSharedPointer<QRingBuffer> outgoingDataBuffer;
void emitReplyUploadProgress(qint64 bytesSent, qint64 bytesTotal); // dup?
void onRedirected(const QUrl &redirectUrl, int httpStatus, int maxRedirectsRemainig);
+ void followRedirect();
qint64 bytesUploaded;
@@ -263,6 +265,7 @@ public:
QList<QSslError> pendingIgnoreSslErrorsList;
#endif
+ QNetworkRequest redirectRequest;
bool loadFromCacheIfAllowed(QHttpNetworkRequest &httpRequest);
void invalidateCache();
diff --git a/src/network/access/qnetworkrequest.cpp b/src/network/access/qnetworkrequest.cpp
index abc924d0e2..169695fa27 100644
--- a/src/network/access/qnetworkrequest.cpp
+++ b/src/network/access/qnetworkrequest.cpp
@@ -360,6 +360,16 @@ QT_BEGIN_NAMESPACE
Note, http://example.com and http://example.com:80
will fail with this policy (implicit/explicit ports
are considered to be a mismatch).
+
+ \value UserVerifiedRedirectsPolicy Client decides whether to follow each
+ redirect by handling the redirected()
+ signal, emitting redirectAllowed() on
+ the QNetworkReply object to allow
+ the redirect or aborting/finishing it to
+ reject the redirect. This can be used,
+ for example, to ask the user whether to
+ accept the redirect, or to decide
+ based on some app-specific configuration.
*/
class QNetworkRequestPrivate: public QSharedData, public QNetworkHeadersPrivate
diff --git a/src/network/access/qnetworkrequest.h b/src/network/access/qnetworkrequest.h
index 52c398663a..06c895af5f 100644
--- a/src/network/access/qnetworkrequest.h
+++ b/src/network/access/qnetworkrequest.h
@@ -116,7 +116,8 @@ public:
enum RedirectsPolicy {
ManualRedirectsPolicy,
NoLessSafeRedirectsPolicy,
- SameOriginRedirectsPolicy
+ SameOriginRedirectsPolicy,
+ UserVerifiedRedirectsPolicy
};