diff options
author | Mandeep Sandhu <mandeepsandhu.chd@gmail.com> | 2014-03-17 19:21:25 +0530 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@theqtcompany.com> | 2015-03-09 08:32:14 +0000 |
commit | d815de8c26ccee33713e37a0fec2982755dcfe1f (patch) | |
tree | 9bfae5a77f94368c139e5290399a9f7ec6471367 /src/network/access/qhttpnetworkconnection.cpp | |
parent | f7118e7f1b495fc0a0b8d83dff1a207dfddb09aa (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.cpp | 55 |
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; |