QGIS API Documentation 4.1.0-Master (5bf3c20f3c9)
Loading...
Searching...
No Matches
qgsnetworkaccessmanager.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsnetworkaccessmanager.cpp
3 This class implements a QNetworkManager with the ability to chain in
4 own proxy factories.
5
6 -------------------
7 begin : 2010-05-08
8 copyright : (C) 2010 by Juergen E. Fischer
9 email : jef at norbit dot de
10
11***************************************************************************/
12
13/***************************************************************************
14 * *
15 * This program is free software; you can redistribute it and/or modify *
16 * it under the terms of the GNU General Public License as published by *
17 * the Free Software Foundation; either version 2 of the License, or *
18 * (at your option) any later version. *
19 * *
20 ***************************************************************************/
21
23
24#include "qgis.h"
25#include "qgsapplication.h"
26#include "qgsauthmanager.h"
28#include "qgslogger.h"
29#include "qgsmessagelog.h"
30#include "qgsnetworkdiskcache.h"
31#include "qgsnetworkreply.h"
32#include "qgssettings.h"
35#include "qgssettingstree.h"
36
37#include <QAuthenticator>
38#include <QBuffer>
39#include <QNetworkReply>
40#include <QRecursiveMutex>
41#include <QStandardPaths>
42#include <QString>
43#include <QThreadStorage>
44#include <QTimer>
45#include <QUrl>
46#include <QUuid>
47
48#include "moc_qgsnetworkaccessmanager.cpp"
49
50using namespace Qt::StringLiterals;
51
52const QgsSettingsEntryInteger *QgsNetworkAccessManager::settingsNetworkTimeout = new QgsSettingsEntryInteger( u"network-timeout"_s, QgsSettingsTree::sTreeNetwork, 60000, QObject::tr( "Network timeout" ) );
53
54#ifndef QT_NO_SSL
55#include <QSslConfiguration>
56#endif
57
58#include "qgsnetworkdiskcache.h"
59#include "qgsauthmanager.h"
60
61QgsNetworkAccessManager *QgsNetworkAccessManager::sMainNAM = nullptr;
62
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;
66
68class QgsNetworkProxyFactory : public QNetworkProxyFactory
69{
70 public:
71 QgsNetworkProxyFactory() = default;
72
73 QList<QNetworkProxy> queryProxy( const QNetworkProxyQuery &query = QNetworkProxyQuery() ) override
74 {
75 QgsNetworkAccessManager *nam = QgsNetworkAccessManager::instance();
76
77 // iterate proxies factories and take first non empty list
78 const auto constProxyFactories = nam->proxyFactories();
79 for ( QNetworkProxyFactory *f : constProxyFactories )
80 {
81 QList<QNetworkProxy> systemproxies = QNetworkProxyFactory::systemProxyForQuery( query );
82 if ( !systemproxies.isEmpty() )
83 return systemproxies;
84
85 QList<QNetworkProxy> proxies = f->queryProxy( query );
86 if ( !proxies.isEmpty() )
87 return proxies;
88 }
89
90 // no proxies from the proxy factory list check for excludes
91 if ( query.queryType() != QNetworkProxyQuery::UrlRequest )
92 return QList<QNetworkProxy>() << nam->fallbackProxy();
93
94 const QString url = query.url().toString();
95
96 const auto constNoProxyList = nam->noProxyList();
97 for ( const QString &noProxy : constNoProxyList )
98 {
99 if ( !noProxy.trimmed().isEmpty() && url.startsWith( noProxy ) )
100 {
101 QgsDebugMsgLevel( u"don't using any proxy for %1 [exclude %2]"_s.arg( url, noProxy ), 4 );
102 return QList<QNetworkProxy>() << QNetworkProxy( QNetworkProxy::NoProxy );
103 }
104 }
105
106 const auto constExcludeList = nam->excludeList();
107 for ( const QString &exclude : constExcludeList )
108 {
109 if ( !exclude.trimmed().isEmpty() && url.startsWith( exclude ) )
110 {
111 QgsDebugMsgLevel( u"using default proxy for %1 [exclude %2]"_s.arg( url, exclude ), 4 );
112 return QList<QNetworkProxy>() << QNetworkProxy( QNetworkProxy::DefaultProxy );
113 }
114 }
115
116 if ( nam->useSystemProxy() )
117 {
118 QgsDebugMsgLevel( u"requesting system proxy for query %1"_s.arg( url ), 4 );
119 QList<QNetworkProxy> proxies = QNetworkProxyFactory::systemProxyForQuery( query );
120 if ( !proxies.isEmpty() )
121 {
122 QgsDebugMsgLevel( u"using system proxy %1:%2 for query"_s.arg( proxies.first().hostName() ).arg( proxies.first().port() ), 4 );
123 return proxies;
124 }
125 }
126
127 QgsDebugMsgLevel( u"using fallback proxy for %1"_s.arg( url ), 4 );
128 return QList<QNetworkProxy>() << nam->fallbackProxy();
129 }
130};
132
134class QgsNetworkCookieJar : public QNetworkCookieJar
135{
136 Q_OBJECT
137
138 public:
139 QgsNetworkCookieJar( QgsNetworkAccessManager *parent )
140 : QNetworkCookieJar( parent )
141 , mNam( parent )
142 {}
143
144 bool deleteCookie( const QNetworkCookie &cookie ) override
145 {
146 const QMutexLocker locker( &mMutex );
147 if ( QNetworkCookieJar::deleteCookie( cookie ) )
148 {
149 emit mNam->cookiesChanged( allCookies() );
150 return true;
151 }
152 return false;
153 }
154 bool insertCookie( const QNetworkCookie &cookie ) override
155 {
156 const QMutexLocker locker( &mMutex );
157 if ( QNetworkCookieJar::insertCookie( cookie ) )
158 {
159 emit mNam->cookiesChanged( allCookies() );
160 return true;
161 }
162 return false;
163 }
164 bool setCookiesFromUrl( const QList<QNetworkCookie> &cookieList, const QUrl &url ) override
165 {
166 const QMutexLocker locker( &mMutex );
167 return QNetworkCookieJar::setCookiesFromUrl( cookieList, url );
168 }
169 bool updateCookie( const QNetworkCookie &cookie ) override
170 {
171 const QMutexLocker locker( &mMutex );
172 if ( QNetworkCookieJar::updateCookie( cookie ) )
173 {
174 emit mNam->cookiesChanged( allCookies() );
175 return true;
176 }
177 return false;
178 }
179
180 // Override these to make them public
181 QList<QNetworkCookie> allCookies() const
182 {
183 const QMutexLocker locker( &mMutex );
184 return QNetworkCookieJar::allCookies();
185 }
186 void setAllCookies( const QList<QNetworkCookie> &cookieList )
187 {
188 const QMutexLocker locker( &mMutex );
189 QNetworkCookieJar::setAllCookies( cookieList );
190 }
191
192 QgsNetworkAccessManager *mNam = nullptr;
193 mutable QRecursiveMutex mMutex;
194};
196
197
198//
199// Static calls to enforce singleton behavior
200//
202{
203 static QThreadStorage<QgsNetworkAccessManager> sInstances;
204 QgsNetworkAccessManager *nam = &sInstances.localData();
205
206 if ( nam->thread() == qApp->thread() )
207 sMainNAM = nam;
208
209 if ( !nam->mInitialized )
210 {
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 );
212 nam->setupDefaultProxyAndCache( connectionType );
213 nam->setCacheDisabled( sMainNAM->cacheDisabled() );
214 }
215 else
216 {
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 );
218 }
219
220 return nam;
221}
222
224 : QNetworkAccessManager( parent )
225 , mSslErrorHandlerSemaphore( 1 )
226 , mAuthRequestHandlerSemaphore( 1 )
227{
228 setRedirectPolicy( QNetworkRequest::NoLessSafeRedirectPolicy );
229 setProxyFactory( new QgsNetworkProxyFactory() );
230 setCookieJar( new QgsNetworkCookieJar( this ) );
231 enableStrictTransportSecurityStore( true );
232 setStrictTransportSecurityEnabled( true );
233}
234
235void QgsNetworkAccessManager::setSslErrorHandler( std::unique_ptr<QgsSslErrorHandler> handler )
236{
237 Q_ASSERT( sMainNAM == this );
238 mSslErrorHandler = std::move( handler );
239}
240
241void QgsNetworkAccessManager::setAuthHandler( std::unique_ptr<QgsNetworkAuthenticationHandler> handler )
242{
243 Q_ASSERT( sMainNAM == this );
244 mAuthHandler = std::move( handler );
245}
246
247void QgsNetworkAccessManager::insertProxyFactory( QNetworkProxyFactory *factory )
248{
249 mProxyFactories.insert( 0, factory );
250}
251
252void QgsNetworkAccessManager::removeProxyFactory( QNetworkProxyFactory *factory )
253{
254 mProxyFactories.removeAll( factory );
255}
256
257const QList<QNetworkProxyFactory *> QgsNetworkAccessManager::proxyFactories() const
258{
259 return mProxyFactories;
260}
261
263{
264 return mExcludedURLs;
265}
266
268{
269 return mNoProxyURLs;
270}
271
272const QNetworkProxy &QgsNetworkAccessManager::fallbackProxy() const
273{
274 return mFallbackProxy;
275}
276
277void QgsNetworkAccessManager::setFallbackProxyAndExcludes( const QNetworkProxy &proxy, const QStringList &excludes, const QStringList &noProxyURLs )
278{
280 u"proxy settings: (type:%1 host: %2:%3, user:%4, password:%5"_s
281 .arg(
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
288 : u"Undefined"_s,
289 proxy.hostName()
290 )
291 .arg( proxy.port() )
292 .arg( proxy.user(), proxy.password().isEmpty() ? u"not set"_s : u"set"_s ),
293 4
294 );
295
296 mFallbackProxy = proxy;
297 mExcludedURLs = excludes;
298 // remove empty records from excludes list -- these would otherwise match ANY url, so the proxy would always be skipped!
299 mExcludedURLs.erase(
300 std::remove_if(
301 mExcludedURLs.begin(),
302 mExcludedURLs.end(), // clazy:exclude=detaching-member
303 []( const QString &url ) { return url.trimmed().isEmpty(); }
304 ),
305 mExcludedURLs.end()
306 ); // clazy:exclude=detaching-member
307
308 mNoProxyURLs = noProxyURLs;
309 mNoProxyURLs.erase(
310 std::remove_if(
311 mNoProxyURLs.begin(),
312 mNoProxyURLs.end(), // clazy:exclude=detaching-member
313 []( const QString &url ) { return url.trimmed().isEmpty(); }
314 ),
315 mNoProxyURLs.end()
316 ); // clazy:exclude=detaching-member
317}
318
319QNetworkReply *QgsNetworkAccessManager::createRequest( QNetworkAccessManager::Operation op, const QNetworkRequest &req, QIODevice *outgoingData )
320{
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 );
322
323 const QgsSettings s;
324
325 // copy request so we can modify it
326 QNetworkRequest modifiedRequest( req );
327
328 QString userAgent = s.value( u"/qgis/networkAndProxy/userAgent"_s, "Mozilla/5.0" ).toString();
329 if ( !userAgent.isEmpty() )
330 userAgent += ' ';
331 userAgent += u"QGIS/%1/%2"_s.arg( Qgis::versionInt() ).arg( QSysInfo::prettyProductName() );
332 modifiedRequest.setRawHeader( "User-Agent", userAgent.toLatin1() );
333
334#ifndef QT_NO_SSL
335 const bool ishttps = modifiedRequest.url().scheme().compare( "https"_L1, Qt::CaseInsensitive ) == 0;
336 if ( ishttps && !QgsApplication::authManager()->isDisabled() )
337 {
338 QgsDebugMsgLevel( u"Adding trusted CA certs to request"_s, 3 );
339 QSslConfiguration sslconfig( modifiedRequest.sslConfiguration() );
340 // Merge trusted CAs with any additional CAs added by the authentication methods
341 sslconfig.setCaCertificates( QgsAuthCertUtils::casMerge( QgsApplication::authManager()->trustedCaCertsCache(), sslconfig.caCertificates() ) );
342 // check for SSL cert custom config
343 const QString hostport( u"%1:%2"_s.arg( modifiedRequest.url().host().trimmed() ).arg( modifiedRequest.url().port() != -1 ? modifiedRequest.url().port() : 443 ) );
344 const QgsAuthConfigSslServer servconfig = QgsApplication::authManager()->sslCertCustomConfigByHost( hostport.trimmed() );
345 if ( !servconfig.isNull() )
346 {
347 QgsDebugMsgLevel( u"Adding SSL custom config to request for %1"_s.arg( hostport ), 2 );
348 sslconfig.setProtocol( servconfig.sslProtocol() );
349 sslconfig.setPeerVerifyMode( servconfig.sslPeerVerifyMode() );
350 sslconfig.setPeerVerifyDepth( servconfig.sslPeerVerifyDepth() );
351 }
352
353 modifiedRequest.setSslConfiguration( sslconfig );
354 }
355#endif
356
357 if ( modifiedRequest.url().port() != -1 )
358 {
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 );
362 if ( isDefaultPort )
363 {
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 );
367 }
368 }
369
370 if ( sMainNAM->mCacheDisabled )
371 {
372 // if caching is disabled then we override whatever the request actually has set!
373 modifiedRequest.setAttribute( QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::AlwaysNetwork );
374 modifiedRequest.setAttribute( QNetworkRequest::CacheSaveControlAttribute, false );
375 }
376
377 for ( const auto &preprocessor : sCustomPreprocessors )
378 {
379 preprocessor.second( &modifiedRequest );
380 }
381
382 static QAtomicInt sRequestId = 0;
383 const int requestId = ++sRequestId;
384 QByteArray content;
385 if ( QBuffer *buffer = qobject_cast<QBuffer *>( outgoingData ) )
386 {
387 content = buffer->buffer();
388 }
389
390 for ( const auto &preprocessor : sCustomAdvancedPreprocessors )
391 {
392 int intOp = static_cast< int >( op );
393 preprocessor.second( &modifiedRequest, intOp, &content );
394 op = static_cast< QNetworkAccessManager::Operation >( intOp );
395 }
396
397 bool needsCachePendingRequestCleanup = false;
398 if ( QgsNetworkDiskCache *diskCache = qobject_cast< QgsNetworkDiskCache * >( cache() ) )
399 {
400 if ( modifiedRequest.attribute( QNetworkRequest::CacheLoadControlAttribute ) != QNetworkRequest::AlwaysNetwork )
401 {
402 // if we are going to attempt to retrieve this request from cache, first do some checks
403 // on the version in the cache
404 if ( diskCache->hasInvalidMatchForRequest( modifiedRequest ) )
405 {
406 // can't use the previously cached response for this request, so explicitly block that
407 modifiedRequest.setAttribute( QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::AlwaysNetwork );
408 modifiedRequest.setAttribute( QNetworkRequest::CacheSaveControlAttribute, false );
409 }
410 }
411
412 if ( modifiedRequest.attribute( QNetworkRequest::CacheSaveControlAttribute, true ).toBool() )
413 {
414 if ( diskCache->hasPendingRequestForUrl( modifiedRequest.url() ) )
415 {
416 // don't allow multiple requests to attempt to write to the same cache resource
417 modifiedRequest.setAttribute( QNetworkRequest::CacheSaveControlAttribute, false );
418 }
419 else
420 {
421 QVariantMap currentHeaders;
422 const QList<QByteArray> rawHeaderList = modifiedRequest.rawHeaderList();
423 for ( const QByteArray &header : rawHeaderList )
424 {
425 currentHeaders.insert( QString::fromUtf8( header ).toLower(), modifiedRequest.rawHeader( header ) );
426 }
427 diskCache->insertPendingRequestHeaders( modifiedRequest.url(), currentHeaders );
428 needsCachePendingRequestCleanup = true;
429 }
430 }
431 }
432
433 emit requestAboutToBeCreated( QgsNetworkRequestParameters( op, modifiedRequest, requestId, content ) );
435 emit requestAboutToBeCreated( op, modifiedRequest, outgoingData );
437 QNetworkReply *reply = QNetworkAccessManager::createRequest( op, modifiedRequest, outgoingData );
438 reply->setProperty( "requestId", requestId );
439
440 emit requestCreated( QgsNetworkRequestParameters( op, reply->request(), requestId, content ) );
442 emit requestCreated( reply );
444
445 connect( reply, &QNetworkReply::downloadProgress, this, &QgsNetworkAccessManager::onReplyDownloadProgress );
446#ifndef QT_NO_SSL
447 connect( reply, &QNetworkReply::sslErrors, this, &QgsNetworkAccessManager::onReplySslErrors );
448#endif
449
450 for ( const auto &replyPreprocessor : sCustomReplyPreprocessors )
451 {
452 replyPreprocessor.second( modifiedRequest, reply );
453 }
454
455 if ( needsCachePendingRequestCleanup )
456 {
457 if ( QgsNetworkDiskCache *diskCache = qobject_cast< QgsNetworkDiskCache * >( cache() ) )
458 {
459 const QUrl url = modifiedRequest.url();
460 connect( reply, &QNetworkReply::finished, diskCache, [url, diskCache] { diskCache->removePendingRequestForUrl( url ); } );
461 }
462 }
463
464 // The timer will call abortRequest slot to abort the connection if needed.
465 // The timer is stopped by the finished signal and is restarted on downloadProgress and
466 // uploadProgress.
467 if ( timeout() )
468 {
469 QTimer *timer = new QTimer( reply );
470 timer->setObjectName( u"timeoutTimer"_s );
471 connect( timer, &QTimer::timeout, this, &QgsNetworkAccessManager::abortRequest );
472 timer->setSingleShot( true );
473 timer->start( timeout() );
474
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 );
478 }
479 QgsDebugMsgLevel( u"Created [reply:%1]"_s.arg( reinterpret_cast< qint64 >( reply ), 0, 16 ), 3 );
480
481 return reply;
482}
483
484void QgsNetworkAccessManager::abortRequest()
485{
486 QTimer *timer = qobject_cast<QTimer *>( sender() );
487 Q_ASSERT( timer );
488
489 QNetworkReply *reply = qobject_cast<QNetworkReply *>( timer->parent() );
490 Q_ASSERT( reply );
491
492 reply->abort();
493 QgsDebugMsgLevel( u"Abort [reply:%1] %2"_s.arg( reinterpret_cast< qint64 >( reply ), 0, 16 ).arg( reply->url().toString() ), 3 );
494 QgsMessageLog::logMessage( tr( "Network request %1 timed out" ).arg( reply->url().toString() ), tr( "Network" ) );
495 // Notify the application
496 emit requestTimedOut( QgsNetworkRequestParameters( reply->operation(), reply->request(), getRequestId( reply ) ) );
497 emit requestTimedOut( reply );
498}
499
500void QgsNetworkAccessManager::onReplyFinished( QNetworkReply *reply )
501{
502 emit finished( QgsNetworkReplyContent( reply ) );
503}
504
505void QgsNetworkAccessManager::onReplyDownloadProgress( qint64 bytesReceived, qint64 bytesTotal )
506{
507 if ( QNetworkReply *reply = qobject_cast< QNetworkReply *>( sender() ) )
508 {
509 emit downloadProgress( getRequestId( reply ), bytesReceived, bytesTotal );
510 }
511}
512
513int QgsNetworkAccessManager::getRequestId( QNetworkReply *reply )
514{
515 return reply->property( "requestId" ).toInt();
516}
517
518void QgsNetworkAccessManager::pauseTimeout( QNetworkReply *reply )
519{
520 Q_ASSERT( reply->manager() == this );
521
522 QTimer *timer = reply->findChild<QTimer *>( u"timeoutTimer"_s );
523 if ( timer && timer->isActive() )
524 {
525 timer->stop();
526 }
527}
528
529void QgsNetworkAccessManager::restartTimeout( QNetworkReply *reply )
530{
531 Q_ASSERT( reply->manager() == this );
532 // restart reply timeout
533 QTimer *timer = reply->findChild<QTimer *>( u"timeoutTimer"_s );
534 if ( timer )
535 {
536 Q_ASSERT( !timer->isActive() );
537 QgsDebugMsgLevel( u"Restarting network reply timeout"_s, 2 );
538 timer->setSingleShot( true );
539 timer->start( timeout() );
540 }
541}
542
543void QgsNetworkAccessManager::afterAuthRequestHandled( QNetworkReply *reply )
544{
545 if ( reply->manager() == this )
546 {
547 restartTimeout( reply );
548 emit authRequestHandled( reply );
549 }
550}
551
552#ifndef QT_NO_SSL
553void QgsNetworkAccessManager::onReplySslErrors( const QList<QSslError> &errors )
554{
555 QNetworkReply *reply = qobject_cast< QNetworkReply *>( sender() );
556 Q_ASSERT( reply );
557 Q_ASSERT( reply->manager() == this );
558
559 QgsDebugMsgLevel( u"Stopping network reply timeout whilst SSL error is handled"_s, 2 );
560 pauseTimeout( reply );
561
562 emit requestEncounteredSslErrors( getRequestId( reply ), errors );
563
564 // acquire semaphore a first time, so we block next acquire until release is called
565 mSslErrorHandlerSemaphore.acquire();
566
567 // in main thread this will trigger SSL error handler immediately and return once the errors are handled,
568 // while in worker thread the signal will be queued (and return immediately) -- hence the need to lock the thread in the next block
569 emit sslErrorsOccurred( reply, errors );
570 if ( this != sMainNAM )
571 {
572 // lock thread and wait till error is handled. If we return from this slot now, then the reply will resume
573 // without actually giving the main thread the chance to act on the ssl error and possibly ignore it.
574 mSslErrorHandlerSemaphore.acquire();
575 mSslErrorHandlerSemaphore.release();
576 afterSslErrorHandled( reply );
577 }
578}
579
580void QgsNetworkAccessManager::afterSslErrorHandled( QNetworkReply *reply )
581{
582 if ( reply->manager() == this )
583 {
584 restartTimeout( reply );
585 emit sslErrorsHandled( reply );
586 }
587}
588
589void QgsNetworkAccessManager::handleSslErrors( QNetworkReply *reply, const QList<QSslError> &errors )
590{
591 mSslErrorHandler->handleSslErrors( reply, errors );
592 afterSslErrorHandled( reply );
593 qobject_cast<QgsNetworkAccessManager *>( reply->manager() )->mSslErrorHandlerSemaphore.release();
594}
595
596#endif
597
598void QgsNetworkAccessManager::onAuthRequired( QNetworkReply *reply, QAuthenticator *auth )
599{
600 Q_ASSERT( reply );
601 Q_ASSERT( reply->manager() == this );
602
603 QgsDebugMsgLevel( u"Stopping network reply timeout whilst auth request is handled"_s, 2 );
604 pauseTimeout( reply );
605
606 emit requestRequiresAuth( getRequestId( reply ), auth->realm() );
607
608 // acquire semaphore a first time, so we block next acquire until release is called
609 mAuthRequestHandlerSemaphore.acquire();
610
611 // in main thread this will trigger auth handler immediately and return once the request is satisfied,
612 // while in worker thread the signal will be queued (and return immediately) -- hence the need to lock the thread in the next block
613 emit authRequestOccurred( reply, auth );
614
615 if ( this != sMainNAM )
616 {
617 // lock thread and wait till error is handled. If we return from this slot now, then the reply will resume
618 // without actually giving the main thread the chance to act on the ssl error and possibly ignore it.
619 mAuthRequestHandlerSemaphore.acquire();
620 mAuthRequestHandlerSemaphore.release();
621 afterAuthRequestHandled( reply );
622 }
623}
624
626{
627 if ( this != sMainNAM )
628 {
629 sMainNAM->requestAuthOpenBrowser( url );
631 return;
632 }
633 mAuthHandler->handleAuthRequestOpenBrowser( url );
634}
635
637{
638 if ( this != sMainNAM )
639 {
640 sMainNAM->requestAuthCloseBrowser();
642 return;
643 }
644 mAuthHandler->handleAuthRequestCloseBrowser();
645}
646
648{
649 if ( this != sMainNAM )
650 {
652 }
653 emit authBrowserAborted();
654}
655
656void QgsNetworkAccessManager::handleAuthRequest( QNetworkReply *reply, QAuthenticator *auth )
657{
658 mAuthHandler->handleAuthRequest( reply, auth );
659
660 emit requestAuthDetailsAdded( getRequestId( reply ), auth->realm(), auth->user(), auth->password() );
661
662 afterAuthRequestHandled( reply );
663 qobject_cast<QgsNetworkAccessManager *>( reply->manager() )->mAuthRequestHandlerSemaphore.release();
664}
665
666QString QgsNetworkAccessManager::cacheLoadControlName( QNetworkRequest::CacheLoadControl control )
667{
668 switch ( control )
669 {
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;
678 }
679 return u"PreferNetwork"_s;
680}
681
682QNetworkRequest::CacheLoadControl QgsNetworkAccessManager::cacheLoadControlFromName( const QString &name )
683{
684 if ( name == "AlwaysNetwork"_L1 )
685 {
686 return QNetworkRequest::AlwaysNetwork;
687 }
688 else if ( name == "PreferNetwork"_L1 )
689 {
690 return QNetworkRequest::PreferNetwork;
691 }
692 else if ( name == "PreferCache"_L1 )
693 {
694 return QNetworkRequest::PreferCache;
695 }
696 else if ( name == "AlwaysCache"_L1 )
697 {
698 return QNetworkRequest::AlwaysCache;
699 }
700 return QNetworkRequest::PreferNetwork;
701}
702
703void QgsNetworkAccessManager::setupDefaultProxyAndCache( Qt::ConnectionType connectionType )
704{
705 mInitialized = true;
706 mUseSystemProxy = false;
707
708 Q_ASSERT( sMainNAM );
709
710 if ( sMainNAM != this )
711 {
712 connect( this, &QNetworkAccessManager::proxyAuthenticationRequired, sMainNAM, &QNetworkAccessManager::proxyAuthenticationRequired, connectionType );
713
714 connect( this, qOverload< QNetworkReply *>( &QgsNetworkAccessManager::requestTimedOut ), sMainNAM, qOverload< QNetworkReply *>( &QgsNetworkAccessManager::requestTimedOut ) );
715
716 connect( this, qOverload< QgsNetworkRequestParameters >( &QgsNetworkAccessManager::requestTimedOut ), sMainNAM, qOverload< QgsNetworkRequestParameters >( &QgsNetworkAccessManager::requestTimedOut ) );
717
718 connect( this, qOverload< QgsNetworkRequestParameters >( &QgsNetworkAccessManager::requestAboutToBeCreated ), sMainNAM, qOverload< QgsNetworkRequestParameters >( &QgsNetworkAccessManager::requestAboutToBeCreated ) );
719
720 connect( this, qOverload< const QgsNetworkRequestParameters & >( &QgsNetworkAccessManager::requestCreated ), sMainNAM, qOverload< const QgsNetworkRequestParameters & >( &QgsNetworkAccessManager::requestCreated ) );
721
722 connect( this, qOverload< QgsNetworkReplyContent >( &QgsNetworkAccessManager::finished ), sMainNAM, qOverload< QgsNetworkReplyContent >( &QgsNetworkAccessManager::finished ) );
723
725
726#ifndef QT_NO_SSL
727 connect( this, &QNetworkAccessManager::sslErrors, sMainNAM, &QNetworkAccessManager::sslErrors, connectionType );
728
730#endif
731
733 connect( sMainNAM, &QgsNetworkAccessManager::cookiesChanged, this, &QgsNetworkAccessManager::syncCookies );
734 connect( this, &QgsNetworkAccessManager::cookiesChanged, sMainNAM, &QgsNetworkAccessManager::syncCookies );
735 }
736 else
737 {
738#ifndef QT_NO_SSL
739 if ( !mSslErrorHandler )
740 setSslErrorHandler( std::make_unique< QgsSslErrorHandler >() );
741#endif
742 if ( !mAuthHandler )
743 setAuthHandler( std::make_unique< QgsNetworkAuthenticationHandler>() );
744 }
745#ifndef QT_NO_SSL
746 connect( this, &QgsNetworkAccessManager::sslErrorsOccurred, sMainNAM, &QgsNetworkAccessManager::handleSslErrors );
747#endif
748 connect( this, &QNetworkAccessManager::authenticationRequired, this, &QgsNetworkAccessManager::onAuthRequired );
749 connect( this, &QgsNetworkAccessManager::authRequestOccurred, sMainNAM, &QgsNetworkAccessManager::handleAuthRequest );
750
751 connect( this, &QNetworkAccessManager::finished, this, &QgsNetworkAccessManager::onReplyFinished );
752
753 // check if proxy is enabled
754 const QgsSettings settings;
755 QNetworkProxy proxy;
756 QStringList excludes;
757 QStringList noProxyURLs;
758
759 const bool proxyEnabled = settings.value( u"proxy/proxyEnabled"_s, false ).toBool();
760 if ( proxyEnabled )
761 {
762 // This settings is keep for retrocompatibility, the returned proxy for these URL is the default one,
763 // meaning the system one
764 excludes = settings.value( u"proxy/proxyExcludedUrls"_s, QStringList() ).toStringList();
765
766 noProxyURLs = settings.value( u"proxy/noProxyUrls"_s, QStringList() ).toStringList();
767
768 //read type, host, port, user, passw from settings
769 const QString proxyHost = settings.value( u"proxy/proxyHost"_s, "" ).toString();
770 const int proxyPort = settings.value( u"proxy/proxyPort"_s, "" ).toString().toInt();
771
772 const QString proxyUser = settings.value( u"proxy/proxyUser"_s, "" ).toString();
773 const QString proxyPassword = settings.value( u"proxy/proxyPassword"_s, "" ).toString();
774
775 const QString proxyTypeString = settings.value( u"proxy/proxyType"_s, "" ).toString();
776
777 if ( proxyTypeString == "DefaultProxy"_L1 )
778 {
779 mUseSystemProxy = true;
780 QNetworkProxyFactory::setUseSystemConfiguration( true );
781 QList<QNetworkProxy> proxies = QNetworkProxyFactory::systemProxyForQuery();
782 if ( !proxies.isEmpty() )
783 {
784 proxy = proxies.first();
785 }
786 QgsDebugMsgLevel( u"setting default proxy"_s, 4 );
787 }
788 else
789 {
790 QNetworkProxy::ProxyType proxyType = QNetworkProxy::DefaultProxy;
791 if ( proxyTypeString == "Socks5Proxy"_L1 )
792 {
793 proxyType = QNetworkProxy::Socks5Proxy;
794 }
795 else if ( proxyTypeString == "HttpProxy"_L1 )
796 {
797 proxyType = QNetworkProxy::HttpProxy;
798 }
799 else if ( proxyTypeString == "HttpCachingProxy"_L1 )
800 {
801 proxyType = QNetworkProxy::HttpCachingProxy;
802 }
803 else if ( proxyTypeString == "FtpCachingProxy"_L1 )
804 {
805 proxyType = QNetworkProxy::FtpCachingProxy;
806 }
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 );
809 }
810 // Setup network proxy authentication configuration
811 const QString authcfg = settings.value( u"proxy/authcfg"_s, "" ).toString();
812 if ( !authcfg.isEmpty() )
813 {
814#ifdef HAVE_AUTH
815 QgsDebugMsgLevel( u"setting proxy from stored authentication configuration %1"_s.arg( authcfg ), 2 );
816 // Never crash! Never.
817 if ( QgsAuthManager *authManager = QgsApplication::authManager() )
818 authManager->updateNetworkProxy( proxy, authcfg );
819#else
820 QgsDebugError( u"Auth manager is not available - cannot update network proxy for authcfg: %1"_s.arg( authcfg ) );
821#endif
822 }
823 }
824
825 setFallbackProxyAndExcludes( proxy, excludes, noProxyURLs );
826
827 QgsNetworkDiskCache *newcache = qobject_cast<QgsNetworkDiskCache *>( cache() );
828 if ( !newcache )
829 newcache = new QgsNetworkDiskCache( this );
830
831 QString cacheDirectory = QgsSettingsRegistryCore::settingsNetworkCacheDirectory->value();
832 if ( cacheDirectory.isEmpty() )
833 cacheDirectory = QStandardPaths::writableLocation( QStandardPaths::CacheLocation );
834 newcache->setCacheDirectory( cacheDirectory );
835 qint64 cacheSize = QgsSettingsRegistryCore::settingsNetworkCacheSize->value();
836 newcache->setMaximumCacheSize( cacheSize );
837
838 QgsDebugMsgLevel( u"cacheDirectory: %1"_s.arg( newcache->cacheDirectory() ), 4 );
839 QgsDebugMsgLevel( u"maximumCacheSize: %1"_s.arg( newcache->maximumCacheSize() ), 4 );
840
841 if ( cache() != newcache )
842 setCache( newcache );
843
844 if ( this != sMainNAM )
845 {
846 static_cast<QgsNetworkCookieJar *>( cookieJar() )->setAllCookies( static_cast<QgsNetworkCookieJar *>( sMainNAM->cookieJar() )->allCookies() );
847 }
848}
849
850void QgsNetworkAccessManager::syncCookies( const QList<QNetworkCookie> &cookies )
851{
852 if ( sender() != this )
853 {
854 static_cast<QgsNetworkCookieJar *>( cookieJar() )->setAllCookies( cookies );
855 if ( this == sMainNAM )
856 {
857 emit cookiesChanged( cookies );
858 }
859 }
860}
861
863{
864 return settingsNetworkTimeout->value();
865}
866
868{
869 settingsNetworkTimeout->setValue( time );
870}
871
872QgsNetworkReplyContent QgsNetworkAccessManager::blockingGet( QNetworkRequest &request, const QString &authCfg, bool forceRefresh, QgsFeedback *feedback, Qgis::NetworkRequestFlags flags )
873{
874 QgsBlockingNetworkRequest br( flags );
875 br.setAuthCfg( authCfg );
876 br.get( request, forceRefresh, feedback );
877 return br.reply();
878}
879
881 QNetworkRequest &request, const QByteArray &data, const QString &authCfg, bool forceRefresh, QgsFeedback *feedback, Qgis::NetworkRequestFlags flags
882)
883{
884 QgsBlockingNetworkRequest br( flags );
885 br.setAuthCfg( authCfg );
886 ( void ) br.post( request, data, forceRefresh, feedback );
887 return br.reply();
888}
889
890QString QgsNetworkAccessManager::setRequestPreprocessor( const std::function<void( QNetworkRequest * )> &processor )
891{
892 QString id = QUuid::createUuid().toString();
893 sCustomPreprocessors.emplace_back( std::make_pair( id, processor ) );
894 return id;
895}
896
898{
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()
903 );
904 return prevCount != sCustomPreprocessors.size();
905}
906
908{
909 const size_t prevCount = sCustomAdvancedPreprocessors.size();
910 sCustomAdvancedPreprocessors.erase(
911 std::remove_if(
912 sCustomAdvancedPreprocessors.begin(),
913 sCustomAdvancedPreprocessors.end(),
914 [id]( std::pair< QString, std::function< void( QNetworkRequest *, int &, QByteArray * ) > > &a ) { return a.first == id; }
915 ),
916 sCustomAdvancedPreprocessors.end()
917 );
918 return prevCount != sCustomAdvancedPreprocessors.size();
919}
920
921QString QgsNetworkAccessManager::setAdvancedRequestPreprocessor( const std::function<void( QNetworkRequest *, int &, QByteArray * )> &processor )
922{
923 QString id = QUuid::createUuid().toString();
924 sCustomAdvancedPreprocessors.emplace_back( std::make_pair( id, processor ) );
925 return id;
926}
927
928QString QgsNetworkAccessManager::setReplyPreprocessor( const std::function<void( const QNetworkRequest &, QNetworkReply * )> &processor )
929{
930 QString id = QUuid::createUuid().toString();
931 sCustomReplyPreprocessors.emplace_back( std::make_pair( id, processor ) );
932 return id;
933}
934
936{
937 const size_t prevCount = sCustomReplyPreprocessors.size();
938 sCustomReplyPreprocessors.erase(
939 std::remove_if(
940 sCustomReplyPreprocessors.begin(), sCustomReplyPreprocessors.end(), [id]( std::pair< QString, std::function< void( const QNetworkRequest &, QNetworkReply * ) > > &a ) { return a.first == id; }
941 ),
942 sCustomReplyPreprocessors.end()
943 );
944 return prevCount != sCustomReplyPreprocessors.size();
945}
946
947void QgsNetworkAccessManager::preprocessRequest( QNetworkRequest *req ) const
948{
949 for ( const auto &preprocessor : sCustomPreprocessors )
950 {
951 preprocessor.second( req );
952 }
953}
954
955
956//
957// QgsNetworkRequestParameters
958//
959
960QgsNetworkRequestParameters::QgsNetworkRequestParameters( QNetworkAccessManager::Operation operation, const QNetworkRequest &request, int requestId, const QByteArray &content )
961 : mOperation( operation )
962 , mRequest( request )
963 , mOriginatingThreadId( u"0x%2"_s.arg( reinterpret_cast<quintptr>( QThread::currentThread() ), 2 * QT_POINTER_SIZE, 16, '0'_L1 ) )
964 , mRequestId( requestId )
965 , mContent( content )
966 , mInitiatorClass( request.attribute( static_cast< QNetworkRequest::Attribute >( QgsNetworkRequestParameters::AttributeInitiatorClass ) ).toString() )
967 , mInitiatorRequestId( request.attribute( static_cast< QNetworkRequest::Attribute >( QgsNetworkRequestParameters::AttributeInitiatorRequestId ) ) )
968{}
969
970
971//
972// QgsSslErrorHandler
973//
974
975void QgsSslErrorHandler::handleSslErrors( QNetworkReply *reply, const QList<QSslError> & )
976{
977 Q_UNUSED( reply )
978 QgsDebugError( u"SSL errors occurred accessing URL:\n%1"_s.arg( reply->request().url().toString() ) );
979}
980
981//
982// QgsNetworkAuthenticationHandler
983//
984
985void QgsNetworkAuthenticationHandler::handleAuthRequest( QNetworkReply *reply, QAuthenticator * )
986{
987 Q_UNUSED( reply )
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() ) );
989}
990
992{
993 Q_UNUSED( url )
994 QgsDebugError( u"Network authentication required external browser to open URL %1, but no handler was in place"_s.arg( url.toString() ) );
995}
996
998{
999 QgsDebugError( u"Network authentication required external browser closed, but no handler was in place"_s );
1000}
1001
1002// For QgsNetworkCookieJar
1003#include "qgsnetworkaccessmanager.moc"
QFlags< NetworkRequestFlag > NetworkRequestFlags
Flags controlling behavior of network requests.
Definition qgis.h:197
static int versionInt()
Version number used for comparing versions using the "Check QGIS Version" function.
Definition qgis.cpp:687
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.
Definition qgsfeedback.h:44
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)
void setMaximumCacheSize(qint64 size)
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.
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.
Definition qgssettings.h:68
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
Definition qgis.h:7504
#define Q_NOWARN_DEPRECATED_PUSH
Definition qgis.h:7503
#define QgsDebugMsgLevel(str, level)
Definition qgslogger.h:63
#define QgsDebugError(str)
Definition qgslogger.h:59