summaryrefslogtreecommitdiffstats
path: root/src/network/access/qhttpnetworkconnection.cpp
diff options
context:
space:
mode:
authorMandeep Sandhu <mandeepsandhu.chd@gmail.com>2014-03-17 19:21:25 +0530
committerAllan Sandfeld Jensen <allan.jensen@theqtcompany.com>2015-03-09 08:32:14 +0000
commitd815de8c26ccee33713e37a0fec2982755dcfe1f (patch)
tree9bfae5a77f94368c139e5290399a9f7ec6471367 /src/network/access/qhttpnetworkconnection.cpp
parentf7118e7f1b495fc0a0b8d83dff1a207dfddb09aa (diff)
QNetworkAccessManager: Support HTTP redirection
This commit adds support for following HTTP redirect responses on a per request basis. This behavior is disabled by default. It can be switched on by setting the QNetworkRequest::FollowRedirectAttribute to true. 2 new error codes have been added to QNetworkReply: * TooManyRedirectsError: Set when the number of redirects exceed a given value set by the user (defaults to 50 if not set) * UnsecureRedirectError: Set when we are redirecting from a 'https' to 'http' protocol. Test cases for the following scenarios: * Single HTTP redirect using local test server * Changing max-redirects * Testing all redirect related error scenarios The next commit will extend this feature at a QNAM level. Task-number: QTBUG-8232 Change-Id: If9e28ad12bad08bcdc5bc511b1cd59dc9d8150f0 Reviewed-by: Allan Sandfeld Jensen <allan.jensen@theqtcompany.com>
Diffstat (limited to 'src/network/access/qhttpnetworkconnection.cpp')
-rw-r--r--src/network/access/qhttpnetworkconnection.cpp55
1 files changed, 55 insertions, 0 deletions
diff --git a/src/network/access/qhttpnetworkconnection.cpp b/src/network/access/qhttpnetworkconnection.cpp
index 7a848dcfcd..7eaa7535ee 100644
--- a/src/network/access/qhttpnetworkconnection.cpp
+++ b/src/network/access/qhttpnetworkconnection.cpp
@@ -506,6 +506,55 @@ bool QHttpNetworkConnectionPrivate::handleAuthenticateChallenge(QAbstractSocket
return false;
}
+bool QHttpNetworkConnectionPrivate::parseRedirectResponse(QAbstractSocket *socket, QHttpNetworkReply *reply, QUrl *redirectUrl)
+{
+ if (!reply->request().isFollowRedirects())
+ return false;
+
+ QUrl rUrl;
+ QList<QPair<QByteArray, QByteArray> > fields = reply->header();
+ foreach (const QNetworkReply::RawHeaderPair &header, fields) {
+ if (header.first.toLower() == "location") {
+ rUrl = QUrl::fromEncoded(header.second);
+ break;
+ }
+ }
+
+ // If the location url is invalid/empty, we emit ProtocolUnknownError
+ if (!rUrl.isValid()) {
+ emitReplyError(socket, reply, QNetworkReply::ProtocolUnknownError);
+ return false;
+ }
+
+ // Check if we have exceeded max redirects allowed
+ if (reply->request().redirectCount() <= 0) {
+ emitReplyError(socket, reply, QNetworkReply::TooManyRedirectsError);
+ return false;
+ }
+
+ // Resolve the URL if it's relative
+ if (rUrl.isRelative())
+ rUrl = reply->request().url().resolved(rUrl);
+
+ // Check redirect url protocol
+ QString scheme = rUrl.scheme();
+ if (scheme == QLatin1String("http") || scheme == QLatin1String("https")) {
+ QString previousUrlScheme = reply->request().url().scheme();
+ // Check if we're doing an unsecure redirect (https -> http)
+ if (previousUrlScheme == QLatin1String("https")
+ && scheme == QLatin1String("http")) {
+ emitReplyError(socket, reply, QNetworkReply::InsecureRedirectError);
+ return false;
+ }
+ } else {
+ emitReplyError(socket, reply, QNetworkReply::ProtocolUnknownError);
+ return false;
+ }
+ redirectUrl->setUrl(QString(rUrl.toEncoded()));
+
+ return true;
+}
+
void QHttpNetworkConnectionPrivate::createAuthorization(QAbstractSocket *socket, QHttpNetworkRequest &request)
{
Q_ASSERT(socket);
@@ -802,6 +851,12 @@ QString QHttpNetworkConnectionPrivate::errorDetail(QNetworkReply::NetworkError e
case QNetworkReply::SslHandshakeFailedError:
errorString = QCoreApplication::translate("QHttp", "SSL handshake failed");
break;
+ case QNetworkReply::TooManyRedirectsError:
+ errorString = QCoreApplication::translate("QHttp", "Too many redirects");
+ break;
+ case QNetworkReply::InsecureRedirectError:
+ errorString = QCoreApplication::translate("QHttp", "Insecure redirect");
+ break;
default:
// all other errors are treated as QNetworkReply::UnknownNetworkError
errorString = extraDetail;