QHttp: Fix handling of redirect loaded from cache
In some situations when loading a redirect from cache which would lead to a real request we would not emit the finished() signal because the replyFinished function has a pre-condition that the response did not originate from the cache. However, after the initial redirect was loaded from the cache we never unset the 'loadingFromCache' boolean, so it was still true after the request had been made to the real target. Pick-to: 6.2 6.3 5.15 Change-Id: I015a2ebae4af4bd17392182c3951e875a7b353c4 Reviewed-by: Edward Welbourne <edward.welbourne@qt.io> Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
This commit is contained in:
parent
d642c16fe7
commit
41d217829c
@ -712,6 +712,7 @@ void QNetworkReplyHttpImplPrivate::postRequest(const QNetworkRequest &newHttpReq
|
|||||||
httpRequest.setRedirectPolicy(redirectPolicy);
|
httpRequest.setRedirectPolicy(redirectPolicy);
|
||||||
|
|
||||||
httpRequest.setPriority(convert(newHttpRequest.priority()));
|
httpRequest.setPriority(convert(newHttpRequest.priority()));
|
||||||
|
loadingFromCache = false;
|
||||||
|
|
||||||
switch (operation) {
|
switch (operation) {
|
||||||
case QNetworkAccessManager::GetOperation:
|
case QNetworkAccessManager::GetOperation:
|
||||||
|
@ -500,6 +500,7 @@ private Q_SLOTS:
|
|||||||
void ioHttpCookiesDuringRedirect();
|
void ioHttpCookiesDuringRedirect();
|
||||||
void ioHttpRedirect_data();
|
void ioHttpRedirect_data();
|
||||||
void ioHttpRedirect();
|
void ioHttpRedirect();
|
||||||
|
void ioHttpRedirectWithCache();
|
||||||
void ioHttpRedirectFromLocalToRemote();
|
void ioHttpRedirectFromLocalToRemote();
|
||||||
void ioHttpRedirectPostPut_data();
|
void ioHttpRedirectPostPut_data();
|
||||||
void ioHttpRedirectPostPut();
|
void ioHttpRedirectPostPut();
|
||||||
@ -8874,6 +8875,64 @@ void tst_QNetworkReply::ioHttpRedirect()
|
|||||||
QVERIFY(validateRedirectedResponseHeaders(reply));
|
QVERIFY(validateRedirectedResponseHeaders(reply));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Test that, if we load a redirect from cache, we don't treat the request to
|
||||||
|
the destination of the redirect as a redirect.
|
||||||
|
|
||||||
|
If it was treated as a redirect the finished() signal was never emitted!
|
||||||
|
*/
|
||||||
|
void tst_QNetworkReply::ioHttpRedirectWithCache()
|
||||||
|
{
|
||||||
|
// Disallow caching the result so that the second request must also send the request
|
||||||
|
QByteArray http200ResponseNoCache = "HTTP/1.1 200 OK\r\n"
|
||||||
|
"Content-Type: text/plain\r\n"
|
||||||
|
"Cache-Control: no-cache\r\n"
|
||||||
|
"\r\nHello";
|
||||||
|
|
||||||
|
MiniHttpServer target(http200ResponseNoCache, false);
|
||||||
|
QUrl targetUrl("http://localhost/");
|
||||||
|
targetUrl.setPort(target.serverPort());
|
||||||
|
|
||||||
|
// A cache-able redirect reply
|
||||||
|
QString redirectReply = QStringLiteral("HTTP/1.1 308\r\n"
|
||||||
|
"Content-Type: text/plain\r\n"
|
||||||
|
"location: %1\r\n"
|
||||||
|
"Cache-Control: max-age=3600\r\n"
|
||||||
|
"\r\nYou're being redirected").arg(targetUrl.toString());
|
||||||
|
MiniHttpServer redirectServer(redirectReply.toLatin1(), false);
|
||||||
|
QUrl url("http://localhost/");
|
||||||
|
url.setPort(redirectServer.serverPort());
|
||||||
|
|
||||||
|
QTemporaryDir tempDir(QDir::tempPath() + "/tmp_cache_28035");
|
||||||
|
QVERIFY2(tempDir.isValid(), qPrintable(tempDir.errorString()));
|
||||||
|
tempDir.setAutoRemove(true);
|
||||||
|
|
||||||
|
QNetworkDiskCache *diskCache = new QNetworkDiskCache();
|
||||||
|
diskCache->setCacheDirectory(tempDir.path());
|
||||||
|
// Manager takes ownership of the cache:
|
||||||
|
manager.setCache(diskCache);
|
||||||
|
QCOMPARE(diskCache->cacheSize(), 0);
|
||||||
|
|
||||||
|
// Send the first request, we end up caching the redirect reply
|
||||||
|
QNetworkRequest request(url);
|
||||||
|
QNetworkReplyPtr reply(manager.get(request));
|
||||||
|
|
||||||
|
QCOMPARE(waitForFinish(reply), int(Success));
|
||||||
|
QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200);
|
||||||
|
QVERIFY(validateRedirectedResponseHeaders(reply));
|
||||||
|
|
||||||
|
QVERIFY(diskCache->cacheSize() != 0);
|
||||||
|
|
||||||
|
// Now for the second request, we will use the cache, and we test that the finished()
|
||||||
|
// signal is still emitted.
|
||||||
|
request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache);
|
||||||
|
reply.reset(manager.get(request));
|
||||||
|
|
||||||
|
QCOMPARE(waitForFinish(reply), int(Success));
|
||||||
|
QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200);
|
||||||
|
QVERIFY(validateRedirectedResponseHeaders(reply));
|
||||||
|
}
|
||||||
|
|
||||||
void tst_QNetworkReply::ioHttpRedirectFromLocalToRemote()
|
void tst_QNetworkReply::ioHttpRedirectFromLocalToRemote()
|
||||||
{
|
{
|
||||||
QUrl targetUrl("http://" + QtNetworkSettings::httpServerName() + "/qtest/rfc3252.txt");
|
QUrl targetUrl("http://" + QtNetworkSettings::httpServerName() + "/qtest/rfc3252.txt");
|
||||||
|
Loading…
Reference in New Issue
Block a user