37#include <QAuthenticator>
39#include <QNetworkReply>
40#include <QRecursiveMutex>
41#include <QStandardPaths>
43#include <QThreadStorage>
48#include "moc_qgsnetworkaccessmanager.cpp"
50using namespace Qt::StringLiterals;
55#include <QSslConfiguration>
63static std::vector< std::pair< QString, std::function< void( QNetworkRequest * ) > > > sCustomPreprocessors;
64static std::vector< std::pair< QString, std::function< void( QNetworkRequest *,
int &op, QByteArray *data ) > > > sCustomAdvancedPreprocessors;
65static std::vector< std::pair< QString, std::function< void(
const QNetworkRequest &, QNetworkReply * ) > > > sCustomReplyPreprocessors;
68class QgsNetworkProxyFactory :
public QNetworkProxyFactory
71 QgsNetworkProxyFactory() =
default;
73 QList<QNetworkProxy> queryProxy(
const QNetworkProxyQuery &query = QNetworkProxyQuery() )
override
79 for ( QNetworkProxyFactory *f : constProxyFactories )
81 QList<QNetworkProxy> systemproxies = QNetworkProxyFactory::systemProxyForQuery( query );
82 if ( !systemproxies.isEmpty() )
85 QList<QNetworkProxy> proxies = f->queryProxy( query );
86 if ( !proxies.isEmpty() )
91 if ( query.queryType() != QNetworkProxyQuery::UrlRequest )
94 const QString url = query.url().toString();
97 for (
const QString &noProxy : constNoProxyList )
99 if ( !noProxy.trimmed().isEmpty() && url.startsWith( noProxy ) )
101 QgsDebugMsgLevel( u
"don't using any proxy for %1 [exclude %2]"_s.arg( url, noProxy ), 4 );
102 return QList<QNetworkProxy>() << QNetworkProxy( QNetworkProxy::NoProxy );
107 for (
const QString &exclude : constExcludeList )
109 if ( !exclude.trimmed().isEmpty() && url.startsWith( exclude ) )
111 QgsDebugMsgLevel( u
"using default proxy for %1 [exclude %2]"_s.arg( url, exclude ), 4 );
112 return QList<QNetworkProxy>() << QNetworkProxy( QNetworkProxy::DefaultProxy );
118 QgsDebugMsgLevel( u
"requesting system proxy for query %1"_s.arg( url ), 4 );
119 QList<QNetworkProxy> proxies = QNetworkProxyFactory::systemProxyForQuery( query );
120 if ( !proxies.isEmpty() )
122 QgsDebugMsgLevel( u
"using system proxy %1:%2 for query"_s.arg( proxies.first().hostName() ).arg( proxies.first().port() ), 4 );
134class QgsNetworkCookieJar :
public QNetworkCookieJar
139 QgsNetworkCookieJar( QgsNetworkAccessManager *parent )
140 : QNetworkCookieJar( parent )
144 bool deleteCookie(
const QNetworkCookie &cookie )
override
146 const QMutexLocker locker( &mMutex );
147 if ( QNetworkCookieJar::deleteCookie( cookie ) )
149 emit mNam->cookiesChanged( allCookies() );
154 bool insertCookie(
const QNetworkCookie &cookie )
override
156 const QMutexLocker locker( &mMutex );
157 if ( QNetworkCookieJar::insertCookie( cookie ) )
159 emit mNam->cookiesChanged( allCookies() );
164 bool setCookiesFromUrl(
const QList<QNetworkCookie> &cookieList,
const QUrl &url )
override
166 const QMutexLocker locker( &mMutex );
167 return QNetworkCookieJar::setCookiesFromUrl( cookieList, url );
169 bool updateCookie(
const QNetworkCookie &cookie )
override
171 const QMutexLocker locker( &mMutex );
172 if ( QNetworkCookieJar::updateCookie( cookie ) )
174 emit mNam->cookiesChanged( allCookies() );
181 QList<QNetworkCookie> allCookies()
const
183 const QMutexLocker locker( &mMutex );
184 return QNetworkCookieJar::allCookies();
186 void setAllCookies(
const QList<QNetworkCookie> &cookieList )
188 const QMutexLocker locker( &mMutex );
189 QNetworkCookieJar::setAllCookies( cookieList );
192 QgsNetworkAccessManager *mNam =
nullptr;
193 mutable QRecursiveMutex mMutex;
203 static QThreadStorage<QgsNetworkAccessManager> sInstances;
206 if ( nam->thread() == qApp->thread() )
209 if ( !nam->mInitialized )
211 QgsDebugMsgLevel( u
"Initializing new network access manager for %1thread: %2"_s.arg( QThread::currentThread() == qApp->thread() ? u
"MAIN "_s : QString() ).arg(
reinterpret_cast< qint64
>( QThread::currentThread() ), 0, 16 ), 2 );
217 QgsDebugMsgLevel( u
"Network access manager retrieved for %1thread: %2"_s.arg( QThread::currentThread() == qApp->thread() ? u
"MAIN "_s : QString() ).arg(
reinterpret_cast< qint64
>( QThread::currentThread() ), 0, 16 ), 4 );
224 : QNetworkAccessManager( parent )
225 , mSslErrorHandlerSemaphore( 1 )
226 , mAuthRequestHandlerSemaphore( 1 )
228 setRedirectPolicy( QNetworkRequest::NoLessSafeRedirectPolicy );
229 setProxyFactory(
new QgsNetworkProxyFactory() );
230 setCookieJar(
new QgsNetworkCookieJar(
this ) );
231 enableStrictTransportSecurityStore(
true );
232 setStrictTransportSecurityEnabled(
true );
237 Q_ASSERT( sMainNAM ==
this );
238 mSslErrorHandler = std::move( handler );
243 Q_ASSERT( sMainNAM ==
this );
244 mAuthHandler = std::move( handler );
249 mProxyFactories.insert( 0, factory );
254 mProxyFactories.removeAll( factory );
259 return mProxyFactories;
264 return mExcludedURLs;
274 return mFallbackProxy;
280 u
"proxy settings: (type:%1 host: %2:%3, user:%4, password:%5"_s
282 proxy.type() == QNetworkProxy::DefaultProxy ? u
"DefaultProxy"_s
283 : proxy.type() == QNetworkProxy::Socks5Proxy ? u
"Socks5Proxy"_s
284 : proxy.type() == QNetworkProxy::NoProxy ? u
"NoProxy"_s
285 : proxy.type() == QNetworkProxy::HttpProxy ? u
"HttpProxy"_s
286 : proxy.type() == QNetworkProxy::HttpCachingProxy ? u
"HttpCachingProxy"_s
287 : proxy.type() == QNetworkProxy::FtpCachingProxy ? u
"FtpCachingProxy"_s
292 .arg( proxy.user(), proxy.password().isEmpty() ? u
"not set"_s : u
"set"_s ),
296 mFallbackProxy = proxy;
297 mExcludedURLs = excludes;
301 mExcludedURLs.begin(),
303 [](
const QString &url ) { return url.trimmed().isEmpty(); }
308 mNoProxyURLs = noProxyURLs;
311 mNoProxyURLs.begin(),
313 [](
const QString &url ) { return url.trimmed().isEmpty(); }
321 QgsDebugMsgLevel( u
"Creating new network request on thread: %1 for %2"_s.arg(
reinterpret_cast< qint64
>( QThread::currentThread() ), 0, 16 ).arg( req.url().toString() ), 3 );
326 QNetworkRequest modifiedRequest( req );
328 QString userAgent = s.
value( u
"/qgis/networkAndProxy/userAgent"_s,
"Mozilla/5.0" ).toString();
329 if ( !userAgent.isEmpty() )
331 userAgent += u
"QGIS/%1/%2"_s.arg(
Qgis::versionInt() ).arg( QSysInfo::prettyProductName() );
332 modifiedRequest.setRawHeader(
"User-Agent", userAgent.toLatin1() );
335 const bool ishttps = modifiedRequest.url().scheme().compare(
"https"_L1, Qt::CaseInsensitive ) == 0;
339 QSslConfiguration sslconfig( modifiedRequest.sslConfiguration() );
341 sslconfig.setCaCertificates( QgsAuthCertUtils::casMerge(
QgsApplication::authManager()->trustedCaCertsCache(), sslconfig.caCertificates() ) );
343 const QString hostport( u
"%1:%2"_s.arg( modifiedRequest.url().host().trimmed() ).arg( modifiedRequest.url().port() != -1 ? modifiedRequest.url().port() : 443 ) );
345 if ( !servconfig.
isNull() )
347 QgsDebugMsgLevel( u
"Adding SSL custom config to request for %1"_s.arg( hostport ), 2 );
353 modifiedRequest.setSslConfiguration( sslconfig );
357 if ( modifiedRequest.url().port() != -1 )
359 QUrl requestUrl = modifiedRequest.url();
360 const QString scheme = requestUrl.scheme();
361 const bool isDefaultPort = ( scheme ==
"http"_L1 && requestUrl.port() == 80 ) || ( scheme ==
"https"_L1 && requestUrl.port() == 443 );
364 QgsDebugMsgLevel( u
"Removing explicit default port %2 from url %1"_s.arg( requestUrl.port() ).arg( requestUrl.toString() ), 2 );
365 requestUrl.setPort( -1 );
366 modifiedRequest.setUrl( requestUrl );
370 if ( sMainNAM->mCacheDisabled )
373 modifiedRequest.setAttribute( QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::AlwaysNetwork );
374 modifiedRequest.setAttribute( QNetworkRequest::CacheSaveControlAttribute,
false );
377 for (
const auto &preprocessor : sCustomPreprocessors )
379 preprocessor.second( &modifiedRequest );
382 static QAtomicInt sRequestId = 0;
383 const int requestId = ++sRequestId;
385 if ( QBuffer *buffer = qobject_cast<QBuffer *>( outgoingData ) )
387 content = buffer->buffer();
390 for (
const auto &preprocessor : sCustomAdvancedPreprocessors )
392 int intOp =
static_cast< int >( op );
393 preprocessor.second( &modifiedRequest, intOp, &content );
394 op =
static_cast< QNetworkAccessManager::Operation
>( intOp );
397 bool needsCachePendingRequestCleanup =
false;
400 if ( modifiedRequest.attribute( QNetworkRequest::CacheLoadControlAttribute ) != QNetworkRequest::AlwaysNetwork )
404 if ( diskCache->hasInvalidMatchForRequest( modifiedRequest ) )
407 modifiedRequest.setAttribute( QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::AlwaysNetwork );
408 modifiedRequest.setAttribute( QNetworkRequest::CacheSaveControlAttribute,
false );
412 if ( modifiedRequest.attribute( QNetworkRequest::CacheSaveControlAttribute,
true ).toBool() )
414 if ( diskCache->hasPendingRequestForUrl( modifiedRequest.url() ) )
417 modifiedRequest.setAttribute( QNetworkRequest::CacheSaveControlAttribute,
false );
421 QVariantMap currentHeaders;
422 const QList<QByteArray> rawHeaderList = modifiedRequest.rawHeaderList();
423 for (
const QByteArray &header : rawHeaderList )
425 currentHeaders.insert( QString::fromUtf8( header ).toLower(), modifiedRequest.rawHeader( header ) );
427 diskCache->insertPendingRequestHeaders( modifiedRequest.url(), currentHeaders );
428 needsCachePendingRequestCleanup =
true;
437 QNetworkReply *reply = QNetworkAccessManager::createRequest( op, modifiedRequest, outgoingData );
438 reply->setProperty(
"requestId", requestId );
445 connect( reply, &QNetworkReply::downloadProgress,
this, &QgsNetworkAccessManager::onReplyDownloadProgress );
447 connect( reply, &QNetworkReply::sslErrors,
this, &QgsNetworkAccessManager::onReplySslErrors );
450 for (
const auto &replyPreprocessor : sCustomReplyPreprocessors )
452 replyPreprocessor.second( modifiedRequest, reply );
455 if ( needsCachePendingRequestCleanup )
459 const QUrl url = modifiedRequest.url();
460 connect( reply, &QNetworkReply::finished, diskCache, [url, diskCache] { diskCache->removePendingRequestForUrl( url ); } );
469 QTimer *timer =
new QTimer( reply );
470 timer->setObjectName( u
"timeoutTimer"_s );
471 connect( timer, &QTimer::timeout,
this, &QgsNetworkAccessManager::abortRequest );
472 timer->setSingleShot(
true );
475 connect( reply, &QNetworkReply::downloadProgress, timer, [timer] { timer->start(); } );
476 connect( reply, &QNetworkReply::uploadProgress, timer, [timer] { timer->start(); } );
477 connect( reply, &QNetworkReply::finished, timer, &QTimer::stop );
479 QgsDebugMsgLevel( u
"Created [reply:%1]"_s.arg(
reinterpret_cast< qint64
>( reply ), 0, 16 ), 3 );
484void QgsNetworkAccessManager::abortRequest()
486 QTimer *timer = qobject_cast<QTimer *>( sender() );
489 QNetworkReply *reply = qobject_cast<QNetworkReply *>( timer->parent() );
493 QgsDebugMsgLevel( u
"Abort [reply:%1] %2"_s.arg(
reinterpret_cast< qint64
>( reply ), 0, 16 ).arg( reply->url().toString() ), 3 );
500void QgsNetworkAccessManager::onReplyFinished( QNetworkReply *reply )
502 emit
finished( QgsNetworkReplyContent( reply ) );
505void QgsNetworkAccessManager::onReplyDownloadProgress( qint64 bytesReceived, qint64 bytesTotal )
507 if ( QNetworkReply *reply = qobject_cast< QNetworkReply *>( sender() ) )
513int QgsNetworkAccessManager::getRequestId( QNetworkReply *reply )
515 return reply->property(
"requestId" ).toInt();
518void QgsNetworkAccessManager::pauseTimeout( QNetworkReply *reply )
520 Q_ASSERT( reply->manager() ==
this );
522 QTimer *timer = reply->findChild<QTimer *>( u
"timeoutTimer"_s );
523 if ( timer && timer->isActive() )
529void QgsNetworkAccessManager::restartTimeout( QNetworkReply *reply )
531 Q_ASSERT( reply->manager() ==
this );
533 QTimer *timer = reply->findChild<QTimer *>( u
"timeoutTimer"_s );
536 Q_ASSERT( !timer->isActive() );
538 timer->setSingleShot(
true );
543void QgsNetworkAccessManager::afterAuthRequestHandled( QNetworkReply *reply )
545 if ( reply->manager() ==
this )
547 restartTimeout( reply );
548 emit authRequestHandled( reply );
553void QgsNetworkAccessManager::onReplySslErrors(
const QList<QSslError> &errors )
555 QNetworkReply *reply = qobject_cast< QNetworkReply *>( sender() );
557 Q_ASSERT( reply->manager() ==
this );
559 QgsDebugMsgLevel( u
"Stopping network reply timeout whilst SSL error is handled"_s, 2 );
560 pauseTimeout( reply );
565 mSslErrorHandlerSemaphore.acquire();
569 emit sslErrorsOccurred( reply, errors );
570 if (
this != sMainNAM )
574 mSslErrorHandlerSemaphore.acquire();
575 mSslErrorHandlerSemaphore.release();
576 afterSslErrorHandled( reply );
580void QgsNetworkAccessManager::afterSslErrorHandled( QNetworkReply *reply )
582 if ( reply->manager() ==
this )
584 restartTimeout( reply );
585 emit sslErrorsHandled( reply );
589void QgsNetworkAccessManager::handleSslErrors( QNetworkReply *reply,
const QList<QSslError> &errors )
591 mSslErrorHandler->handleSslErrors( reply, errors );
592 afterSslErrorHandled( reply );
593 qobject_cast<QgsNetworkAccessManager *>( reply->manager() )->mSslErrorHandlerSemaphore.release();
598void QgsNetworkAccessManager::onAuthRequired( QNetworkReply *reply, QAuthenticator *auth )
601 Q_ASSERT( reply->manager() ==
this );
603 QgsDebugMsgLevel( u
"Stopping network reply timeout whilst auth request is handled"_s, 2 );
604 pauseTimeout( reply );
609 mAuthRequestHandlerSemaphore.acquire();
613 emit authRequestOccurred( reply, auth );
615 if (
this != sMainNAM )
619 mAuthRequestHandlerSemaphore.acquire();
620 mAuthRequestHandlerSemaphore.release();
621 afterAuthRequestHandled( reply );
627 if (
this != sMainNAM )
629 sMainNAM->requestAuthOpenBrowser( url );
633 mAuthHandler->handleAuthRequestOpenBrowser( url );
638 if (
this != sMainNAM )
640 sMainNAM->requestAuthCloseBrowser();
644 mAuthHandler->handleAuthRequestCloseBrowser();
649 if (
this != sMainNAM )
656void QgsNetworkAccessManager::handleAuthRequest( QNetworkReply *reply, QAuthenticator *auth )
658 mAuthHandler->handleAuthRequest( reply, auth );
662 afterAuthRequestHandled( reply );
663 qobject_cast<QgsNetworkAccessManager *>( reply->manager() )->mAuthRequestHandlerSemaphore.release();
670 case QNetworkRequest::AlwaysNetwork:
671 return u
"AlwaysNetwork"_s;
672 case QNetworkRequest::PreferNetwork:
673 return u
"PreferNetwork"_s;
674 case QNetworkRequest::PreferCache:
675 return u
"PreferCache"_s;
676 case QNetworkRequest::AlwaysCache:
677 return u
"AlwaysCache"_s;
679 return u
"PreferNetwork"_s;
684 if ( name ==
"AlwaysNetwork"_L1 )
686 return QNetworkRequest::AlwaysNetwork;
688 else if ( name ==
"PreferNetwork"_L1 )
690 return QNetworkRequest::PreferNetwork;
692 else if ( name ==
"PreferCache"_L1 )
694 return QNetworkRequest::PreferCache;
696 else if ( name ==
"AlwaysCache"_L1 )
698 return QNetworkRequest::AlwaysCache;
700 return QNetworkRequest::PreferNetwork;
706 mUseSystemProxy =
false;
708 Q_ASSERT( sMainNAM );
710 if ( sMainNAM !=
this )
712 connect(
this, &QNetworkAccessManager::proxyAuthenticationRequired, sMainNAM, &QNetworkAccessManager::proxyAuthenticationRequired, connectionType );
727 connect(
this, &QNetworkAccessManager::sslErrors, sMainNAM, &QNetworkAccessManager::sslErrors, connectionType );
739 if ( !mSslErrorHandler )
743 setAuthHandler( std::make_unique< QgsNetworkAuthenticationHandler>() );
746 connect(
this, &QgsNetworkAccessManager::sslErrorsOccurred, sMainNAM, &QgsNetworkAccessManager::handleSslErrors );
748 connect(
this, &QNetworkAccessManager::authenticationRequired,
this, &QgsNetworkAccessManager::onAuthRequired );
749 connect(
this, &QgsNetworkAccessManager::authRequestOccurred, sMainNAM, &QgsNetworkAccessManager::handleAuthRequest );
751 connect(
this, &QNetworkAccessManager::finished,
this, &QgsNetworkAccessManager::onReplyFinished );
756 QStringList excludes;
757 QStringList noProxyURLs;
759 const bool proxyEnabled = settings.
value( u
"proxy/proxyEnabled"_s,
false ).toBool();
764 excludes = settings.
value( u
"proxy/proxyExcludedUrls"_s, QStringList() ).toStringList();
766 noProxyURLs = settings.
value( u
"proxy/noProxyUrls"_s, QStringList() ).toStringList();
769 const QString proxyHost = settings.
value( u
"proxy/proxyHost"_s,
"" ).toString();
770 const int proxyPort = settings.
value( u
"proxy/proxyPort"_s,
"" ).toString().toInt();
772 const QString proxyUser = settings.
value( u
"proxy/proxyUser"_s,
"" ).toString();
773 const QString proxyPassword = settings.
value( u
"proxy/proxyPassword"_s,
"" ).toString();
775 const QString proxyTypeString = settings.
value( u
"proxy/proxyType"_s,
"" ).toString();
777 if ( proxyTypeString ==
"DefaultProxy"_L1 )
779 mUseSystemProxy =
true;
780 QNetworkProxyFactory::setUseSystemConfiguration(
true );
781 QList<QNetworkProxy> proxies = QNetworkProxyFactory::systemProxyForQuery();
782 if ( !proxies.isEmpty() )
784 proxy = proxies.first();
790 QNetworkProxy::ProxyType proxyType = QNetworkProxy::DefaultProxy;
791 if ( proxyTypeString ==
"Socks5Proxy"_L1 )
793 proxyType = QNetworkProxy::Socks5Proxy;
795 else if ( proxyTypeString ==
"HttpProxy"_L1 )
797 proxyType = QNetworkProxy::HttpProxy;
799 else if ( proxyTypeString ==
"HttpCachingProxy"_L1 )
801 proxyType = QNetworkProxy::HttpCachingProxy;
803 else if ( proxyTypeString ==
"FtpCachingProxy"_L1 )
805 proxyType = QNetworkProxy::FtpCachingProxy;
807 QgsDebugMsgLevel( u
"setting proxy %1 %2:%3 %4/%5"_s.arg( proxyType ).arg( proxyHost ).arg( proxyPort ).arg( proxyUser, proxyPassword ), 2 );
808 proxy = QNetworkProxy( proxyType, proxyHost, proxyPort, proxyUser, proxyPassword );
811 const QString authcfg = settings.
value( u
"proxy/authcfg"_s,
"" ).toString();
812 if ( !authcfg.isEmpty() )
815 QgsDebugMsgLevel( u
"setting proxy from stored authentication configuration %1"_s.arg( authcfg ), 2 );
818 authManager->updateNetworkProxy( proxy, authcfg );
820 QgsDebugError( u
"Auth manager is not available - cannot update network proxy for authcfg: %1"_s.arg( authcfg ) );
832 if ( cacheDirectory.isEmpty() )
833 cacheDirectory = QStandardPaths::writableLocation( QStandardPaths::CacheLocation );
841 if ( cache() != newcache )
842 setCache( newcache );
844 if (
this != sMainNAM )
846 static_cast<QgsNetworkCookieJar *
>( cookieJar() )->setAllCookies(
static_cast<QgsNetworkCookieJar *
>( sMainNAM->cookieJar() )->allCookies() );
850void QgsNetworkAccessManager::syncCookies(
const QList<QNetworkCookie> &cookies )
852 if ( sender() !=
this )
854 static_cast<QgsNetworkCookieJar *
>( cookieJar() )->setAllCookies( cookies );
855 if (
this == sMainNAM )
876 br.
get( request, forceRefresh, feedback );
886 ( void ) br.
post( request, data, forceRefresh, feedback );
892 QString
id = QUuid::createUuid().toString();
893 sCustomPreprocessors.emplace_back( std::make_pair(
id, processor ) );
899 const size_t prevCount = sCustomPreprocessors.size();
900 sCustomPreprocessors.erase(
901 std::remove_if( sCustomPreprocessors.begin(), sCustomPreprocessors.end(), [
id]( std::pair< QString, std::function<
void( QNetworkRequest * ) > > &a ) { return a.first == id; } ),
902 sCustomPreprocessors.end()
904 return prevCount != sCustomPreprocessors.size();
909 const size_t prevCount = sCustomAdvancedPreprocessors.size();
910 sCustomAdvancedPreprocessors.erase(
912 sCustomAdvancedPreprocessors.begin(),
913 sCustomAdvancedPreprocessors.end(),
914 [
id]( std::pair< QString, std::function<
void( QNetworkRequest *,
int &, QByteArray * ) > > &a ) { return a.first == id; }
916 sCustomAdvancedPreprocessors.end()
918 return prevCount != sCustomAdvancedPreprocessors.size();
923 QString
id = QUuid::createUuid().toString();
924 sCustomAdvancedPreprocessors.emplace_back( std::make_pair(
id, processor ) );
930 QString
id = QUuid::createUuid().toString();
931 sCustomReplyPreprocessors.emplace_back( std::make_pair(
id, processor ) );
937 const size_t prevCount = sCustomReplyPreprocessors.size();
938 sCustomReplyPreprocessors.erase(
940 sCustomReplyPreprocessors.begin(), sCustomReplyPreprocessors.end(), [
id]( std::pair< QString, std::function<
void(
const QNetworkRequest &, QNetworkReply * ) > > &a ) { return a.first == id; }
942 sCustomReplyPreprocessors.end()
944 return prevCount != sCustomReplyPreprocessors.size();
949 for (
const auto &preprocessor : sCustomPreprocessors )
951 preprocessor.second( req );
963 , mOriginatingThreadId( u
"0x%2"_s.arg( reinterpret_cast<quintptr>( QThread::currentThread() ), 2 * QT_POINTER_SIZE, 16,
'0'_L1 ) )
978 QgsDebugError( u
"SSL errors occurred accessing URL:\n%1"_s.arg( reply->request().url().toString() ) );
988 QgsDebugError( u
"Network reply required authentication, but no handler was in place to provide this authentication request while accessing the URL:\n%1"_s.arg( reply->request().url().toString() ) );
994 QgsDebugError( u
"Network authentication required external browser to open URL %1, but no handler was in place"_s.arg( url.toString() ) );
999 QgsDebugError( u
"Network authentication required external browser closed, but no handler was in place"_s );
1003#include "qgsnetworkaccessmanager.moc"
QFlags< NetworkRequestFlag > NetworkRequestFlags
Flags controlling behavior of network requests.
static int versionInt()
Version number used for comparing versions using the "Check QGIS Version" function.
static QgsAuthManager * authManager()
Returns the application's authentication manager instance.
Configuration container for SSL server connection exceptions or overrides.
QSsl::SslProtocol sslProtocol() const
SSL server protocol to use in connections.
int sslPeerVerifyDepth() const
Number or SSL client's peer to verify in connections.
bool isNull() const
Whether configuration is null (missing components).
QSslSocket::PeerVerifyMode sslPeerVerifyMode() const
SSL client's peer verify mode to use in connections.
Singleton which offers an interface to manage the authentication configuration database and to utiliz...
const QgsAuthConfigSslServer sslCertCustomConfigByHost(const QString &hostport)
sslCertCustomConfigByHost get an SSL certificate custom config by hostport (host:port)
A thread safe class for performing blocking (sync) network requests, with full support for QGIS proxy...
ErrorCode post(QNetworkRequest &request, QIODevice *data, bool forceRefresh=false, QgsFeedback *feedback=nullptr)
Performs a "post" operation on the specified request, using the given data.
void setAuthCfg(const QString &authCfg)
Sets the authentication config id which should be used during the request.
ErrorCode get(QNetworkRequest &request, bool forceRefresh=false, QgsFeedback *feedback=nullptr, RequestFlags requestFlags=QgsBlockingNetworkRequest::RequestFlags())
Performs a "get" operation on the specified request.
QgsNetworkReplyContent reply() const
Returns the content of the network reply, after a get(), post(), head() or put() request has been mad...
Base class for feedback objects to be used for cancellation of something running in a worker thread.
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true, const char *file=__builtin_FILE(), const char *function=__builtin_FUNCTION(), int line=__builtin_LINE(), Qgis::StringFormat format=Qgis::StringFormat::PlainText)
Adds a message to the log instance (and creates it if necessary).
QNetworkAccessManager with additional QGIS specific logic.
QStringList noProxyList() const
Returns the no proxy list.
void finished(QgsNetworkReplyContent reply)
Emitted whenever a pending network reply is finished.
static const QgsSettingsEntryInteger * settingsNetworkTimeout
Settings entry network timeout.
void cookiesChanged(const QList< QNetworkCookie > &cookies)
Emitted when the cookies changed.
void insertProxyFactory(QNetworkProxyFactory *factory)
Inserts a factory into the proxy factories list.
void setSslErrorHandler(std::unique_ptr< QgsSslErrorHandler > handler)
Sets the application SSL error handler, which is used to respond to SSL errors encountered during net...
Q_DECL_DEPRECATED void requestAboutToBeCreated(QNetworkAccessManager::Operation operation, const QNetworkRequest &request, QIODevice *device)
void abortAuthBrowser()
Abort any outstanding external browser login request.
void setCacheDisabled(bool disabled)
Sets whether all network caching should be disabled.
const QList< QNetworkProxyFactory * > proxyFactories() const
Returns a list of proxy factories used by the manager.
void downloadProgress(int requestId, qint64 bytesReceived, qint64 bytesTotal)
Emitted when a network reply receives a progress report.
void requestAuthOpenBrowser(const QUrl &url) const
Forwards an external browser login url opening request to the authentication handler.
void requestAuthCloseBrowser() const
Forwards an external browser login closure request to the authentication handler.
void requestEncounteredSslErrors(int requestId, const QList< QSslError > &errors)
Emitted when a network request encounters SSL errors.
static QString cacheLoadControlName(QNetworkRequest::CacheLoadControl control)
Returns the name for QNetworkRequest::CacheLoadControl.
void requestCreated(const QgsNetworkRequestParameters &request)
Emitted when a network request has been created.
static QgsNetworkReplyContent blockingGet(QNetworkRequest &request, const QString &authCfg=QString(), bool forceRefresh=false, QgsFeedback *feedback=nullptr, Qgis::NetworkRequestFlags flags=Qgis::NetworkRequestFlags())
Posts a GET request to obtain the contents of the target request and returns a new QgsNetworkReplyCon...
static QString setReplyPreprocessor(const std::function< void(const QNetworkRequest &, QNetworkReply *)> &processor)
Sets a reply pre-processor function, which allows manipulation of QNetworkReply objects after they ar...
static bool removeRequestPreprocessor(const QString &id)
Removes the custom request pre-processor function with matching id.
void requestAuthDetailsAdded(int requestId, const QString &realm, const QString &user, const QString &password)
Emitted when network authentication details have been added to a request.
static QNetworkRequest::CacheLoadControl cacheLoadControlFromName(const QString &name)
Returns QNetworkRequest::CacheLoadControl from a name.
static bool removeAdvancedRequestPreprocessor(const QString &id)
Removes an advanced request pre-processor function with matching id.
QgsNetworkAccessManager(QObject *parent=nullptr)
void requestRequiresAuth(int requestId, const QString &realm)
Emitted when a network request prompts an authentication request.
void preprocessRequest(QNetworkRequest *req) const
Preprocesses request.
void setAuthHandler(std::unique_ptr< QgsNetworkAuthenticationHandler > handler)
Sets the application network authentication handler, which is used to respond to network authenticati...
static void setTimeout(int time)
Sets the maximum timeout time for network requests, in milliseconds.
static QString setAdvancedRequestPreprocessor(const std::function< void(QNetworkRequest *, int &op, QByteArray *data)> &processor)
Sets an advanced request pre-processor function, which allows manipulation of a network request befor...
const QNetworkProxy & fallbackProxy() const
Returns the fallback proxy used by the manager.
static QgsNetworkReplyContent blockingPost(QNetworkRequest &request, const QByteArray &data, const QString &authCfg=QString(), bool forceRefresh=false, QgsFeedback *feedback=nullptr, Qgis::NetworkRequestFlags flags=Qgis::NetworkRequestFlags())
Posts a POST request to obtain the contents of the target request, using the given data,...
static int timeout()
Returns the network timeout length, in milliseconds.
void setupDefaultProxyAndCache(Qt::ConnectionType connectionType=Qt::BlockingQueuedConnection)
Setup the QgsNetworkAccessManager (NAM) according to the user's settings.
static QString setRequestPreprocessor(const std::function< void(QNetworkRequest *request)> &processor)
Sets a request pre-processor function, which allows manipulation of a network request before it is pr...
void setFallbackProxyAndExcludes(const QNetworkProxy &proxy, const QStringList &excludes, const QStringList &noProxyURLs)
Sets the fallback proxy and URLs which shouldn't use it.
static bool removeReplyPreprocessor(const QString &id)
Removes the custom reply pre-processor function with matching id.
QStringList excludeList() const
Returns the proxy exclude list.
static QgsNetworkAccessManager * instance(Qt::ConnectionType connectionType=Qt::BlockingQueuedConnection)
Returns a pointer to the active QgsNetworkAccessManager for the current thread.
void removeProxyFactory(QNetworkProxyFactory *factory)
Removes a factory from the proxy factories list.
void authBrowserAborted()
Emitted when external browser logins are to be aborted.
void requestTimedOut(QgsNetworkRequestParameters request)
Emitted when a network request has timed out.
bool useSystemProxy() const
Returns whether the system proxy should be used.
QNetworkReply * createRequest(QNetworkAccessManager::Operation op, const QNetworkRequest &req, QIODevice *outgoingData=nullptr) override
virtual void handleAuthRequest(QNetworkReply *reply, QAuthenticator *auth)
Called whenever network authentication requests are encountered during a network reply.
virtual void handleAuthRequestCloseBrowser()
Called to terminate a network authentication through external browser.
virtual void handleAuthRequestOpenBrowser(const QUrl &url)
Called to initiate a network authentication through external browser url.
Wrapper implementation of QNetworkDiskCache with all methods guarded by a mutex solely for internal u...
void setCacheDirectory(const QString &cacheDir)
qint64 maximumCacheSize() const
void setMaximumCacheSize(qint64 size)
QString cacheDirectory() const
Encapsulates a network reply within a container which is inexpensive to copy and safe to pass between...
Encapsulates parameters and properties of a network request.
int requestId() const
Returns a unique ID identifying the request.
@ AttributeInitiatorClass
Class name of original object which created the request.
@ AttributeInitiatorRequestId
Internal ID used by originator object to identify requests.
QgsNetworkRequestParameters()=default
QNetworkAccessManager::Operation operation() const
Returns the request operation, e.g.
QNetworkRequest request() const
Returns the network request.
QByteArray content() const
Returns the request's content.
An integer settings entry.
static const QgsSettingsEntryInteger64 * settingsNetworkCacheSize
Settings entry network cache directory.
static const QgsSettingsEntryString * settingsNetworkCacheDirectory
Settings entry network cache directory.
static QgsSettingsTreeNode * sTreeNetwork
Stores settings for use within QGIS.
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
virtual void handleSslErrors(QNetworkReply *reply, const QList< QSslError > &errors)
Called whenever SSL errors are encountered during a network reply.
#define Q_NOWARN_DEPRECATED_POP
#define Q_NOWARN_DEPRECATED_PUSH
#define QgsDebugMsgLevel(str, level)
#define QgsDebugError(str)