QGIS API Documentation 4.1.0-Master (467af3bbe65)
Loading...
Searching...
No Matches
qgsblockingnetworkrequest.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsblockingnetworkrequest.cpp
3 -----------------------------
4 begin : November 2018
5 copyright : (C) 2018 by Nyall Dawson
6 email : nyall dot dawson at gmail dot com
7 ***************************************************************************
8 * *
9 * This program is free software; you can redistribute it and/or modify *
10 * it under the terms of the GNU General Public License as published by *
11 * the Free Software Foundation; either version 2 of the License, or *
12 * (at your option) any later version. *
13 * *
14 ***************************************************************************/
15
17
18#include "qgsapplication.h"
19#include "qgsauthmanager.h"
20#include "qgsfeedback.h"
21#include "qgslogger.h"
22#include "qgsmessagelog.h"
24#include "qgsvariantutils.h"
25
26#include <QAuthenticator>
27#include <QBuffer>
28#include <QMutex>
29#include <QNetworkCacheMetaData>
30#include <QNetworkReply>
31#include <QNetworkRequest>
32#include <QString>
33#include <QUrl>
34#include <QWaitCondition>
35
36#include "moc_qgsblockingnetworkrequest.cpp"
37
38using namespace Qt::StringLiterals;
39
41 : mFlags( flags )
42{
43 connect( QgsNetworkAccessManager::instance(), qOverload< QNetworkReply * >( &QgsNetworkAccessManager::requestTimedOut ), this, &QgsBlockingNetworkRequest::requestTimedOut );
44}
45
50
51void QgsBlockingNetworkRequest::requestTimedOut( QNetworkReply *reply )
52{
53 if ( reply == mReply )
54 mTimedout = true;
55}
56
58{
59 return mAuthCfg;
60}
61
63{
64 mAuthCfg = authCfg;
65}
66
67QgsBlockingNetworkRequest::ErrorCode QgsBlockingNetworkRequest::get( QNetworkRequest &request, bool forceRefresh, QgsFeedback *feedback, RequestFlags requestFlags )
68{
69 return doRequest( Qgis::HttpMethod::Get, request, forceRefresh, feedback, requestFlags );
70}
71
72QgsBlockingNetworkRequest::ErrorCode QgsBlockingNetworkRequest::post( QNetworkRequest &request, const QByteArray &data, bool forceRefresh, QgsFeedback *feedback )
73{
74 QByteArray ldata( data );
75 QBuffer buffer( &ldata );
76 buffer.open( QIODevice::ReadOnly );
77 return post( request, &buffer, forceRefresh, feedback );
78}
79
80QgsBlockingNetworkRequest::ErrorCode QgsBlockingNetworkRequest::post( QNetworkRequest &request, QIODevice *data, bool forceRefresh, QgsFeedback *feedback )
81{
82 mPayloadDataVariant = data;
83 return doRequest( Qgis::HttpMethod::Post, request, forceRefresh, feedback );
84}
85
86QgsBlockingNetworkRequest::ErrorCode QgsBlockingNetworkRequest::post( QNetworkRequest &request, QHttpMultiPart *data, bool forceRefresh, QgsFeedback *feedback )
87{
88 mPayloadDataVariant = data;
89 return doRequest( Qgis::HttpMethod::Post, request, forceRefresh, feedback );
90}
91
92QgsBlockingNetworkRequest::ErrorCode QgsBlockingNetworkRequest::head( QNetworkRequest &request, bool forceRefresh, QgsFeedback *feedback )
93{
94 return doRequest( Qgis::HttpMethod::Head, request, forceRefresh, feedback );
95}
96
97QgsBlockingNetworkRequest::ErrorCode QgsBlockingNetworkRequest::put( QNetworkRequest &request, const QByteArray &data, QgsFeedback *feedback )
98{
99 QByteArray ldata( data );
100 QBuffer buffer( &ldata );
101 buffer.open( QIODevice::ReadOnly );
102 return put( request, &buffer, feedback );
103}
104
105QgsBlockingNetworkRequest::ErrorCode QgsBlockingNetworkRequest::put( QNetworkRequest &request, QIODevice *data, QgsFeedback *feedback )
106{
107 mPayloadDataVariant = data;
108 return doRequest( Qgis::HttpMethod::Put, request, true, feedback );
109}
110
112{
113 return doRequest( Qgis::HttpMethod::Delete, request, true, feedback );
114}
115
116void QgsBlockingNetworkRequest::sendRequestToNetworkAccessManager( const QNetworkRequest &request )
117{
118 switch ( mMethod )
119 {
121 mReply = QgsNetworkAccessManager::instance()->get( request );
122 break;
123
125 if ( std::holds_alternative<QHttpMultiPart *>( mPayloadDataVariant ) )
126 {
127 mReply = QgsNetworkAccessManager::instance()->post( request, std::get<QHttpMultiPart *>( mPayloadDataVariant ) );
128 }
129 else if ( std::holds_alternative<QIODevice *>( mPayloadDataVariant ) )
130 {
131 mReply = QgsNetworkAccessManager::instance()->post( request, std::get<QIODevice *>( mPayloadDataVariant ) );
132 }
133 else
134 {
135 // should not happen, but might if someone extends the variant type without updating this code
136 QgsDebugError( QString( "Not implemented std::variant type" ) );
137 }
138 break;
139
141 mReply = QgsNetworkAccessManager::instance()->head( request );
142 break;
143
145 mReply = QgsNetworkAccessManager::instance()->put( request, std::get<QIODevice *>( mPayloadDataVariant ) );
146 break;
147
149 mReply = QgsNetworkAccessManager::instance()->deleteResource( request );
150 break;
151 };
152}
153
154QgsBlockingNetworkRequest::ErrorCode QgsBlockingNetworkRequest::doRequest( Qgis::HttpMethod method, QNetworkRequest &request, bool forceRefresh, QgsFeedback *feedback, RequestFlags requestFlags )
155{
156 mMethod = method;
157 mFeedback = feedback;
158
159 abort(); // cancel previous
160 mIsAborted = false;
161 mTimedout = false;
162 mGotNonEmptyResponse = false;
163 mRequestFlags = requestFlags;
164
165 mErrorMessage.clear();
166 mErrorCode = NoError;
167 mForceRefresh = forceRefresh;
168 mReplyContent.clear();
169
170 if ( !mAuthCfg.isEmpty() && !QgsApplication::authManager()->updateNetworkRequest( request, mAuthCfg ) )
171 {
172 mErrorCode = NetworkError;
173 mErrorMessage = errorMessageFailedAuth();
174 if ( !mFlags.testFlag( Qgis::NetworkRequestFlag::DisableMessageLogging ) )
175 {
176 QgsMessageLog::logMessage( mErrorMessage, tr( "Network" ) );
177 }
178 return NetworkError;
179 }
180
181 QgsDebugMsgLevel( u"Calling: %1"_s.arg( request.url().toString() ), 2 );
182
183 request.setAttribute( QNetworkRequest::RedirectPolicyAttribute, QNetworkRequest::ManualRedirectPolicy );
184 request.setAttribute( QNetworkRequest::CacheLoadControlAttribute, forceRefresh ? QNetworkRequest::AlwaysNetwork : QNetworkRequest::PreferCache );
185 request.setAttribute( QNetworkRequest::CacheSaveControlAttribute, true );
186
187 QWaitCondition authRequestBufferNotEmpty;
188 QMutex waitConditionMutex;
189
190 bool threadFinished = false;
191 bool success = false;
192
193 const bool requestMadeFromMainThread = QThread::currentThread() == QApplication::instance()->thread();
194
195 if ( mFeedback )
196 connect( mFeedback, &QgsFeedback::canceled, this, &QgsBlockingNetworkRequest::abort );
197
198 const std::function<void()> downloaderFunction = [this, request, &waitConditionMutex, &authRequestBufferNotEmpty, &threadFinished, &success, requestMadeFromMainThread]() {
199 // this function will always be run in worker threads -- either the blocking call is being made in a worker thread,
200 // or the blocking call has been made from the main thread and we've fired up a new thread for this function
201 Q_ASSERT( QThread::currentThread() != QgsApplication::instance()->thread() );
202
203 QgsNetworkAccessManager::instance( Qt::DirectConnection );
204
205 success = true;
206
207 sendRequestToNetworkAccessManager( request );
208
209 if ( mFeedback )
210 connect( mFeedback, &QgsFeedback::canceled, mReply, &QNetworkReply::abort );
211
212 if ( !mAuthCfg.isEmpty() && !QgsApplication::authManager()->updateNetworkReply( mReply, mAuthCfg ) )
213 {
214 mErrorCode = NetworkError;
215 mErrorMessage = errorMessageFailedAuth();
216 if ( !mFlags.testFlag( Qgis::NetworkRequestFlag::DisableMessageLogging ) )
217 {
218 QgsMessageLog::logMessage( mErrorMessage, tr( "Network" ) );
219 }
220 if ( requestMadeFromMainThread )
221 authRequestBufferNotEmpty.wakeAll();
222 success = false;
223 }
224 else
225 {
226 // We are able to use direct connection here, because we
227 // * either run on the thread mReply lives in, so DirectConnection is standard and safe anyway
228 // * or the owner thread of mReply is currently not doing anything because it's blocked in future.waitForFinished() (if it is the main thread)
229 connect( mReply, &QNetworkReply::finished, this, &QgsBlockingNetworkRequest::replyFinished, Qt::DirectConnection );
230 connect( mReply, &QNetworkReply::downloadProgress, this, &QgsBlockingNetworkRequest::replyProgress, Qt::DirectConnection );
231 connect( mReply, &QNetworkReply::uploadProgress, this, &QgsBlockingNetworkRequest::replyProgress, Qt::DirectConnection );
232
233 if ( request.hasRawHeader( "Range" ) )
234 connect( mReply, &QNetworkReply::metaDataChanged, this, &QgsBlockingNetworkRequest::abortIfNotPartialContentReturned, Qt::DirectConnection );
235
236 auto resumeMainThread = [&waitConditionMutex, &authRequestBufferNotEmpty]() {
237 // when this method is called we have "produced" a single authentication request -- so the buffer is now full
238 // and it's time for the "consumer" (main thread) to do its part
239 waitConditionMutex.lock();
240 authRequestBufferNotEmpty.wakeAll();
241 waitConditionMutex.unlock();
242
243 // note that we don't need to handle waking this thread back up - that's done automatically by QgsNetworkAccessManager
244 };
245
246 QMetaObject::Connection authRequestConnection;
247 QMetaObject::Connection proxyAuthenticationConnection;
248#ifndef QT_NO_SSL
249 QMetaObject::Connection sslErrorsConnection;
250#endif
251
252 if ( requestMadeFromMainThread )
253 {
254 authRequestConnection = connect( QgsNetworkAccessManager::instance(), &QgsNetworkAccessManager::authRequestOccurred, this, resumeMainThread, Qt::DirectConnection );
255 proxyAuthenticationConnection = connect( QgsNetworkAccessManager::instance(), &QgsNetworkAccessManager::proxyAuthenticationRequired, this, resumeMainThread, Qt::DirectConnection );
256
257#ifndef QT_NO_SSL
258 sslErrorsConnection = connect( QgsNetworkAccessManager::instance(), &QgsNetworkAccessManager::sslErrorsOccurred, this, resumeMainThread, Qt::DirectConnection );
259#endif
260 }
261 QEventLoop loop;
262 // connecting to aboutToQuit avoids an on-going request to remain stalled
263 // when QThreadPool::globalInstance()->waitForDone()
264 // is called at process termination
265 connect( qApp, &QCoreApplication::aboutToQuit, &loop, &QEventLoop::quit, Qt::DirectConnection );
266 connect( this, &QgsBlockingNetworkRequest::finished, &loop, &QEventLoop::quit, Qt::DirectConnection );
267 loop.exec();
268
269 if ( requestMadeFromMainThread )
270 {
271 // event loop exited - need to disconnect as to not leave functor hanging to receive signals in future
272 disconnect( authRequestConnection );
273 disconnect( proxyAuthenticationConnection );
274#ifndef QT_NO_SSL
275 disconnect( sslErrorsConnection );
276#endif
277 }
278 }
279
280 if ( requestMadeFromMainThread )
281 {
282 waitConditionMutex.lock();
283 threadFinished = true;
284 authRequestBufferNotEmpty.wakeAll();
285 waitConditionMutex.unlock();
286 }
287 };
288
289 if ( requestMadeFromMainThread )
290 {
291 auto downloaderThread = std::make_unique<DownloaderThread>( downloaderFunction );
292 downloaderThread->start();
293
294 while ( true )
295 {
296 waitConditionMutex.lock();
297 if ( threadFinished )
298 {
299 waitConditionMutex.unlock();
300 break;
301 }
302 authRequestBufferNotEmpty.wait( &waitConditionMutex );
303
304 // If the downloader thread wakes us (the main thread) up and is not yet finished
305 // then it has "produced" an authentication request which we need to now "consume".
306 // The processEvents() call gives the auth manager the chance to show a dialog and
307 // once done with that, we can wake the downloaderThread again and continue the download.
308 if ( !threadFinished )
309 {
310 waitConditionMutex.unlock();
311
312 QgsApplication::processEvents();
313 // we don't need to wake up the worker thread - it will automatically be woken when
314 // the auth request has been dealt with by QgsNetworkAccessManager
315 }
316 else
317 {
318 waitConditionMutex.unlock();
319 }
320 }
321 // wait for thread to gracefully exit
322 downloaderThread->wait();
323 }
324 else
325 {
326 downloaderFunction();
327 }
328 return mErrorCode;
329}
330
332{
333 mIsAborted = true;
334 if ( mReply )
335 {
336 mReply->deleteLater();
337 mReply = nullptr;
338 }
339}
340
341void QgsBlockingNetworkRequest::replyProgress( qint64 bytesReceived, qint64 bytesTotal )
342{
343 QgsDebugMsgLevel( u"%1 of %2 bytes downloaded."_s.arg( bytesReceived ).arg( bytesTotal < 0 ? u"unknown number of"_s : QString::number( bytesTotal ) ), 2 );
344
345 if ( bytesReceived != 0 )
346 mGotNonEmptyResponse = true;
347
348 if ( !mIsAborted && mReply && ( !mFeedback || !mFeedback->isCanceled() ) )
349 {
350 if ( mReply->error() == QNetworkReply::NoError )
351 {
352 const QVariant redirect = mReply->attribute( QNetworkRequest::RedirectionTargetAttribute );
353 if ( !QgsVariantUtils::isNull( redirect ) )
354 {
355 // We don't want to emit downloadProgress() for a redirect
356 return;
357 }
358 }
359 }
360
361 if ( mMethod == Qgis::HttpMethod::Put || mMethod == Qgis::HttpMethod::Post )
362 emit uploadProgress( bytesReceived, bytesTotal );
363 else
364 emit downloadProgress( bytesReceived, bytesTotal );
365}
366
367void QgsBlockingNetworkRequest::replyFinished()
368{
369 if ( !mIsAborted && mReply )
370 {
371 if ( mReply->error() == QNetworkReply::NoError && ( !mFeedback || !mFeedback->isCanceled() ) )
372 {
373 QgsDebugMsgLevel( u"reply OK"_s, 2 );
374 const QVariant redirect = mReply->attribute( QNetworkRequest::RedirectionTargetAttribute );
375 if ( !QgsVariantUtils::isNull( redirect ) )
376 {
377 QgsDebugMsgLevel( u"Request redirected."_s, 2 );
378
379 const QUrl &toUrl = redirect.toUrl();
380 mReply->request();
381 if ( toUrl == mReply->url() )
382 {
383 mErrorMessage = tr( "Redirect loop detected: %1" ).arg( toUrl.toString() );
384 if ( !mFlags.testFlag( Qgis::NetworkRequestFlag::DisableMessageLogging ) )
385 {
386 QgsMessageLog::logMessage( mErrorMessage, tr( "Network" ) );
387 }
388 mReplyContent.clear();
389 }
390 else
391 {
392 QNetworkRequest request( toUrl );
393
394 if ( !mAuthCfg.isEmpty() && !QgsApplication::authManager()->updateNetworkRequest( request, mAuthCfg ) )
395 {
396 mReplyContent.clear();
397 mErrorMessage = errorMessageFailedAuth();
398 mErrorCode = NetworkError;
399 if ( !mFlags.testFlag( Qgis::NetworkRequestFlag::DisableMessageLogging ) )
400 {
401 QgsMessageLog::logMessage( mErrorMessage, tr( "Network" ) );
402 }
403 emit finished();
405 emit downloadFinished();
407 return;
408 }
409
410 request.setAttribute( QNetworkRequest::RedirectPolicyAttribute, QNetworkRequest::ManualRedirectPolicy );
411 request.setAttribute( QNetworkRequest::CacheLoadControlAttribute, mForceRefresh ? QNetworkRequest::AlwaysNetwork : QNetworkRequest::PreferCache );
412 request.setAttribute( QNetworkRequest::CacheSaveControlAttribute, true );
413
414 // if that was a range request, use the same range for the redirected request
415 if ( mReply->request().hasRawHeader( "Range" ) )
416 request.setRawHeader( "Range", mReply->request().rawHeader( "Range" ) );
417
418 mReply->deleteLater();
419 mReply = nullptr;
420
421 QgsDebugMsgLevel( u"redirected: %1 forceRefresh=%2"_s.arg( redirect.toString() ).arg( mForceRefresh ), 2 );
422
423 sendRequestToNetworkAccessManager( request );
424
425 if ( mFeedback )
426 connect( mFeedback, &QgsFeedback::canceled, mReply, &QNetworkReply::abort );
427
428 if ( !mAuthCfg.isEmpty() && !QgsApplication::authManager()->updateNetworkReply( mReply, mAuthCfg ) )
429 {
430 mReplyContent.clear();
431 mErrorMessage = errorMessageFailedAuth();
432 mErrorCode = NetworkError;
433 if ( !mFlags.testFlag( Qgis::NetworkRequestFlag::DisableMessageLogging ) )
434 {
435 QgsMessageLog::logMessage( mErrorMessage, tr( "Network" ) );
436 }
437 emit finished();
439 emit downloadFinished();
441 return;
442 }
443
444 connect( mReply, &QNetworkReply::finished, this, &QgsBlockingNetworkRequest::replyFinished, Qt::DirectConnection );
445 connect( mReply, &QNetworkReply::downloadProgress, this, &QgsBlockingNetworkRequest::replyProgress, Qt::DirectConnection );
446 connect( mReply, &QNetworkReply::uploadProgress, this, &QgsBlockingNetworkRequest::replyProgress, Qt::DirectConnection );
447
448 if ( request.hasRawHeader( "Range" ) )
449 connect( mReply, &QNetworkReply::metaDataChanged, this, &QgsBlockingNetworkRequest::abortIfNotPartialContentReturned, Qt::DirectConnection );
450
451 return;
452 }
453 }
454 else
455 {
456 const QgsNetworkAccessManager *nam = QgsNetworkAccessManager::instance();
457
458 if ( nam->cache() )
459 {
460 QNetworkCacheMetaData cmd = nam->cache()->metaData( mReply->request().url() );
461
462 QNetworkCacheMetaData::RawHeaderList hl;
463 const auto constRawHeaders = cmd.rawHeaders();
464 for ( const QNetworkCacheMetaData::RawHeader &h : constRawHeaders )
465 {
466 if ( h.first != "Cache-Control" )
467 hl.append( h );
468 }
469 cmd.setRawHeaders( hl );
470
471 QgsDebugMsgLevel( u"expirationDate:%1"_s.arg( cmd.expirationDate().toString() ), 2 );
472 if ( cmd.expirationDate().isNull() )
473 {
474 cmd.setExpirationDate( QDateTime::currentDateTime().addSecs( mExpirationSec ) );
475 }
476
477 nam->cache()->updateMetaData( cmd );
478 }
479 else
480 {
481 QgsDebugMsgLevel( u"No cache!"_s, 2 );
482 }
483
484#ifdef QGISDEBUG
485 const bool fromCache = mReply->attribute( QNetworkRequest::SourceIsFromCacheAttribute ).toBool();
486 QgsDebugMsgLevel( u"Reply was cached: %1"_s.arg( fromCache ), 2 );
487#endif
488
489 mReplyContent = QgsNetworkReplyContent( mReply );
490 const QByteArray content = mReply->readAll();
491 if ( !( mRequestFlags & RequestFlag::EmptyResponseIsValid ) && content.isEmpty() && !mGotNonEmptyResponse && mMethod == Qgis::HttpMethod::Get && ( !mFeedback || !mFeedback->isCanceled() ) )
492 {
493 mErrorMessage = tr( "empty response: %1" ).arg( mReply->errorString() );
494 mErrorCode = ServerExceptionError;
495 if ( !mFlags.testFlag( Qgis::NetworkRequestFlag::DisableMessageLogging ) )
496 {
497 QgsMessageLog::logMessage( mErrorMessage, tr( "Network" ) );
498 }
499 }
500 mReplyContent.setContent( content );
501 }
502 }
503 else
504 {
505 if ( mReply->error() != QNetworkReply::OperationCanceledError && ( !mFeedback || !mFeedback->isCanceled() ) )
506 {
507 mErrorMessage = mReply->errorString();
508 mErrorCode = ServerExceptionError;
509 if ( !mFlags.testFlag( Qgis::NetworkRequestFlag::DisableMessageLogging ) )
510 {
511 QgsMessageLog::logMessage( mErrorMessage, tr( "Network" ) );
512 }
513 }
514 mReplyContent = QgsNetworkReplyContent( mReply );
515 mReplyContent.setContent( mReply->readAll() );
516 }
517 }
518 if ( mTimedout )
519 mErrorCode = TimeoutError;
520
521 if ( mReply )
522 {
523 mReply->deleteLater();
524 mReply = nullptr;
525 }
526
527 emit finished();
529 emit downloadFinished();
531}
532
533QString QgsBlockingNetworkRequest::errorMessageFailedAuth()
534{
535 return tr( "network request update failed for authentication config" );
536}
537
538void QgsBlockingNetworkRequest::abortIfNotPartialContentReturned()
539{
540 if ( mReply && mReply->attribute( QNetworkRequest::HttpStatusCodeAttribute ).toInt() == 200 )
541 {
542 // We're expecting a 206 - Partial Content but the server returned 200
543 // It seems it does not support range requests and is returning the whole file!
544 mReply->abort();
545 mErrorMessage = tr( "The server does not support range requests" );
546 mErrorCode = ServerExceptionError;
547 }
548}
@ DisableMessageLogging
If present, indicates that no message logging should be performed when network errors are encountered...
Definition qgis.h:188
QFlags< NetworkRequestFlag > NetworkRequestFlags
Flags controlling behavior of network requests.
Definition qgis.h:197
HttpMethod
Different methods of HTTP requests.
Definition qgis.h:1103
@ Post
POST method.
Definition qgis.h:1105
@ Head
HEAD method.
Definition qgis.h:1106
@ Get
GET method.
Definition qgis.h:1104
@ Put
PUT method.
Definition qgis.h:1107
@ Delete
DELETE method.
Definition qgis.h:1108
static QgsApplication * instance()
Returns the singleton instance of the QgsApplication.
static QgsAuthManager * authManager()
Returns the application's authentication manager instance.
bool updateNetworkRequest(QNetworkRequest &request, const QString &authcfg, const QString &dataprovider=QString())
Provider call to update a QNetworkRequest with an authentication config.
bool updateNetworkReply(QNetworkReply *reply, const QString &authcfg, const QString &dataprovider=QString())
Provider call to update a QNetworkReply with an authentication config (used to skip known SSL errors,...
ErrorCode put(QNetworkRequest &request, QIODevice *data, QgsFeedback *feedback=nullptr)
Performs a "put" operation on the specified request, using the given data.
QgsBlockingNetworkRequest(Qgis::NetworkRequestFlags flags=Qgis::NetworkRequestFlags())
Constructor for QgsBlockingNetworkRequest.
void uploadProgress(qint64 bytesReceived, qint64 bytesTotal)
Emitted when when data are sent during a request.
Qgis::NetworkRequestFlags flags() const
Returns the network request flags.
ErrorCode head(QNetworkRequest &request, bool forceRefresh=false, QgsFeedback *feedback=nullptr)
Performs a "head" operation on the specified request.
void abort()
Aborts the network request immediately.
Q_DECL_DEPRECATED void downloadFinished()
Emitted once a request has finished downloading.
ErrorCode post(QNetworkRequest &request, QIODevice *data, bool forceRefresh=false, QgsFeedback *feedback=nullptr)
Performs a "post" operation on the specified request, using the given data.
ErrorCode deleteResource(QNetworkRequest &request, QgsFeedback *feedback=nullptr)
Performs a "delete" operation on the specified request.
void finished()
Emitted once a request has finished.
void setAuthCfg(const QString &authCfg)
Sets the authentication config id which should be used during the request.
QString authCfg() const
Returns the authentication config id which will be used during the request.
void downloadProgress(qint64 bytesReceived, qint64 bytesTotal)
Emitted when when data arrives during a request.
ErrorCode get(QNetworkRequest &request, bool forceRefresh=false, QgsFeedback *feedback=nullptr, RequestFlags requestFlags=QgsBlockingNetworkRequest::RequestFlags())
Performs a "get" operation on the specified request.
@ EmptyResponseIsValid
Do not generate an error if getting an empty response (e.g. HTTP 204).
@ NetworkError
A network error occurred.
@ ServerExceptionError
An exception was raised by the server.
@ NoError
No error was encountered.
@ TimeoutError
Timeout was reached before a reply was received.
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
void canceled()
Internal routines can connect to this signal if they use event loop.
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).
static QgsNetworkAccessManager * instance(Qt::ConnectionType connectionType=Qt::BlockingQueuedConnection)
Returns a pointer to the active QgsNetworkAccessManager for the current thread.
void requestTimedOut(QgsNetworkRequestParameters request)
Emitted when a network request has timed out.
static bool isNull(const QVariant &variant, bool silenceNullWarnings=false)
Returns true if the specified variant should be considered a NULL value.
#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