diff options
author | Tomasz Duda <tomaszduda23@gmail.com> | 2012-09-06 22:15:26 +0200 |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2012-09-18 00:59:08 +0200 |
commit | 60f4fc8b706db9cbeacd5dc4886a7aa347daafc0 (patch) | |
tree | 6a6ed9f8a0e83c589fbb4ddf28bba3573fa70332 /tests/auto/network/access/qnetworkreply | |
parent | 58e2b9c01b31cef8a0fa263de3d984c22f1d7ca7 (diff) |
HTTP header may be damaged - fix, unit test
"HTTP/1.1 100 CONTINUE\r\n"
If the header from a server is splitted between two packets
the first packet contains "HTTP/1.1 100" and the second one
contains " CONTINUE\r\n", one space (0x20) is skipped. After
processing the line looks in this way "HTTP/1.1 100CONTINUE".
QHttpNetworkReplyPrivate::readStatus(QAbstractSocket *socket)
is called twice, if a http header is splitted as above.
The function always removes whitespace from the beginning of a packet,
even if it is the second part of a http header.
QHttpNetworkReply returns QNetworkReply::RemoteHostClosedError
due to damaged http header during processing.
Improvement of unit test.
Task-number: QTBUG-27161
Change-Id: Ifc2949f62473209b4032185effbf5078b4130cda
Reviewed-by: Qt Doc Bot <qt_docbot@qt-project.org>
Reviewed-by: Shane Kearns <shane.kearns@accenture.com>
Diffstat (limited to 'tests/auto/network/access/qnetworkreply')
-rw-r--r-- | tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp | 74 |
1 files changed, 74 insertions, 0 deletions
diff --git a/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp b/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp index 968f25fcf3..d6de1f98e5 100644 --- a/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp +++ b/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp @@ -380,6 +380,9 @@ private Q_SLOTS: void qtbug18232gzipContentLengthZero(); void qtbug22660gzipNoContentLengthEmptyContent(); + void qtbug27161httpHeaderMayBeDamaged_data(); + void qtbug27161httpHeaderMayBeDamaged(); + void synchronousRequest_data(); void synchronousRequest(); #ifndef QT_NO_SSL @@ -6445,6 +6448,77 @@ void tst_QNetworkReply::qtbug22660gzipNoContentLengthEmptyContent() QCOMPARE(reply->readAll(), QByteArray()); } +class QtBug27161Helper : public QObject { + Q_OBJECT +public: + QtBug27161Helper(MiniHttpServer & server, const QByteArray & data): + m_server(server), + m_data(data) + { + connect(&m_server, SIGNAL(newConnection()), this, SLOT(newConnectionSlot())); + } +public slots: + void newConnectionSlot(){ + connect(m_server.client, SIGNAL(bytesWritten(qint64)), this, SLOT(bytesWrittenSlot())); + } + + void bytesWrittenSlot(){ + disconnect(m_server.client, SIGNAL(bytesWritten(qint64)), this, SLOT(bytesWrittenSlot())); + m_Timer.singleShot(100, this, SLOT(timeoutSlot())); + } + + void timeoutSlot(){ + m_server.doClose = true; + // we need to emulate the bytesWrittenSlot call if the data is empty. + if (m_data.size() == 0) + QMetaObject::invokeMethod(&m_server, "bytesWrittenSlot", Qt::QueuedConnection); + else + m_server.client->write(m_data); + } + +private: + MiniHttpServer & m_server; + QByteArray m_data; + QTimer m_Timer; +}; + +void tst_QNetworkReply::qtbug27161httpHeaderMayBeDamaged_data(){ + QByteArray response("HTTP/1.0 200 OK\r\nServer: bogus\r\nContent-Length: 3\r\n\r\nABC"); + QTest::addColumn<QByteArray>("firstPacket"); + QTest::addColumn<QByteArray>("secondPacket"); + + for (int i = 1; i < response.size(); i++){ + QByteArray dataTag("Iteration: "); + dataTag.append(QByteArray::number(i - 1)); + QTest::newRow(dataTag.constData()) << response.left(i) << response.mid(i); + } +} + +/* + * Purpose of this test is to check whether a content from server is parsed correctly + * if it is splitted into two parts. + */ +void tst_QNetworkReply::qtbug27161httpHeaderMayBeDamaged(){ + QFETCH(QByteArray, firstPacket); + QFETCH(QByteArray, secondPacket); + MiniHttpServer server(firstPacket); + server.doClose = false; + QtBug27161Helper helper(server, secondPacket); + + QNetworkRequest request(QUrl("http://localhost:" + QString::number(server.serverPort()))); + QNetworkReplyPtr reply(manager.get(request)); + + QVERIFY(waitForFinish(reply) == Success); + + QVERIFY(reply->isFinished()); + QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->size(), qint64(3)); + QCOMPARE(reply->header(QNetworkRequest::ContentLengthHeader).toLongLong(), qint64(3)); + QCOMPARE(reply->rawHeader("Content-length"), QByteArray("3")); + QCOMPARE(reply->rawHeader("Server"), QByteArray("bogus")); + QCOMPARE(reply->readAll(), QByteArray("ABC")); +} + void tst_QNetworkReply::synchronousRequest_data() { QTest::addColumn<QUrl>("url"); |