From cffec6c4fc1aed32ec9b3d9dd1f97105005385dc Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Wed, 4 May 2011 17:27:36 +0100 Subject: Send User-Agent from the network request in http proxy CONNECT command Some proxies can discriminate based on the User-Agent when sent a CONNECT command for establishing a HTTPS connection. With this change, if the User-Agent header is set in the QNetworkRequest then it will be passed to the http socket engine for use in the connect command sent to the proxy. As before, "Mozilla/5.0" will be used by default when no user agent has been set. Task-number: QTBUG-17223 Reviewed-by: Markus Goetz --- src/network/access/qhttpnetworkconnectionchannel.cpp | 6 ++++++ src/network/socket/qabstractsocket.cpp | 4 ++++ src/network/socket/qhttpsocketengine.cpp | 8 +++++++- src/network/ssl/qsslsocket.cpp | 2 ++ tests/auto/qnetworkreply/tst_qnetworkreply.cpp | 10 +++++++++- 5 files changed, 28 insertions(+), 2 deletions(-) diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp index 700b455..bf2fa8f 100644 --- a/src/network/access/qhttpnetworkconnectionchannel.cpp +++ b/src/network/access/qhttpnetworkconnectionchannel.cpp @@ -557,6 +557,12 @@ bool QHttpNetworkConnectionChannel::ensureConnection() connectHost = connection->d_func()->networkProxy.hostName(); connectPort = connection->d_func()->networkProxy.port(); } + if (socket->proxy().type() == QNetworkProxy::HttpProxy) { + // Make user-agent field available to HTTP proxy socket engine (QTBUG-17223) + QByteArray value = request.headerField("user-agent"); + if (!value.isEmpty()) + socket->setProperty("_q_user-agent", value); + } #endif if (connection->d_func()->encrypt) { #ifndef QT_NO_OPENSSL diff --git a/src/network/socket/qabstractsocket.cpp b/src/network/socket/qabstractsocket.cpp index f927ae2..0dc08d9 100644 --- a/src/network/socket/qabstractsocket.cpp +++ b/src/network/socket/qabstractsocket.cpp @@ -549,6 +549,10 @@ bool QAbstractSocketPrivate::initSocketLayer(QAbstractSocket::NetworkLayerProtoc q->setErrorString(QAbstractSocket::tr("Operation on socket is not supported")); return false; } +#ifndef QT_NO_NETWORKPROXY + //copy user agent to socket engine (if it has been set) + socketEngine->setProperty("_q_user-agent", q->property("_q_user-agent")); +#endif if (!socketEngine->initialize(q->socketType(), protocol)) { #if defined (QABSTRACTSOCKET_DEBUG) qDebug("QAbstractSocketPrivate::initSocketLayer(%s, %s) failed (%s)", diff --git a/src/network/socket/qhttpsocketengine.cpp b/src/network/socket/qhttpsocketengine.cpp index a338d97..cebff34 100644 --- a/src/network/socket/qhttpsocketengine.cpp +++ b/src/network/socket/qhttpsocketengine.cpp @@ -467,7 +467,13 @@ void QHttpSocketEngine::slotSocketConnected() data += path; data += " HTTP/1.1\r\n"; data += "Proxy-Connection: keep-alive\r\n" - "User-Agent: Mozilla/5.0\r\n" + "User-Agent: "; + QVariant v = property("_q_user-agent"); + if (v.isValid()) + data += v.toByteArray(); + else + data += "Mozilla/5.0"; + data += "\r\n" "Host: " + peerAddress + "\r\n"; QAuthenticatorPrivate *priv = QAuthenticatorPrivate::getPrivate(d->authenticator); //qDebug() << "slotSocketConnected: priv=" << priv << (priv ? (int)priv->method : -1); diff --git a/src/network/ssl/qsslsocket.cpp b/src/network/ssl/qsslsocket.cpp index 4252123..cf95adf 100644 --- a/src/network/ssl/qsslsocket.cpp +++ b/src/network/ssl/qsslsocket.cpp @@ -1698,6 +1698,8 @@ void QSslSocket::connectToHostImplementation(const QString &hostName, quint16 po } #ifndef QT_NO_NETWORKPROXY d->plainSocket->setProxy(proxy()); + //copy user agent down to the plain socket (if it has been set) + d->plainSocket->setProperty("_q_user-agent", property("_q_user-agent")); #endif QIODevice::open(openMode); d->plainSocket->connectToHost(hostName, port, openMode); diff --git a/tests/auto/qnetworkreply/tst_qnetworkreply.cpp b/tests/auto/qnetworkreply/tst_qnetworkreply.cpp index 81278b6..27c5713 100644 --- a/tests/auto/qnetworkreply/tst_qnetworkreply.cpp +++ b/tests/auto/qnetworkreply/tst_qnetworkreply.cpp @@ -4537,7 +4537,9 @@ void tst_QNetworkReply::httpProxyCommands() QNetworkProxy proxy(QNetworkProxy::HttpProxy, "127.0.0.1", proxyServer.serverPort()); manager.setProxy(proxy); - QNetworkReplyPtr reply = manager.get(QNetworkRequest(url)); + QNetworkRequest request(url); + request.setRawHeader("User-Agent", "QNetworkReplyAutoTest/1.0"); + QNetworkReplyPtr reply = manager.get(request); manager.setProxy(QNetworkProxy()); // wait for the finished signal @@ -4555,6 +4557,12 @@ void tst_QNetworkReply::httpProxyCommands() QString receivedHeader = proxyServer.receivedData.left(expectedCommand.length()); QCOMPARE(receivedHeader, expectedCommand); + + //QTBUG-17223 - make sure the user agent from the request is sent to proxy server even for CONNECT + int uapos = proxyServer.receivedData.indexOf("User-Agent"); + int uaend = proxyServer.receivedData.indexOf("\r\n", uapos); + QByteArray uaheader = proxyServer.receivedData.mid(uapos, uaend - uapos); + QCOMPARE(uaheader, QByteArray("User-Agent: QNetworkReplyAutoTest/1.0")); } class ProxyChangeHelper : public QObject { -- cgit v0.12