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
This commit is contained in:
Shane Kearns 2011-05-04 17:27:36 +01:00 committed by Markus Goetz
parent 724671feca
commit e01faeb5c7
5 changed files with 28 additions and 2 deletions

View File

@ -579,6 +579,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 (ssl) {
#ifndef QT_NO_OPENSSL

View File

@ -556,6 +556,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)",

View File

@ -501,7 +501,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);

View File

@ -1736,6 +1736,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);

View File

@ -4970,7 +4970,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
@ -4988,6 +4990,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 {