summaryrefslogtreecommitdiffstats
path: root/tests/auto/network/access/http2/http2srv.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/network/access/http2/http2srv.cpp')
-rw-r--r--tests/auto/network/access/http2/http2srv.cpp112
1 files changed, 70 insertions, 42 deletions
diff --git a/tests/auto/network/access/http2/http2srv.cpp b/tests/auto/network/access/http2/http2srv.cpp
index 932b11fbb6..7c5ccc8ff5 100644
--- a/tests/auto/network/access/http2/http2srv.cpp
+++ b/tests/auto/network/access/http2/http2srv.cpp
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the test suite of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QTest>
@@ -109,6 +84,12 @@ Http2Server::~Http2Server()
{
}
+void Http2Server::setInformationalStatusCode(int code)
+{
+ if (code == 100 || (102 <= code && code <= 199))
+ informationalStatusCode = code;
+}
+
void Http2Server::enablePushPromise(bool pushEnabled, const QByteArray &path)
{
pushPromiseEnabled = pushEnabled;
@@ -130,6 +111,23 @@ void Http2Server::setAuthenticationHeader(const QByteArray &authentication)
authenticationHeader = authentication;
}
+void Http2Server::setAuthenticationRequired(bool enable)
+{
+ Q_ASSERT(!enable || authenticationHeader.isEmpty());
+ authenticationRequired = enable;
+}
+
+void Http2Server::setRedirect(const QByteArray &url, int count)
+{
+ redirectUrl = url;
+ redirectCount = count;
+}
+
+void Http2Server::setSendTrailingHEADERS(bool enable)
+{
+ sendTrailingHEADERS = enable;
+}
+
void Http2Server::emulateGOAWAY(int timeout)
{
Q_ASSERT(timeout >= 0);
@@ -267,9 +265,20 @@ void Http2Server::sendDATA(quint32 streamID, quint32 windowSize)
return;
if (last) {
- writer.start(FrameType::DATA, FrameFlag::END_STREAM, streamID);
- writer.setPayloadSize(0);
- writer.write(*socket);
+ if (sendTrailingHEADERS) {
+ writer.start(FrameType::HEADERS,
+ FrameFlag::PRIORITY | FrameFlag::END_HEADERS | FrameFlag::END_STREAM, streamID);
+ const quint32 maxFrameSize(clientSetting(Settings::MAX_FRAME_SIZE_ID,
+ Http2::maxPayloadSize));
+ // 5 bytes for PRIORITY data:
+ writer.append(quint32(0)); // streamID 0 (32-bit)
+ writer.append(quint8(0)); // + weight 0 (8-bit)
+ writer.writeHEADERS(*socket, maxFrameSize);
+ } else {
+ writer.start(FrameType::DATA, FrameFlag::END_STREAM, streamID);
+ writer.setPayloadSize(0);
+ writer.write(*socket);
+ }
suspendedStreams.erase(it);
activeRequests.erase(streamID);
@@ -318,11 +327,11 @@ void Http2Server::incomingConnection(qintptr socketDescriptor)
sslSocket->setProtocol(QSsl::TlsV1_2OrLater);
connect(sslSocket, SIGNAL(sslErrors(QList<QSslError>)),
this, SLOT(ignoreErrorSlot()));
- QFile file(SRCDIR "certs/fluke.key");
+ QFile file(QT_TESTCASE_SOURCEDIR "/certs/fluke.key");
file.open(QIODevice::ReadOnly);
QSslKey key(file.readAll(), QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey);
sslSocket->setPrivateKey(key);
- auto localCert = QSslCertificate::fromPath(SRCDIR "certs/fluke.cert");
+ auto localCert = QSslCertificate::fromPath(QT_TESTCASE_SOURCEDIR "/certs/fluke.cert");
sslSocket->setLocalCertificateChain(localCert);
sslSocket->setSocketDescriptor(socketDescriptor, QAbstractSocket::ConnectedState);
// Stop listening.
@@ -380,16 +389,12 @@ bool Http2Server::verifyProtocolUpgradeRequest()
bool settingsOk = false;
QHttpNetworkReplyPrivate *firstRequestReader = protocolUpgradeHandler->d_func();
+ const auto headers = firstRequestReader->headers();
// That's how we append them, that's what I expect to find:
- for (const auto &header : firstRequestReader->fields) {
- if (header.first == "Connection")
- connectionOk = header.second.contains("Upgrade, HTTP2-Settings");
- else if (header.first == "Upgrade")
- upgradeOk = header.second.contains("h2c");
- else if (header.first == "HTTP2-Settings")
- settingsOk = true;
- }
+ connectionOk = headers.combinedValue(QHttpHeaders::WellKnownHeader::Connection).contains("Upgrade, HTTP2-Settings");
+ upgradeOk = headers.combinedValue(QHttpHeaders::WellKnownHeader::Upgrade).contains("h2c");
+ settingsOk = headers.contains("HTTP2-Settings");
return connectionOk && upgradeOk && settingsOk;
}
@@ -838,6 +843,25 @@ void Http2Server::sendResponse(quint32 streamID, bool emptyBody)
// Now we'll continue with _normal_ response.
}
+ // Create a header with an informational status code and some random header
+ // fields. The setter ensures that the value is 100 or is between 102 and 199
+ // (inclusive) if set - otherwise it is 0
+
+ if (informationalStatusCode > 0) {
+ writer.start(FrameType::HEADERS, FrameFlag::END_HEADERS, streamID);
+
+ HttpHeader informationalHeader;
+ informationalHeader.push_back({":status", QByteArray::number(informationalStatusCode)});
+ informationalHeader.push_back(HeaderField("a_random_header_field", "it_will_be_dropped"));
+ informationalHeader.push_back(HeaderField("another_random_header_field", "drop_this_too"));
+
+ HPack::BitOStream ostream(writer.outboundFrame().buffer);
+ const bool result = encoder.encodeResponse(ostream, informationalHeader);
+ Q_ASSERT(result);
+
+ writer.writeHEADERS(*socket, maxFrameSize);
+ }
+
writer.start(FrameType::HEADERS, FrameFlag::END_HEADERS, streamID);
if (emptyBody)
writer.addFlag(FrameFlag::END_STREAM);
@@ -860,11 +884,15 @@ void Http2Server::sendResponse(quint32 streamID, bool emptyBody)
const QString url("%1://localhost:%2/");
header.push_back({"location", url.arg(isClearText() ? QStringLiteral("http") : QStringLiteral("https"),
QString::number(targetPort)).toLatin1()});
-
+ } else if (redirectCount > 0) { // Not redirecting while reading, unlike above
+ --redirectCount;
+ header.push_back({":status", "308"});
+ header.push_back({"location", redirectUrl});
} else if (!authenticationHeader.isEmpty() && !hasAuth) {
header.push_back({ ":status", "401" });
header.push_back(HPack::HeaderField("www-authenticate", authenticationHeader));
- authenticationHeader.clear();
+ } else if (authenticationRequired) {
+ header.push_back({ ":status", "401" });
} else {
header.push_back({":status", "200"});
}