summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.qmake.conf2
-rw-r--r--src/websockets/qwebsocket.cpp29
-rw-r--r--src/websockets/qwebsocket.h3
-rw-r--r--src/websockets/qwebsocket_p.cpp53
-rw-r--r--src/websockets/qwebsocket_p.h11
-rw-r--r--tests/auto/websockets/dataprocessor/tst_dataprocessor.cpp2
-rw-r--r--tests/auto/websockets/qwebsocket/tst_qwebsocket.cpp46
7 files changed, 109 insertions, 37 deletions
diff --git a/.qmake.conf b/.qmake.conf
index 2ea3e52..924ada9 100644
--- a/.qmake.conf
+++ b/.qmake.conf
@@ -3,4 +3,4 @@ load(qt_build_config)
CONFIG += qt_example_installs
CONFIG += warning_clean
-MODULE_VERSION = 5.5.1
+MODULE_VERSION = 5.6.0
diff --git a/src/websockets/qwebsocket.cpp b/src/websockets/qwebsocket.cpp
index a77f23c..3635003 100644
--- a/src/websockets/qwebsocket.cpp
+++ b/src/websockets/qwebsocket.cpp
@@ -389,7 +389,22 @@ void QWebSocket::close(QWebSocketProtocol::CloseCode closeCode, const QString &r
void QWebSocket::open(const QUrl &url)
{
Q_D(QWebSocket);
- d->open(url, true);
+ QNetworkRequest request(url);
+ d->open(request, true);
+}
+
+/*!
+ \brief Opens a WebSocket connection using the given \a request.
+ \since 5.6
+
+ The \a request url will be used to open the WebSocket connection.
+ Headers present in the request will be sent to the server in the upgrade request,
+ together with the ones needed for the websocket handshake.
+ */
+void QWebSocket::open(const QNetworkRequest &request)
+{
+ Q_D(QWebSocket);
+ d->open(request, true);
}
/*!
@@ -512,7 +527,17 @@ QString QWebSocket::resourceName() const
QUrl QWebSocket::requestUrl() const
{
Q_D(const QWebSocket);
- return d->requestUrl();
+ return d->request().url();
+}
+
+/*!
+ \brief Returns the request that was or will be used to open this socket.
+ \since 5.6
+ */
+QNetworkRequest QWebSocket::request() const
+{
+ Q_D(const QWebSocket);
+ return d->request();
}
/*!
diff --git a/src/websockets/qwebsocket.h b/src/websockets/qwebsocket.h
index 9fdc6eb..7ee4bc6 100644
--- a/src/websockets/qwebsocket.h
+++ b/src/websockets/qwebsocket.h
@@ -36,6 +36,7 @@
#include <QtCore/QUrl>
#include <QtNetwork/QAbstractSocket>
+#include <QtNetwork/QNetworkRequest>
#ifndef QT_NO_NETWORKPROXY
#include <QtNetwork/QNetworkProxy>
#endif
@@ -92,6 +93,7 @@ public:
QWebSocketProtocol::Version version() const;
QString resourceName() const;
QUrl requestUrl() const;
+ QNetworkRequest request() const;
QString origin() const;
QWebSocketProtocol::CloseCode closeCode() const;
QString closeReason() const;
@@ -109,6 +111,7 @@ public Q_SLOTS:
void close(QWebSocketProtocol::CloseCode closeCode = QWebSocketProtocol::CloseCodeNormal,
const QString &reason = QString());
void open(const QUrl &url);
+ void open(const QNetworkRequest &request);
void ping(const QByteArray &payload = QByteArray());
#ifndef QT_NO_SSL
void ignoreSslErrors();
diff --git a/src/websockets/qwebsocket_p.cpp b/src/websockets/qwebsocket_p.cpp
index 174214c..b9504f8 100644
--- a/src/websockets/qwebsocket_p.cpp
+++ b/src/websockets/qwebsocket_p.cpp
@@ -88,7 +88,7 @@ QWebSocketPrivate::QWebSocketPrivate(const QString &origin, QWebSocketProtocol::
m_errorString(),
m_version(version),
m_resourceName(),
- m_requestUrl(),
+ m_request(),
m_origin(origin),
m_protocol(),
m_extension(),
@@ -121,7 +121,7 @@ QWebSocketPrivate::QWebSocketPrivate(QTcpSocket *pTcpSocket, QWebSocketProtocol:
m_errorString(pTcpSocket->errorString()),
m_version(version),
m_resourceName(),
- m_requestUrl(),
+ m_request(),
m_origin(),
m_protocol(),
m_extension(),
@@ -281,9 +281,15 @@ QWebSocket *QWebSocketPrivate::upgradeFrom(QTcpSocket *pTcpSocket,
{
QWebSocket *pWebSocket = new QWebSocket(pTcpSocket, response.acceptedVersion(), parent);
if (Q_LIKELY(pWebSocket)) {
+ QNetworkRequest netRequest(request.requestUrl());
+ QMapIterator<QString, QString> headerIter(request.headers());
+ while (headerIter.hasNext()) {
+ headerIter.next();
+ netRequest.setRawHeader(headerIter.key().toLatin1(), headerIter.value().toLatin1());
+ }
pWebSocket->d_func()->setExtension(response.acceptedExtension());
pWebSocket->d_func()->setOrigin(request.origin());
- pWebSocket->d_func()->setRequestUrl(request.requestUrl());
+ pWebSocket->d_func()->setRequest(netRequest);
pWebSocket->d_func()->setProtocol(response.acceptedProtocol());
pWebSocket->d_func()->setResourceName(request.requestUrl().toString(QUrl::RemoveUserInfo));
//a server should not send masked frames
@@ -330,12 +336,13 @@ void QWebSocketPrivate::close(QWebSocketProtocol::CloseCode closeCode, QString r
/*!
\internal
*/
-void QWebSocketPrivate::open(const QUrl &url, bool mask)
+void QWebSocketPrivate::open(const QNetworkRequest &request, bool mask)
{
//just delete the old socket for the moment;
//later, we can add more 'intelligent' handling by looking at the URL
//m_pSocket.reset();
Q_Q(QWebSocket);
+ QUrl url = request.url();
if (!url.isValid() || url.toString().contains(QStringLiteral("\r\n"))) {
setErrorString(QWebSocket::tr("Invalid URL."));
Q_EMIT q->error(QAbstractSocket::ConnectionRefusedError);
@@ -352,11 +359,11 @@ void QWebSocketPrivate::open(const QUrl &url, bool mask)
m_isClosingHandshakeReceived = false;
m_isClosingHandshakeSent = false;
- setRequestUrl(url);
+ setRequest(request);
QString resourceName = url.path(QUrl::FullyEncoded);
// Check for encoded \r\n
if (resourceName.contains(QStringLiteral("%0D%0A"))) {
- setRequestUrl(QUrl()); //clear requestUrl
+ setRequest(QNetworkRequest()); //clear request
setErrorString(QWebSocket::tr("Invalid resource name."));
Q_EMIT q->error(QAbstractSocket::ConnectionRefusedError);
return;
@@ -479,10 +486,10 @@ void QWebSocketPrivate::setResourceName(const QString &resourceName)
/*!
\internal
*/
-void QWebSocketPrivate::setRequestUrl(const QUrl &requestUrl)
+void QWebSocketPrivate::setRequest(const QNetworkRequest &request)
{
- if (m_requestUrl != requestUrl)
- m_requestUrl = requestUrl;
+ if (m_request != request)
+ m_request = request;
}
/*!
@@ -620,9 +627,9 @@ QString QWebSocketPrivate::resourceName() const
/*!
\internal
*/
-QUrl QWebSocketPrivate::requestUrl() const
+QNetworkRequest QWebSocketPrivate::request() const
{
- return m_requestUrl;
+ return m_request;
}
/*!
@@ -1039,22 +1046,29 @@ void QWebSocketPrivate::processStateChanged(QAbstractSocket::SocketState socketS
Q_Q(QWebSocket);
QAbstractSocket::SocketState webSocketState = this->state();
int port = 80;
- if (m_requestUrl.scheme() == QStringLiteral("wss"))
+ if (m_request.url().scheme() == QStringLiteral("wss"))
port = 443;
switch (socketState) {
case QAbstractSocket::ConnectedState:
if (webSocketState == QAbstractSocket::ConnectingState) {
m_key = generateKey();
+
+ QList<QPair<QString, QString> > headers;
+ foreach (const QByteArray &key, m_request.rawHeaderList())
+ headers << qMakePair(QString::fromLatin1(key),
+ QString::fromLatin1(m_request.rawHeader(key)));
+
const QString handshake =
createHandShakeRequest(m_resourceName,
- m_requestUrl.host()
+ m_request.url().host()
% QStringLiteral(":")
- % QString::number(m_requestUrl.port(port)),
+ % QString::number(m_request.url().port(port)),
origin(),
QString(),
QString(),
- m_key);
+ m_key,
+ headers);
if (handshake.isEmpty()) {
m_pSocket->abort();
Q_EMIT q->error(QAbstractSocket::ConnectionRefusedError);
@@ -1153,7 +1167,8 @@ QString QWebSocketPrivate::createHandShakeRequest(QString resourceName,
QString origin,
QString extensions,
QString protocols,
- QByteArray key)
+ QByteArray key,
+ QList<QPair<QString, QString> > headers)
{
QStringList handshakeRequest;
if (resourceName.contains(QStringLiteral("\r\n"))) {
@@ -1195,6 +1210,12 @@ QString QWebSocketPrivate::createHandShakeRequest(QString resourceName,
handshakeRequest << QStringLiteral("Sec-WebSocket-Extensions: ") % extensions;
if (protocols.length() > 0)
handshakeRequest << QStringLiteral("Sec-WebSocket-Protocol: ") % protocols;
+
+ QListIterator<QPair<QString, QString> > headerIter(headers);
+ while (headerIter.hasNext()) {
+ const QPair<QString,QString> &header = headerIter.next();
+ handshakeRequest << header.first % QStringLiteral(": ") % header.second;
+ }
handshakeRequest << QStringLiteral("\r\n");
return handshakeRequest.join(QStringLiteral("\r\n"));
diff --git a/src/websockets/qwebsocket_p.h b/src/websockets/qwebsocket_p.h
index 7379c51..260e8e8 100644
--- a/src/websockets/qwebsocket_p.h
+++ b/src/websockets/qwebsocket_p.h
@@ -126,7 +126,7 @@ public:
QWebSocketProtocol::Version version() const;
QString resourceName() const;
- QUrl requestUrl() const;
+ QNetworkRequest request() const;
QString origin() const;
QString protocol() const;
QString extension() const;
@@ -144,7 +144,7 @@ public:
#endif
void close(QWebSocketProtocol::CloseCode closeCode, QString reason);
- void open(const QUrl &url, bool mask);
+ void open(const QNetworkRequest &request, bool mask);
void ping(const QByteArray &payload);
QWebSocket * const q_ptr;
@@ -154,7 +154,7 @@ private:
QWebSocket *pWebSocket);
void setVersion(QWebSocketProtocol::Version version);
void setResourceName(const QString &resourceName);
- void setRequestUrl(const QUrl &requestUrl);
+ void setRequest(const QNetworkRequest &request);
void setOrigin(const QString &origin);
void setProtocol(const QString &protocol);
void setExtension(const QString &extension);
@@ -184,7 +184,8 @@ private:
QString origin,
QString extensions,
QString protocols,
- QByteArray key);
+ QByteArray key,
+ QList<QPair<QString, QString> > headers);
static QWebSocket *upgradeFrom(QTcpSocket *tcpSocket,
const QWebSocketHandshakeRequest &request,
@@ -201,7 +202,7 @@ private:
QWebSocketProtocol::Version m_version;
QUrl m_resource;
QString m_resourceName;
- QUrl m_requestUrl;
+ QNetworkRequest m_request;
QString m_origin;
QString m_protocol;
QString m_extension;
diff --git a/tests/auto/websockets/dataprocessor/tst_dataprocessor.cpp b/tests/auto/websockets/dataprocessor/tst_dataprocessor.cpp
index 660d8eb..c1dd9a1 100644
--- a/tests/auto/websockets/dataprocessor/tst_dataprocessor.cpp
+++ b/tests/auto/websockets/dataprocessor/tst_dataprocessor.cpp
@@ -329,7 +329,7 @@ void tst_DataProcessor::goodTextFrame_data()
//error C2308: concatenating mismatched strings
QTest::newRow((QStringLiteral("Text frame containing Hello-") +
QStringLiteral("\xC2\xB5\x40\xC3\x9F\xC3\xB6\xC3\xA4\xC3\xBC\xC3\xA0") +
- QStringLiteral("\xC3\xA1-UTF-8!!")).toLatin1().constData())
+ QStringLiteral("\xC3\xA1-UTF-8!!")).toUtf8().constData())
<< QByteArray::fromHex("48656c6c6f2dc2b540c39fc3b6c3a4c3bcc3a0c3a12d5554462d382121")
<< 22;
}
diff --git a/tests/auto/websockets/qwebsocket/tst_qwebsocket.cpp b/tests/auto/websockets/qwebsocket/tst_qwebsocket.cpp
index aca25d0..f993f84 100644
--- a/tests/auto/websockets/qwebsocket/tst_qwebsocket.cpp
+++ b/tests/auto/websockets/qwebsocket/tst_qwebsocket.cpp
@@ -52,6 +52,7 @@ public:
Q_SIGNALS:
void newConnection(QUrl requestUrl);
+ void newConnection(QNetworkRequest request);
private Q_SLOTS:
void onNewConnection();
@@ -87,6 +88,7 @@ void EchoServer::onNewConnection()
QWebSocket *pSocket = m_pWebSocketServer->nextPendingConnection();
Q_EMIT newConnection(pSocket->requestUrl());
+ Q_EMIT newConnection(pSocket->request());
connect(pSocket, SIGNAL(textMessageReceived(QString)), this, SLOT(processTextMessage(QString)));
connect(pSocket, SIGNAL(binaryMessageReceived(QByteArray)), this, SLOT(processBinaryMessage(QByteArray)));
@@ -140,6 +142,7 @@ private Q_SLOTS:
void tst_sendTextMessage();
void tst_sendBinaryMessage();
void tst_errorString();
+ void tst_openRequest();
#ifndef QT_NO_NETWORKPROXY
void tst_setProxy();
#endif
@@ -425,11 +428,9 @@ void tst_QWebSocket::tst_sendTextMessage()
socket.open(url);
- if (socketConnectedSpy.count() == 0)
- QVERIFY(socketConnectedSpy.wait(500));
+ QTRY_COMPARE(socketConnectedSpy.count(), 1);
QCOMPARE(socketError.count(), 0);
QCOMPARE(socket.state(), QAbstractSocket::ConnectedState);
- QCOMPARE(serverConnectedSpy.count(), 1);
QList<QVariant> arguments = serverConnectedSpy.takeFirst();
QUrl urlConnected = arguments.at(0).toUrl();
QCOMPARE(urlConnected, url);
@@ -461,8 +462,7 @@ void tst_QWebSocket::tst_sendTextMessage()
socket.open(QUrl(QStringLiteral("ws://") + echoServer.hostAddress().toString() +
QStringLiteral(":") + QString::number(echoServer.port())));
- if (socketConnectedSpy.count() == 0)
- QVERIFY(socketConnectedSpy.wait(500));
+ QTRY_COMPARE(socketConnectedSpy.count(), 1);
QCOMPARE(socket.state(), QAbstractSocket::ConnectedState);
socket.sendTextMessage(QStringLiteral("Hello world!"));
@@ -506,8 +506,7 @@ void tst_QWebSocket::tst_sendBinaryMessage()
socket.open(QUrl(QStringLiteral("ws://") + echoServer.hostAddress().toString() +
QStringLiteral(":") + QString::number(echoServer.port())));
- if (socketConnectedSpy.count() == 0)
- QVERIFY(socketConnectedSpy.wait(500));
+ QTRY_COMPARE(socketConnectedSpy.count(), 1);
QCOMPARE(socket.state(), QAbstractSocket::ConnectedState);
socket.sendBinaryMessage(QByteArrayLiteral("Hello world!"));
@@ -537,8 +536,7 @@ void tst_QWebSocket::tst_sendBinaryMessage()
socket.open(QUrl(QStringLiteral("ws://") + echoServer.hostAddress().toString() +
QStringLiteral(":") + QString::number(echoServer.port())));
- if (socketConnectedSpy.count() == 0)
- QVERIFY(socketConnectedSpy.wait(500));
+ QTRY_COMPARE(socketConnectedSpy.count(), 1);
QCOMPARE(socket.state(), QAbstractSocket::ConnectedState);
socket.sendBinaryMessage(QByteArrayLiteral("Hello world!"));
@@ -571,9 +569,7 @@ void tst_QWebSocket::tst_errorString()
socket.open(QUrl(QStringLiteral("ws://someserver.on.mars:9999")));
- if (errorSpy.count() == 0)
- errorSpy.wait(500);
- QCOMPARE(errorSpy.count(), 1);
+ QTRY_COMPARE(errorSpy.count(), 1);
QList<QVariant> arguments = errorSpy.takeFirst();
QAbstractSocket::SocketError socketError =
qvariant_cast<QAbstractSocket::SocketError>(arguments.at(0));
@@ -581,6 +577,32 @@ void tst_QWebSocket::tst_errorString()
QCOMPARE(socket.errorString(), QStringLiteral("Host not found"));
}
+void tst_QWebSocket::tst_openRequest()
+{
+ EchoServer echoServer;
+
+ QWebSocket socket;
+
+ QSignalSpy socketConnectedSpy(&socket, SIGNAL(connected()));
+ QSignalSpy serverRequestSpy(&echoServer, SIGNAL(newConnection(QNetworkRequest)));
+
+ QUrl url = QUrl(QStringLiteral("ws://") + echoServer.hostAddress().toString() +
+ QLatin1Char(':') + QString::number(echoServer.port()));
+ url.addQueryItem("queryitem", "with encoded characters");
+ QNetworkRequest req(url);
+ req.setRawHeader("X-Custom-Header", "A custom header");
+ socket.open(req);
+
+ QTRY_COMPARE(socketConnectedSpy.count(), 1);
+ QTRY_COMPARE(serverRequestSpy.count(), 1);
+ QCOMPARE(socket.state(), QAbstractSocket::ConnectedState);
+ QList<QVariant> arguments = serverRequestSpy.takeFirst();
+ QNetworkRequest requestConnected = arguments.at(0).value<QNetworkRequest>();
+ QCOMPARE(requestConnected.url(), req.url());
+ QCOMPARE(requestConnected.rawHeader("X-Custom-Header"), req.rawHeader("X-Custom-Header"));
+ socket.close();
+}
+
#ifndef QT_NO_NETWORKPROXY
void tst_QWebSocket::tst_setProxy()
{