From 5b1bc864a91c3bdb02e36e7546dadebabb42fdec Mon Sep 17 00:00:00 2001 From: Julien Brianceau Date: Mon, 3 Sep 2012 13:56:09 +0200 Subject: QtNetwork: bypass proxy for local connections According to Qt doc, "Network proxy is not used if the address used in connectToHost(), bind() or listen() is equivalent to QHostAddress::LocalHost or QHostAddress::LocalHostIPv6. This is not the case in current implementation. Change-Id: I6b8a40c1e8bd8aad9504d8f939b87eda6e93337c Reviewed-by: Richard J. Moore Reviewed-by: Thiago Macieira Reviewed-by: Shane Kearns --- src/network/kernel/qnetworkproxy.cpp | 12 +++++ src/network/socket/qabstractsocket.cpp | 9 ---- .../tst_qnetworkproxyfactory.cpp | 61 ++++++++++++++++++++++ 3 files changed, 73 insertions(+), 9 deletions(-) diff --git a/src/network/kernel/qnetworkproxy.cpp b/src/network/kernel/qnetworkproxy.cpp index 21d5748562..e26374eb0f 100644 --- a/src/network/kernel/qnetworkproxy.cpp +++ b/src/network/kernel/qnetworkproxy.cpp @@ -318,6 +318,18 @@ QList QGlobalNetworkProxy::proxyForQuery(const QNetworkProxyQuery QMutexLocker locker(&mutex); QList result; + + // don't look for proxies for a local connection + QHostAddress parsed; + QString hostname = query.url().host(); + if (hostname == QLatin1String("localhost") + || hostname.startsWith(QLatin1String("localhost.")) + || (parsed.setAddress(hostname) + && (parsed.isLoopback()))) { + result << QNetworkProxy(QNetworkProxy::NoProxy); + return result; + } + if (!applicationLevelProxyFactory) { if (applicationLevelProxy && applicationLevelProxy->type() != QNetworkProxy::DefaultProxy) diff --git a/src/network/socket/qabstractsocket.cpp b/src/network/socket/qabstractsocket.cpp index 7c91022759..a7f9ceb3c4 100644 --- a/src/network/socket/qabstractsocket.cpp +++ b/src/network/socket/qabstractsocket.cpp @@ -906,15 +906,6 @@ bool QAbstractSocketPrivate::flush() */ void QAbstractSocketPrivate::resolveProxy(const QString &hostname, quint16 port) { - QHostAddress parsed; - if (hostname == QLatin1String("localhost") - || hostname.startsWith(QLatin1String("localhost.")) - || (parsed.setAddress(hostname) - && (parsed.isLoopback()))) { - proxyInUse = QNetworkProxy::NoProxy; - return; - } - QList proxies; if (proxy.type() != QNetworkProxy::DefaultProxy) { diff --git a/tests/auto/network/kernel/qnetworkproxyfactory/tst_qnetworkproxyfactory.cpp b/tests/auto/network/kernel/qnetworkproxyfactory/tst_qnetworkproxyfactory.cpp index 265c0fecbb..98fd60190d 100644 --- a/tests/auto/network/kernel/qnetworkproxyfactory/tst_qnetworkproxyfactory.cpp +++ b/tests/auto/network/kernel/qnetworkproxyfactory/tst_qnetworkproxyfactory.cpp @@ -80,6 +80,7 @@ private slots: void systemProxyForQueryCalledFromThread(); void systemProxyForQuery_data(); void systemProxyForQuery() const; + void systemProxyForQuery_local(); #ifndef QT_NO_BEARERMANAGEMENT void fromConfigurations(); void inNetworkAccessManager_data(); @@ -196,6 +197,66 @@ void tst_QNetworkProxyFactory::systemProxyForQuery() const } } +void tst_QNetworkProxyFactory::systemProxyForQuery_local() +{ + QList list; + const QString proxyHost("myproxy.test.com"); + + // set an arbitrary proxy + QNetworkProxy::setApplicationProxy(QNetworkProxy(QNetworkProxy::HttpProxy, proxyHost, 80)); + + // localhost + list = QNetworkProxyFactory::proxyForQuery(QNetworkProxyQuery(QUrl("http://localhost/"))); + QVERIFY(list.isEmpty() || (list[0].type() == QNetworkProxy::NoProxy)); + list = QNetworkProxyFactory::proxyForQuery(QNetworkProxyQuery(QString("localhost"), 80)); + QVERIFY(list.isEmpty() || (list[0].type() == QNetworkProxy::NoProxy)); + + // 127.0.0.1 + list = QNetworkProxyFactory::proxyForQuery(QNetworkProxyQuery(QUrl("http://127.0.0.1/"))); + QVERIFY(list.isEmpty() || (list[0].type() == QNetworkProxy::NoProxy)); + list = QNetworkProxyFactory::proxyForQuery(QNetworkProxyQuery(QString("127.0.0.1"), 80)); + QVERIFY(list.isEmpty() || (list[0].type() == QNetworkProxy::NoProxy)); + + // [::1] + list = QNetworkProxyFactory::proxyForQuery(QNetworkProxyQuery(QUrl("http://[::1]/"))); + QVERIFY(list.isEmpty() || (list[0].type() == QNetworkProxy::NoProxy)); + list = QNetworkProxyFactory::proxyForQuery(QNetworkProxyQuery(QString("[::1]"), 80)); + QVERIFY(list.isEmpty() || (list[0].type() == QNetworkProxy::NoProxy)); + + // an arbitrary host + list = QNetworkProxyFactory::proxyForQuery(QNetworkProxyQuery(QUrl("http://another.host.com/"))); + QVERIFY((!list.isEmpty()) && (list[0].hostName() == proxyHost)); + list = QNetworkProxyFactory::proxyForQuery(QNetworkProxyQuery(QString("another.host.com"), 80)); + QVERIFY((!list.isEmpty()) && (list[0].hostName() == proxyHost)); + + // disable proxy + QNetworkProxy::setApplicationProxy(QNetworkProxy(QNetworkProxy::NoProxy)); + + // localhost + list = QNetworkProxyFactory::proxyForQuery(QNetworkProxyQuery(QUrl("http://localhost/"))); + QVERIFY(list.isEmpty() || (list[0].type() == QNetworkProxy::NoProxy)); + list = QNetworkProxyFactory::proxyForQuery(QNetworkProxyQuery(QString("localhost"), 80)); + QVERIFY(list.isEmpty() || (list[0].type() == QNetworkProxy::NoProxy)); + + // 127.0.0.1 + list = QNetworkProxyFactory::proxyForQuery(QNetworkProxyQuery(QUrl("http://127.0.0.1/"))); + QVERIFY(list.isEmpty() || (list[0].type() == QNetworkProxy::NoProxy)); + list = QNetworkProxyFactory::proxyForQuery(QNetworkProxyQuery(QString("127.0.0.1"), 80)); + QVERIFY(list.isEmpty() || (list[0].type() == QNetworkProxy::NoProxy)); + + // [::1] + list = QNetworkProxyFactory::proxyForQuery(QNetworkProxyQuery(QUrl("http://[::1]/"))); + QVERIFY(list.isEmpty() || (list[0].type() == QNetworkProxy::NoProxy)); + list = QNetworkProxyFactory::proxyForQuery(QNetworkProxyQuery(QString("[::1]"), 80)); + QVERIFY(list.isEmpty() || (list[0].type() == QNetworkProxy::NoProxy)); + + // an arbitrary host + list = QNetworkProxyFactory::proxyForQuery(QNetworkProxyQuery(QUrl("http://another.host.com/"))); + QVERIFY(list.isEmpty() || (list[0].type() == QNetworkProxy::NoProxy)); + list = QNetworkProxyFactory::proxyForQuery(QNetworkProxyQuery(QString("another.host.com"), 80)); + QVERIFY(list.isEmpty() || (list[0].type() == QNetworkProxy::NoProxy)); +} + #ifndef QT_NO_BEARERMANAGEMENT //Purpose of this test is just to check systemProxyForQuery doesn't hang or crash -- cgit v1.2.3