QNetworkReply: Propagate proxy errors properly
Map QNetworkError::HostNotFoundError and QNetworkError::ConnectionRefusedError to ProxyNotFoundError resp. ProxyConnectionRefusedError when it originated from the communication with the proxy server. Fixes: QTBUG-68821 Pick-to: 6.5 6.6 Change-Id: I21b91f2667ba0cd329d4ece1fe543472cdab2d22 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
This commit is contained in:
parent
d74235db5d
commit
69de333e1f
@ -1265,8 +1265,16 @@ void QHttpNetworkConnectionPrivate::_q_hostLookupFinished(const QHostInfo &info)
|
||||
networkLayerState = QHttpNetworkConnectionPrivate::IPv6;
|
||||
QMetaObject::invokeMethod(this->q_func(), "_q_startNextRequest", Qt::QueuedConnection);
|
||||
} else {
|
||||
auto lookupError = QNetworkReply::HostNotFoundError;
|
||||
#ifndef QT_NO_NETWORKPROXY
|
||||
// if the proxy can lookup hostnames, all hostname lookups except for the lookup of the
|
||||
// proxy hostname are delegated to the proxy.
|
||||
auto proxyCapabilities = networkProxy.capabilities() | channels[0].proxy.capabilities();
|
||||
if (proxyCapabilities & QNetworkProxy::HostNameLookupCapability)
|
||||
lookupError = QNetworkReply::ProxyNotFoundError;
|
||||
#endif
|
||||
if (dequeueRequest(channels[0].socket)) {
|
||||
emitReplyError(channels[0].socket, channels[0].reply, QNetworkReply::HostNotFoundError);
|
||||
emitReplyError(channels[0].socket, channels[0].reply, lookupError);
|
||||
networkLayerState = QHttpNetworkConnectionPrivate::Unknown;
|
||||
} else if (connectionType == QHttpNetworkConnection::ConnectionTypeHTTP2
|
||||
|| connectionType == QHttpNetworkConnection::ConnectionTypeHTTP2Direct) {
|
||||
@ -1274,7 +1282,7 @@ void QHttpNetworkConnectionPrivate::_q_hostLookupFinished(const QHostInfo &info)
|
||||
// emit error for all replies
|
||||
QHttpNetworkReply *currentReply = h2Pair.second;
|
||||
Q_ASSERT(currentReply);
|
||||
emitReplyError(channels[0].socket, currentReply, QNetworkReply::HostNotFoundError);
|
||||
emitReplyError(channels[0].socket, currentReply, lookupError);
|
||||
}
|
||||
} else {
|
||||
// We can end up here if a request has been aborted or otherwise failed (e.g. timeout)
|
||||
|
@ -949,6 +949,10 @@ void QHttpNetworkConnectionChannel::_q_error(QAbstractSocket::SocketError socket
|
||||
break;
|
||||
case QAbstractSocket::ConnectionRefusedError:
|
||||
errorCode = QNetworkReply::ConnectionRefusedError;
|
||||
#ifndef QT_NO_NETWORKPROXY
|
||||
if (connection->d_func()->networkProxy.type() != QNetworkProxy::NoProxy && !ssl)
|
||||
errorCode = QNetworkReply::ProxyConnectionRefusedError;
|
||||
#endif
|
||||
break;
|
||||
case QAbstractSocket::RemoteHostClosedError:
|
||||
// This error for SSL comes twice in a row, first from SSL layer ("The TLS/SSL connection has been closed") then from TCP layer.
|
||||
@ -1030,6 +1034,9 @@ void QHttpNetworkConnectionChannel::_q_error(QAbstractSocket::SocketError socket
|
||||
}
|
||||
errorCode = QNetworkReply::TimeoutError;
|
||||
break;
|
||||
case QAbstractSocket::ProxyConnectionRefusedError:
|
||||
errorCode = QNetworkReply::ProxyConnectionRefusedError;
|
||||
break;
|
||||
case QAbstractSocket::ProxyAuthenticationRequiredError:
|
||||
errorCode = QNetworkReply::ProxyAuthenticationRequiredError;
|
||||
break;
|
||||
|
@ -526,6 +526,9 @@ private Q_SLOTS:
|
||||
void notFoundWithCompression_data();
|
||||
void notFoundWithCompression();
|
||||
|
||||
void qtbug68821proxyError_data();
|
||||
void qtbug68821proxyError();
|
||||
|
||||
// NOTE: This test must be last!
|
||||
void parentingRepliesToTheApp();
|
||||
private:
|
||||
@ -3852,7 +3855,6 @@ void tst_QNetworkReply::ioGetFromHttpWithSocksProxy()
|
||||
QVERIFY(reader.data.isEmpty());
|
||||
|
||||
QVERIFY(int(reply->error()) > 0);
|
||||
QEXPECT_FAIL("", "QTcpSocket doesn't return enough information yet", Continue);
|
||||
QCOMPARE(int(reply->error()), int(QNetworkReply::ProxyConnectionRefusedError));
|
||||
|
||||
QCOMPARE(authspy.size(), 0);
|
||||
@ -10094,6 +10096,48 @@ void tst_QNetworkReply::notFoundWithCompression()
|
||||
QCOMPARE(reply->readAll(), expected);
|
||||
}
|
||||
|
||||
void tst_QNetworkReply::qtbug68821proxyError_data()
|
||||
{
|
||||
QTest::addColumn<QString>("proxyHost");
|
||||
QTest::addColumn<QString>("scheme");
|
||||
QTest::addColumn<QNetworkReply::NetworkError>("error");
|
||||
|
||||
QTest::newRow("invalidhost+http") << "this-host-will-never-exist.qt-project.org"
|
||||
<< "http" << QNetworkReply::ProxyNotFoundError;
|
||||
QTest::newRow("localhost+http") << "localhost"
|
||||
<< "http" << QNetworkReply::ProxyConnectionRefusedError;
|
||||
#ifndef QT_NO_SSL
|
||||
QTest::newRow("invalidhost+https") << "this-host-will-never-exist.qt-project.org"
|
||||
<< "https" << QNetworkReply::ProxyNotFoundError;
|
||||
QTest::newRow("localhost+https") << "localhost"
|
||||
<< "https" << QNetworkReply::ProxyConnectionRefusedError;
|
||||
#endif
|
||||
}
|
||||
|
||||
void tst_QNetworkReply::qtbug68821proxyError()
|
||||
{
|
||||
QTcpServer proxyServer;
|
||||
QVERIFY(proxyServer.listen());
|
||||
quint16 proxyPort = proxyServer.serverPort();
|
||||
proxyServer.close();
|
||||
|
||||
QFETCH(QString, proxyHost);
|
||||
QNetworkProxy proxy(QNetworkProxy::HttpProxy, proxyHost, proxyPort);
|
||||
|
||||
manager.setProxy(proxy);
|
||||
|
||||
QFETCH(QString, scheme);
|
||||
QNetworkReply *reply = manager.get(QNetworkRequest(QUrl(scheme + "://example.com")));
|
||||
QSignalSpy spy(reply, &QNetworkReply::errorOccurred);
|
||||
QVERIFY(spy.isValid());
|
||||
|
||||
QVERIFY(spy.wait(15000));
|
||||
|
||||
QFETCH(QNetworkReply::NetworkError, error);
|
||||
QCOMPARE(spy.count(), 1);
|
||||
QCOMPARE(spy.at(0).at(0), error);
|
||||
}
|
||||
|
||||
// NOTE: This test must be last testcase in tst_qnetworkreply!
|
||||
void tst_QNetworkReply::parentingRepliesToTheApp()
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user