24 #include <QNetworkRequest>
25 #include <QNetworkReply>
27 #include <QWaitCondition>
28 #include <QNetworkCacheMetaData>
29 #include <QAuthenticator>
41 void QgsBlockingNetworkRequest::requestTimedOut( QNetworkReply *reply )
43 if (
reply == mReply )
59 return doRequest( Get, request, forceRefresh, feedback );
65 return doRequest( Post, request, forceRefresh, feedback );
76 mGotNonEmptyResponse =
false;
78 mErrorMessage.clear();
80 mForceRefresh = forceRefresh;
81 mReplyContent.
clear();
86 mErrorMessage = errorMessageFailedAuth();
91 QgsDebugMsgLevel( QStringLiteral(
"Calling: %1" ).arg( request.url().toString() ), 2 );
93 request.setAttribute( QNetworkRequest::CacheLoadControlAttribute, forceRefresh ? QNetworkRequest::AlwaysNetwork : QNetworkRequest::PreferCache );
94 request.setAttribute( QNetworkRequest::CacheSaveControlAttribute,
true );
96 QWaitCondition authRequestBufferNotEmpty;
97 QMutex waitConditionMutex;
99 bool threadFinished =
false;
100 bool success =
false;
102 const bool requestMadeFromMainThread = QThread::currentThread() == QApplication::instance()->thread();
107 std::function<void()> downloaderFunction = [
this, request, &waitConditionMutex, &authRequestBufferNotEmpty, &threadFinished, &success, requestMadeFromMainThread ]()
134 mErrorMessage = errorMessageFailedAuth();
136 if ( requestMadeFromMainThread )
137 authRequestBufferNotEmpty.wakeAll();
145 connect( mReply, &QNetworkReply::finished,
this, &QgsBlockingNetworkRequest::replyFinished, Qt::DirectConnection );
146 connect( mReply, &QNetworkReply::downloadProgress,
this, &QgsBlockingNetworkRequest::replyProgress, Qt::DirectConnection );
148 auto resumeMainThread = [&waitConditionMutex, &authRequestBufferNotEmpty ]()
152 waitConditionMutex.lock();
153 authRequestBufferNotEmpty.wakeAll();
154 waitConditionMutex.unlock();
159 if ( requestMadeFromMainThread )
173 if ( requestMadeFromMainThread )
175 waitConditionMutex.lock();
176 threadFinished =
true;
177 authRequestBufferNotEmpty.wakeAll();
178 waitConditionMutex.unlock();
182 if ( requestMadeFromMainThread )
184 std::unique_ptr<DownloaderThread> downloaderThread = qgis::make_unique<DownloaderThread>( downloaderFunction );
185 downloaderThread->start();
189 waitConditionMutex.lock();
190 if ( threadFinished )
192 waitConditionMutex.unlock();
195 authRequestBufferNotEmpty.wait( &waitConditionMutex );
201 if ( !threadFinished )
203 waitConditionMutex.unlock();
211 waitConditionMutex.unlock();
215 downloaderThread->wait();
219 downloaderFunction();
229 mReply->deleteLater();
234 void QgsBlockingNetworkRequest::replyProgress( qint64 bytesReceived, qint64 bytesTotal )
236 QgsDebugMsgLevel( QStringLiteral(
"%1 of %2 bytes downloaded." ).arg( bytesReceived ).arg( bytesTotal < 0 ? QStringLiteral(
"unknown number of" ) : QString::number( bytesTotal ) ), 2 );
238 if ( bytesReceived != 0 )
239 mGotNonEmptyResponse =
true;
241 if ( !mIsAborted && mReply && ( !mFeedback || !mFeedback->isCanceled() ) )
243 if ( mReply->error() == QNetworkReply::NoError )
245 QVariant redirect = mReply->attribute( QNetworkRequest::RedirectionTargetAttribute );
246 if ( !redirect.isNull() )
257 void QgsBlockingNetworkRequest::replyFinished()
259 if ( !mIsAborted && mReply )
261 if ( mReply->error() == QNetworkReply::NoError && ( !mFeedback || !mFeedback->isCanceled() ) )
264 QVariant redirect = mReply->attribute( QNetworkRequest::RedirectionTargetAttribute );
265 if ( !redirect.isNull() )
269 const QUrl &toUrl = redirect.toUrl();
271 if ( toUrl == mReply->url() )
273 mErrorMessage = tr(
"Redirect loop detected: %1" ).arg( toUrl.toString() );
275 mReplyContent.
clear();
279 QNetworkRequest request( toUrl );
283 mReplyContent.
clear();
284 mErrorMessage = errorMessageFailedAuth();
291 request.setAttribute( QNetworkRequest::CacheLoadControlAttribute, mForceRefresh ? QNetworkRequest::AlwaysNetwork : QNetworkRequest::PreferCache );
292 request.setAttribute( QNetworkRequest::CacheSaveControlAttribute,
true );
294 mReply->deleteLater();
297 QgsDebugMsgLevel( QStringLiteral(
"redirected: %1 forceRefresh=%2" ).arg( redirect.toString() ).arg( mForceRefresh ), 2 );
314 mReplyContent.
clear();
315 mErrorMessage = errorMessageFailedAuth();
322 connect( mReply, &QNetworkReply::finished,
this, &QgsBlockingNetworkRequest::replyFinished, Qt::DirectConnection );
323 connect( mReply, &QNetworkReply::downloadProgress,
this, &QgsBlockingNetworkRequest::replyProgress, Qt::DirectConnection );
333 QNetworkCacheMetaData cmd = nam->cache()->metaData( mReply->request().url() );
335 QNetworkCacheMetaData::RawHeaderList hl;
336 const auto constRawHeaders = cmd.rawHeaders();
337 for (
const QNetworkCacheMetaData::RawHeader &h : constRawHeaders )
339 if ( h.first !=
"Cache-Control" )
342 cmd.setRawHeaders( hl );
344 QgsDebugMsgLevel( QStringLiteral(
"expirationDate:%1" ).arg( cmd.expirationDate().toString() ), 2 );
345 if ( cmd.expirationDate().isNull() )
347 cmd.setExpirationDate( QDateTime::currentDateTime().addSecs( mExpirationSec ) );
350 nam->cache()->updateMetaData( cmd );
358 bool fromCache = mReply->attribute( QNetworkRequest::SourceIsFromCacheAttribute ).toBool();
359 QgsDebugMsgLevel( QStringLiteral(
"Reply was cached: %1" ).arg( fromCache ), 2 );
363 const QByteArray content = mReply->readAll();
364 if ( content.isEmpty() && !mGotNonEmptyResponse )
366 mErrorMessage = tr(
"empty response: %1" ).arg( mReply->errorString() );
375 if ( mReply->error() != QNetworkReply::OperationCanceledError )
377 mErrorMessage = mReply->errorString();
389 mReply->deleteLater();
396 QString QgsBlockingNetworkRequest::errorMessageFailedAuth()
398 return tr(
"network request update failed for authentication config" );