HTTP: Make redirect response parsing more generic

To enable its use in the http2 protocol handler.
This factors out the error-reporting code for HTTP 1, which in
any case has to be done differently for HTTP 2, saving duplication
and simplifying the redirect handling code.

Task-number: QTBUG-100651
Pick-to: 6.3 6.2 5.15
Change-Id: I4b470646a9ad5ee702c9b1921d115e137d3d5b8b
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
Reviewed-by: Øystein Heskestad <oystein.heskestad@qt.io>
Reviewed-by: Marc Mutz <marc.mutz@qt.io>
This commit is contained in:
Mårten Nordheim 2022-02-09 17:40:48 +01:00
parent eab5ec5a37
commit 52492ff720
2 changed files with 29 additions and 16 deletions

View File

@ -525,10 +525,23 @@ bool QHttpNetworkConnectionPrivate::handleAuthenticateChallenge(QAbstractSocket
return false;
}
QUrl QHttpNetworkConnectionPrivate::parseRedirectResponse(QAbstractSocket *socket, QHttpNetworkReply *reply)
// Used by the HTTP1 code-path
QUrl QHttpNetworkConnectionPrivate::parseRedirectResponse(QAbstractSocket *socket,
QHttpNetworkReply *reply)
{
ParseRedirectResult result = parseRedirectResponse(reply);
if (result.errorCode != QNetworkReply::NoError) {
emitReplyError(socket, reply, result.errorCode);
return {};
}
return std::move(result.redirectUrl);
}
QHttpNetworkConnectionPrivate::ParseRedirectResult
QHttpNetworkConnectionPrivate::parseRedirectResponse(QHttpNetworkReply *reply)
{
if (!reply->request().isFollowRedirects())
return QUrl();
return {{}, QNetworkReply::NoError};
QUrl redirectUrl;
const QList<QPair<QByteArray, QByteArray> > fields = reply->header();
@ -539,17 +552,13 @@ QUrl QHttpNetworkConnectionPrivate::parseRedirectResponse(QAbstractSocket *socke
}
}
// If the location url is invalid/empty, we emit ProtocolUnknownError
if (!redirectUrl.isValid()) {
emitReplyError(socket, reply, QNetworkReply::ProtocolUnknownError);
return QUrl();
}
// If the location url is invalid/empty, we return ProtocolUnknownError
if (!redirectUrl.isValid())
return {{}, QNetworkReply::ProtocolUnknownError};
// Check if we have exceeded max redirects allowed
if (reply->request().redirectCount() <= 0) {
emitReplyError(socket, reply, QNetworkReply::TooManyRedirectsError);
return QUrl();
}
if (reply->request().redirectCount() <= 0)
return {{}, QNetworkReply::TooManyRedirectsError};
// Resolve the URL if it's relative
if (redirectUrl.isRelative())
@ -570,8 +579,7 @@ QUrl QHttpNetworkConnectionPrivate::parseRedirectResponse(QAbstractSocket *socke
if (priorUrl.host() != redirectUrl.host()
|| priorUrl.scheme() != redirectUrl.scheme()
|| priorUrl.port() != redirectUrl.port()) {
emitReplyError(socket, reply, QNetworkReply::InsecureRedirectError);
return QUrl();
return {{}, QNetworkReply::InsecureRedirectError};
}
break;
case QNetworkRequest::UserVerifiedRedirectPolicy:
@ -580,10 +588,9 @@ QUrl QHttpNetworkConnectionPrivate::parseRedirectResponse(QAbstractSocket *socke
Q_ASSERT(!"Unexpected redirect policy");
}
} else {
emitReplyError(socket, reply, QNetworkReply::ProtocolUnknownError);
return QUrl();
return {{}, QNetworkReply::ProtocolUnknownError};
}
return redirectUrl;
return {std::move(redirectUrl), QNetworkReply::NoError};
}
void QHttpNetworkConnectionPrivate::createAuthorization(QAbstractSocket *socket, QHttpNetworkRequest &request)

View File

@ -260,6 +260,12 @@ public:
void emitReplyError(QAbstractSocket *socket, QHttpNetworkReply *reply, QNetworkReply::NetworkError errorCode);
bool handleAuthenticateChallenge(QAbstractSocket *socket, QHttpNetworkReply *reply, bool isProxy, bool &resend);
struct ParseRedirectResult {
QUrl redirectUrl;
QNetworkReply::NetworkError errorCode;
};
ParseRedirectResult parseRedirectResponse(QHttpNetworkReply *reply);
// Used by the HTTP1 code-path
QUrl parseRedirectResponse(QAbstractSocket *socket, QHttpNetworkReply *reply);
#ifndef QT_NO_NETWORKPROXY