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;
|
networkLayerState = QHttpNetworkConnectionPrivate::IPv6;
|
||||||
QMetaObject::invokeMethod(this->q_func(), "_q_startNextRequest", Qt::QueuedConnection);
|
QMetaObject::invokeMethod(this->q_func(), "_q_startNextRequest", Qt::QueuedConnection);
|
||||||
} else {
|
} 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)) {
|
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;
|
networkLayerState = QHttpNetworkConnectionPrivate::Unknown;
|
||||||
} else if (connectionType == QHttpNetworkConnection::ConnectionTypeHTTP2
|
} else if (connectionType == QHttpNetworkConnection::ConnectionTypeHTTP2
|
||||||
|| connectionType == QHttpNetworkConnection::ConnectionTypeHTTP2Direct) {
|
|| connectionType == QHttpNetworkConnection::ConnectionTypeHTTP2Direct) {
|
||||||
@ -1274,7 +1282,7 @@ void QHttpNetworkConnectionPrivate::_q_hostLookupFinished(const QHostInfo &info)
|
|||||||
// emit error for all replies
|
// emit error for all replies
|
||||||
QHttpNetworkReply *currentReply = h2Pair.second;
|
QHttpNetworkReply *currentReply = h2Pair.second;
|
||||||
Q_ASSERT(currentReply);
|
Q_ASSERT(currentReply);
|
||||||
emitReplyError(channels[0].socket, currentReply, QNetworkReply::HostNotFoundError);
|
emitReplyError(channels[0].socket, currentReply, lookupError);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// We can end up here if a request has been aborted or otherwise failed (e.g. timeout)
|
// 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;
|
break;
|
||||||
case QAbstractSocket::ConnectionRefusedError:
|
case QAbstractSocket::ConnectionRefusedError:
|
||||||
errorCode = QNetworkReply::ConnectionRefusedError;
|
errorCode = QNetworkReply::ConnectionRefusedError;
|
||||||
|
#ifndef QT_NO_NETWORKPROXY
|
||||||
|
if (connection->d_func()->networkProxy.type() != QNetworkProxy::NoProxy && !ssl)
|
||||||
|
errorCode = QNetworkReply::ProxyConnectionRefusedError;
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
case QAbstractSocket::RemoteHostClosedError:
|
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.
|
// 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;
|
errorCode = QNetworkReply::TimeoutError;
|
||||||
break;
|
break;
|
||||||
|
case QAbstractSocket::ProxyConnectionRefusedError:
|
||||||
|
errorCode = QNetworkReply::ProxyConnectionRefusedError;
|
||||||
|
break;
|
||||||
case QAbstractSocket::ProxyAuthenticationRequiredError:
|
case QAbstractSocket::ProxyAuthenticationRequiredError:
|
||||||
errorCode = QNetworkReply::ProxyAuthenticationRequiredError;
|
errorCode = QNetworkReply::ProxyAuthenticationRequiredError;
|
||||||
break;
|
break;
|
||||||
|
@ -526,6 +526,9 @@ private Q_SLOTS:
|
|||||||
void notFoundWithCompression_data();
|
void notFoundWithCompression_data();
|
||||||
void notFoundWithCompression();
|
void notFoundWithCompression();
|
||||||
|
|
||||||
|
void qtbug68821proxyError_data();
|
||||||
|
void qtbug68821proxyError();
|
||||||
|
|
||||||
// NOTE: This test must be last!
|
// NOTE: This test must be last!
|
||||||
void parentingRepliesToTheApp();
|
void parentingRepliesToTheApp();
|
||||||
private:
|
private:
|
||||||
@ -3852,7 +3855,6 @@ void tst_QNetworkReply::ioGetFromHttpWithSocksProxy()
|
|||||||
QVERIFY(reader.data.isEmpty());
|
QVERIFY(reader.data.isEmpty());
|
||||||
|
|
||||||
QVERIFY(int(reply->error()) > 0);
|
QVERIFY(int(reply->error()) > 0);
|
||||||
QEXPECT_FAIL("", "QTcpSocket doesn't return enough information yet", Continue);
|
|
||||||
QCOMPARE(int(reply->error()), int(QNetworkReply::ProxyConnectionRefusedError));
|
QCOMPARE(int(reply->error()), int(QNetworkReply::ProxyConnectionRefusedError));
|
||||||
|
|
||||||
QCOMPARE(authspy.size(), 0);
|
QCOMPARE(authspy.size(), 0);
|
||||||
@ -10094,6 +10096,48 @@ void tst_QNetworkReply::notFoundWithCompression()
|
|||||||
QCOMPARE(reply->readAll(), expected);
|
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!
|
// NOTE: This test must be last testcase in tst_qnetworkreply!
|
||||||
void tst_QNetworkReply::parentingRepliesToTheApp()
|
void tst_QNetworkReply::parentingRepliesToTheApp()
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user