QtNetwork: bypass proxy for local connections
authorJulien Brianceau <jbrianceau@nds.com>
Mon, 3 Sep 2012 11:56:09 +0000 (13:56 +0200)
committerQt by Nokia <qt-info@nokia.com>
Fri, 7 Sep 2012 13:44:31 +0000 (15:44 +0200)
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 <rich@kde.org>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Reviewed-by: Shane Kearns <shane.kearns@accenture.com>
src/network/kernel/qnetworkproxy.cpp
src/network/socket/qabstractsocket.cpp
tests/auto/network/kernel/qnetworkproxyfactory/tst_qnetworkproxyfactory.cpp

index 21d5748..e26374e 100644 (file)
@@ -318,6 +318,18 @@ QList<QNetworkProxy> QGlobalNetworkProxy::proxyForQuery(const QNetworkProxyQuery
     QMutexLocker locker(&mutex);
 
     QList<QNetworkProxy> 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)
index 7c91022..a7f9ceb 100644 (file)
@@ -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<QNetworkProxy> proxies;
 
     if (proxy.type() != QNetworkProxy::DefaultProxy) {
index 265c0fe..98fd601 100644 (file)
@@ -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<QNetworkProxy> 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