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