Fix redirecting all the other methods for HTTP 307 and 308
c4cf90b1f739c47383672de3d66b1d9d5427f5db made POST requests be redirected properly, but this wasn't enough and should have included every method/verb. Change-Id: I37b12dc9fdffcbf2aadbd2360d4fc2584c024939 Reviewed-by: Edward Welbourne <edward.welbourne@qt.io> Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
This commit is contained in:
parent
7e7683cabb
commit
18f0a45964
@ -1110,16 +1110,14 @@ QNetworkAccessManager::Operation QNetworkReplyHttpImplPrivate::getRedirectOperat
|
|||||||
// HTTP status code can be used to decide if we can redirect with a GET
|
// HTTP status code can be used to decide if we can redirect with a GET
|
||||||
// operation or not. See http://www.ietf.org/rfc/rfc2616.txt [Sec 10.3] for
|
// operation or not. See http://www.ietf.org/rfc/rfc2616.txt [Sec 10.3] for
|
||||||
// more details
|
// more details
|
||||||
Q_UNUSED(httpStatus);
|
|
||||||
|
// We MUST keep using the verb that was used originally when being redirected with 307 or 308.
|
||||||
|
if (httpStatus == 307 || httpStatus == 308)
|
||||||
|
return currentOp;
|
||||||
|
|
||||||
switch (currentOp) {
|
switch (currentOp) {
|
||||||
case QNetworkAccessManager::HeadOperation:
|
case QNetworkAccessManager::HeadOperation:
|
||||||
return QNetworkAccessManager::HeadOperation;
|
return QNetworkAccessManager::HeadOperation;
|
||||||
case QNetworkAccessManager::PostOperation:
|
|
||||||
// We MUST keep using POST when being redirected with 307 or 308.
|
|
||||||
if (statusCode == 307 || statusCode == 308)
|
|
||||||
return QNetworkAccessManager::PostOperation;
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -491,10 +491,12 @@ private Q_SLOTS:
|
|||||||
void ioHttpRedirect_data();
|
void ioHttpRedirect_data();
|
||||||
void ioHttpRedirect();
|
void ioHttpRedirect();
|
||||||
void ioHttpRedirectFromLocalToRemote();
|
void ioHttpRedirectFromLocalToRemote();
|
||||||
void ioHttpRedirectPost_data();
|
void ioHttpRedirectPostPut_data();
|
||||||
void ioHttpRedirectPost();
|
void ioHttpRedirectPostPut();
|
||||||
void ioHttpRedirectMultipartPost_data();
|
void ioHttpRedirectMultipartPost_data();
|
||||||
void ioHttpRedirectMultipartPost();
|
void ioHttpRedirectMultipartPost();
|
||||||
|
void ioHttpRedirectDelete();
|
||||||
|
void ioHttpRedirectCustom();
|
||||||
#ifndef QT_NO_SSL
|
#ifndef QT_NO_SSL
|
||||||
void putWithServerClosingConnectionImmediately();
|
void putWithServerClosingConnectionImmediately();
|
||||||
#endif
|
#endif
|
||||||
@ -546,7 +548,7 @@ static void setupSslServer(QSslSocket* serverSocket)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Does not work for PUT! Limited support for POST.
|
// Limited support for POST and PUT.
|
||||||
class MiniHttpServer: public QTcpServer
|
class MiniHttpServer: public QTcpServer
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@ -678,7 +680,7 @@ public slots:
|
|||||||
|
|
||||||
if (doubleEndlPos != -1) {
|
if (doubleEndlPos != -1) {
|
||||||
const int endOfHeader = doubleEndlPos + 4;
|
const int endOfHeader = doubleEndlPos + 4;
|
||||||
hasContent = receivedData.startsWith("POST");
|
hasContent = receivedData.startsWith("POST") || receivedData.startsWith("PUT");
|
||||||
if (hasContent && contentLength == 0)
|
if (hasContent && contentLength == 0)
|
||||||
parseContentLength();
|
parseContentLength();
|
||||||
contentRead = receivedData.length() - endOfHeader;
|
contentRead = receivedData.length() - endOfHeader;
|
||||||
@ -8546,37 +8548,46 @@ void tst_QNetworkReply::ioHttpRedirectFromLocalToRemote()
|
|||||||
QCOMPARE(reply->readAll(), reference.readAll());
|
QCOMPARE(reply->readAll(), reference.readAll());
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_QNetworkReply::ioHttpRedirectPost_data()
|
void tst_QNetworkReply::ioHttpRedirectPostPut_data()
|
||||||
{
|
{
|
||||||
|
QTest::addColumn<bool>("usePost");
|
||||||
QTest::addColumn<QString>("status");
|
QTest::addColumn<QString>("status");
|
||||||
QTest::addColumn<QByteArray>("data");
|
QTest::addColumn<QByteArray>("data");
|
||||||
QTest::addColumn<QString>("contentType");
|
QTest::addColumn<QString>("contentType");
|
||||||
|
|
||||||
QByteArray data;
|
QByteArray data;
|
||||||
data = "hello world";
|
data = "hello world";
|
||||||
QTest::addRow("307") << "307 Temporary Redirect" << data << "text/plain";
|
QTest::addRow("post-307") << true << "307 Temporary Redirect" << data << "text/plain";
|
||||||
|
QTest::addRow("put-307") << false << "307 Temporary Redirect" << data << "text/plain";
|
||||||
QString permanentRedirect = "308 Permanent Redirect";
|
QString permanentRedirect = "308 Permanent Redirect";
|
||||||
QTest::addRow("308") << permanentRedirect << data << "text/plain";
|
QTest::addRow("post-308") << true << permanentRedirect << data << "text/plain";
|
||||||
|
QTest::addRow("put-308") << false << permanentRedirect << data << "text/plain";
|
||||||
|
|
||||||
// Some data from ::putToFile_data
|
// Some data from ::putToFile_data
|
||||||
data = "";
|
data = "";
|
||||||
QTest::newRow("empty") << permanentRedirect << data << "application/octet-stream";
|
QTest::newRow("post-empty") << true << permanentRedirect << data << "application/octet-stream";
|
||||||
|
QTest::newRow("put-empty") << false << permanentRedirect << data << "application/octet-stream";
|
||||||
|
|
||||||
data = QByteArray("abcd\0\1\2\abcd",12);
|
data = QByteArray("abcd\0\1\2\abcd",12);
|
||||||
QTest::newRow("with-nul") << permanentRedirect << data << "application/octet-stream";
|
QTest::newRow("post-with-nul") << true << permanentRedirect << data << "application/octet-stream";
|
||||||
|
QTest::newRow("put-with-nul") << false << permanentRedirect << data << "application/octet-stream";
|
||||||
|
|
||||||
data = QByteArray(4097, '\4');
|
data = QByteArray(4097, '\4');
|
||||||
QTest::newRow("4k+1") << permanentRedirect << data << "application/octet-stream";
|
QTest::newRow("post-4k+1") << true << permanentRedirect << data << "application/octet-stream";
|
||||||
|
QTest::newRow("put-4k+1") << false << permanentRedirect << data << "application/octet-stream";
|
||||||
|
|
||||||
data = QByteArray(128*1024+1, '\177');
|
data = QByteArray(128*1024+1, '\177');
|
||||||
QTest::newRow("128k+1") << permanentRedirect << data << "application/octet-stream";
|
QTest::newRow("post-128k+1") << true << permanentRedirect << data << "application/octet-stream";
|
||||||
|
QTest::newRow("put-128k+1") << false << permanentRedirect << data << "application/octet-stream";
|
||||||
|
|
||||||
data = QByteArray(2*1024*1024+1, '\177');
|
data = QByteArray(2*1024*1024+1, '\177');
|
||||||
QTest::newRow("2MB+1") << permanentRedirect << data << "application/octet-stream";
|
QTest::newRow("post-2MB+1") << true << permanentRedirect << data << "application/octet-stream";
|
||||||
|
QTest::newRow("put-2MB+1") << false << permanentRedirect << data << "application/octet-stream";
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_QNetworkReply::ioHttpRedirectPost()
|
void tst_QNetworkReply::ioHttpRedirectPostPut()
|
||||||
{
|
{
|
||||||
|
QFETCH(bool, usePost);
|
||||||
QFETCH(QString, status);
|
QFETCH(QString, status);
|
||||||
QFETCH(QByteArray, data);
|
QFETCH(QByteArray, data);
|
||||||
QFETCH(QString, contentType);
|
QFETCH(QString, contentType);
|
||||||
@ -8595,7 +8606,7 @@ void tst_QNetworkReply::ioHttpRedirectPost()
|
|||||||
auto oldRedirectPolicy = manager.redirectPolicy();
|
auto oldRedirectPolicy = manager.redirectPolicy();
|
||||||
manager.setRedirectPolicy(QNetworkRequest::RedirectPolicy::NoLessSafeRedirectPolicy);
|
manager.setRedirectPolicy(QNetworkRequest::RedirectPolicy::NoLessSafeRedirectPolicy);
|
||||||
|
|
||||||
QNetworkReplyPtr reply(manager.post(request, data));
|
QNetworkReplyPtr reply(usePost ? manager.post(request, data) : manager.put(request, data));
|
||||||
// Restore previous policy:
|
// Restore previous policy:
|
||||||
manager.setRedirectPolicy(oldRedirectPolicy);
|
manager.setRedirectPolicy(oldRedirectPolicy);
|
||||||
|
|
||||||
@ -8664,6 +8675,50 @@ void tst_QNetworkReply::ioHttpRedirectMultipartPost()
|
|||||||
QCOMPARE(replyData, expectedReplyData);
|
QCOMPARE(replyData, expectedReplyData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tst_QNetworkReply::ioHttpRedirectDelete()
|
||||||
|
{
|
||||||
|
MiniHttpServer target(httpEmpty200Response, false);
|
||||||
|
QUrl targetUrl("http://localhost/");
|
||||||
|
targetUrl.setPort(target.serverPort());
|
||||||
|
|
||||||
|
QString redirectReply = tempRedirectReplyStr().arg(targetUrl.toString());
|
||||||
|
MiniHttpServer redirectServer(redirectReply.toLatin1());
|
||||||
|
QUrl url("http://localhost/");
|
||||||
|
url.setPort(redirectServer.serverPort());
|
||||||
|
QNetworkRequest request(url);
|
||||||
|
auto oldRedirectPolicy = manager.redirectPolicy();
|
||||||
|
manager.setRedirectPolicy(QNetworkRequest::RedirectPolicy::NoLessSafeRedirectPolicy);
|
||||||
|
|
||||||
|
QNetworkReplyPtr reply(manager.deleteResource(request));
|
||||||
|
// Restore previous policy:
|
||||||
|
manager.setRedirectPolicy(oldRedirectPolicy);
|
||||||
|
|
||||||
|
QCOMPARE(waitForFinish(reply), int(Success));
|
||||||
|
QVERIFY2(target.receivedData.startsWith("DELETE"), "Target server called with the wrong method");
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_QNetworkReply::ioHttpRedirectCustom()
|
||||||
|
{
|
||||||
|
MiniHttpServer target(httpEmpty200Response, false);
|
||||||
|
QUrl targetUrl("http://localhost/");
|
||||||
|
targetUrl.setPort(target.serverPort());
|
||||||
|
|
||||||
|
QString redirectReply = tempRedirectReplyStr().arg(targetUrl.toString());
|
||||||
|
MiniHttpServer redirectServer(redirectReply.toLatin1());
|
||||||
|
QUrl url("http://localhost/");
|
||||||
|
url.setPort(redirectServer.serverPort());
|
||||||
|
QNetworkRequest request(url);
|
||||||
|
auto oldRedirectPolicy = manager.redirectPolicy();
|
||||||
|
manager.setRedirectPolicy(QNetworkRequest::RedirectPolicy::NoLessSafeRedirectPolicy);
|
||||||
|
|
||||||
|
QNetworkReplyPtr reply(manager.sendCustomRequest(request, QByteArrayLiteral("CUSTOM")));
|
||||||
|
// Restore previous policy:
|
||||||
|
manager.setRedirectPolicy(oldRedirectPolicy);
|
||||||
|
|
||||||
|
QCOMPARE(waitForFinish(reply), int(Success));
|
||||||
|
QVERIFY2(target.receivedData.startsWith("CUSTOM"), "Target server called with the wrong method");
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef QT_NO_SSL
|
#ifndef QT_NO_SSL
|
||||||
|
|
||||||
class PutWithServerClosingConnectionImmediatelyHandler: public QObject
|
class PutWithServerClosingConnectionImmediatelyHandler: public QObject
|
||||||
|
Loading…
x
Reference in New Issue
Block a user