25  , mFeedback( feedback )
 
   26  , mThread( QThread::currentThread() )
 
   28  CPLHTTPPushFetchCallback( QgsCPLHTTPFetchOverrider::callback, 
this );
 
 
   33  CPLHTTPPopFetchCallback();
 
 
   37CPLHTTPResult *QgsCPLHTTPFetchOverrider::callback( 
const char *pszURL,
 
   38    CSLConstList papszOptions,
 
   41    CPLHTTPFetchWriteFunc pfnWrite,
 
   47  auto psResult = 
static_cast<CPLHTTPResult *
>( CPLCalloc( 
sizeof( CPLHTTPResult ), 1 ) );
 
   48  if ( CSLFetchNameValue( papszOptions, 
"CLOSE_PERSISTENT" ) )
 
   57  for ( 
const char *pszOption : { 
"FORM_FILE_PATH", 
"FORM_ITEM_COUNT" } )
 
   59    if ( CSLFetchNameValue( papszOptions, pszOption ) )
 
   61      QgsDebugError( QStringLiteral( 
"Option %1 not handled" ).arg( pszOption ) );
 
   66  if ( pThis->mFeedback && pThis->mFeedback->
isCanceled() )
 
   68    psResult->nStatus = 1;
 
   69    psResult->pszErrBuf = CPLStrdup( 
"download interrupted by user" );
 
   76  QNetworkRequest request( QString::fromUtf8( pszURL ) );
 
   77  for ( 
const auto &keyValue : pThis->mAttributes )
 
   79    request.setAttribute( keyValue.first, keyValue.second );
 
   83  const char *pszHeaders = CSLFetchNameValue( papszOptions, 
"HEADERS" );
 
   86    char **papszTokensHeaders = CSLTokenizeString2( pszHeaders, 
"\r\n", 0 );
 
   87    for ( 
int i = 0; papszTokensHeaders[i] != 
nullptr; ++i )
 
   89      char *pszKey = 
nullptr;
 
   90      const char *pszValue = CPLParseNameValue( papszTokensHeaders[i], &pszKey );
 
   91      if ( pszKey && pszValue )
 
   94          QByteArray::fromStdString( pszKey ),
 
   95          QByteArray::fromStdString( pszValue ) );
 
   99    CSLDestroy( papszTokensHeaders );
 
  102  constexpr bool forceRefresh = 
true;
 
  103  const char *pszCustomRequest = CSLFetchNameValue( papszOptions, 
"CUSTOMREQUEST" );
 
  104  const char *pszPostFields = CSLFetchNameValue( papszOptions, 
"POSTFIELDS" );
 
  108    if ( !pszCustomRequest || EQUAL( pszCustomRequest, 
"POST" ) )
 
  110      errCode = blockingRequest.
post( request,
 
  111                                      QByteArray::fromStdString( pszPostFields ),
 
  115    else if ( EQUAL( pszCustomRequest, 
"PUT" ) )
 
  117      errCode = blockingRequest.
put( request,
 
  118                                     QByteArray::fromStdString( pszPostFields ),
 
  123      QgsDebugError( QStringLiteral( 
"Invalid CUSTOMREQUEST = %1 when POSTFIELDS is defined" ).arg( pszCustomRequest ) );
 
  129    if ( !pszCustomRequest || EQUAL( pszCustomRequest, 
"GET" ) )
 
  133    else if ( EQUAL( pszCustomRequest, 
"HEAD" ) )
 
  135      errCode = blockingRequest.
head( request, forceRefresh, pThis->mFeedback );
 
  137    else if ( EQUAL( pszCustomRequest, 
"DELETE" ) )
 
  139      errCode = blockingRequest.
deleteResource( request, pThis->mFeedback );
 
  143      QgsDebugError( QStringLiteral( 
"Invalid CUSTOMREQUEST = %1 when POSTFIELDS is not defined" ).arg( pszCustomRequest ) );
 
  149    psResult->nStatus = 1;
 
  150    psResult->pszErrBuf = CPLStrdup( blockingRequest.
errorMessage().toUtf8() );
 
  157  for ( 
const auto &pair : reply.rawHeaderPairs() )
 
  159    if ( EQUAL( pair.first.toStdString().c_str(), 
"Content-Type" ) )
 
  161      CPLFree( psResult->pszContentType );
 
  162      psResult->pszContentType = CPLStrdup( pair.second.toStdString().c_str() );
 
  164    psResult->papszHeaders = CSLAddNameValue(
 
  165                               psResult->papszHeaders,
 
  166                               pair.first.toStdString().c_str(),
 
  167                               pair.second.toStdString().c_str() );
 
  171  QByteArray content( reply.content() );
 
  177    if ( 
static_cast<int>( pfnWrite( content.data(), 1, content.size(), pWriteArg ) ) != content.size() )
 
  179      psResult->nStatus = 1;
 
  180      psResult->pszErrBuf = CPLStrdup( 
"download interrupted by user" );
 
  186    psResult->nDataLen = 
static_cast<int>( content.size() );
 
  187    psResult->pabyData = 
static_cast<GByte *
>( CPLMalloc( psResult->nDataLen + 1 ) );
 
  188    memcpy( psResult->pabyData, content.constData(), psResult->nDataLen );
 
  189    psResult->pabyData[psResult->nDataLen] = 0;
 
  197  mAttributes[code] = value;
 
 
  202  mFeedback = feedback;
 
 
A thread safe class for performing blocking (sync) network requests, with full support for QGIS proxy...
 
ErrorCode put(QNetworkRequest &request, QIODevice *data, QgsFeedback *feedback=nullptr)
Performs a "put" operation on the specified request, using the given data.
 
ErrorCode head(QNetworkRequest &request, bool forceRefresh=false, QgsFeedback *feedback=nullptr)
Performs a "head" operation on the specified request.
 
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 setAuthCfg(const QString &authCfg)
Sets the authentication config id which should be used during the request.
 
QString errorMessage() const
Returns the error message string, after a get(), post(), head() or put() request has been made.
 
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)
 
@ NoError
No error was encountered.
 
QgsNetworkReplyContent reply() const
Returns the content of the network reply, after a get(), post(), head() or put() request has been mad...
 
Utility class to redirect GDAL's CPL HTTP calls through QgsBlockingNetworkRequest.
 
QgsCPLHTTPFetchOverrider(const QString &authCfg=QString(), QgsFeedback *feedback=nullptr)
Installs the redirection for the current thread.
 
void setAttribute(QNetworkRequest::Attribute code, const QVariant &value)
Define attribute that must be forwarded to the actual QNetworkRequest.
 
QThread * thread() const
Returns the thread associated with the overrider.
 
void setFeedback(QgsFeedback *feedback)
Sets the feedback cancellation object for the redirection.
 
~QgsCPLHTTPFetchOverrider()
 
Base class for feedback objects to be used for cancellation of something running in a worker thread.
 
bool isCanceled() const
Tells whether the operation has been canceled already.
 
Encapsulates a network reply within a container which is inexpensive to copy and safe to pass between...
 
#define QgsDebugError(str)