Navigation Menu

Skip to content

Commit

Permalink
Add QgsNetworkAccessManager::setRequestPreprocessor
Browse files Browse the repository at this point in the history
  • Loading branch information
mhugent committed Jun 21, 2021
1 parent 00536e8 commit 307bce8
Show file tree
Hide file tree
Showing 3 changed files with 131 additions and 0 deletions.
49 changes: 49 additions & 0 deletions python/core/auto_generated/network/qgsnetworkaccessmanager.sip.in
Expand Up @@ -321,6 +321,55 @@ The contents of the reply will be returned after the request is completed or an
.. versionadded:: 3.6
%End

static QString setRequestPreprocessor( SIP_PYCALLABLE / AllowNone / );
%Docstring
Sets a request pre-processor function, which allows to manipulate a network request before it is processed.

The ``processor`` function takes the QNetworkRequest as its argument, and can mutate the request if neccessary.

:return: An auto-generated string uniquely identifying the preprocessor, which can later be
used to remove the preprocessor (via a call to :py:func:`~QgsNetworkAccessManager.removeRequestPreprocessor`).

.. seealso:: :py:func:`removeRequestPreprocessor`

.. versionadded:: 3.12
%End
%MethodCode
PyObject *s = 0;
Py_BEGIN_ALLOW_THREADS
Py_XINCREF( a0 );
QString id = QgsNetworkAccessManager::setRequestPreprocessor( [a0]( QNetworkRequest *arg )
{
SIP_BLOCK_THREADS
Py_XDECREF( sipCallMethod( NULL, a0, "D", &arg, sipType_QNetworkRequest, NULL ) );
SIP_UNBLOCK_THREADS
} );

s = sipConvertFromNewType( new QString( id ), sipType_QString, 0 );
Py_END_ALLOW_THREADS
return s;
%End

static void removeRequestPreprocessor( const QString &id );
%Docstring
Removes the custom pre-processor function with matching ``id``.

The ``id`` must correspond to a pre-processor previously added via a call to :py:func:`~QgsNetworkAccessManager.setRequestPreprocessor`.

Returns ``True`` if processor existed and was removed.

.. seealso:: :py:func:`setRequestPreprocessor`

.. versionadded:: 3.12
%End
%MethodCode
if ( !QgsNetworkAccessManager::removeRequestPreprocessor( *a0 ) )
{
PyErr_SetString( PyExc_KeyError, QStringLiteral( "No processor with id %1 exists." ).arg( *a0 ).toUtf8().constData() );
sipIsErr = 1;
}
%End

void requestAuthOpenBrowser( const QUrl &url ) const;
%Docstring
Forwards an external browser login ``url`` opening request to the authentication handler.
Expand Down
25 changes: 25 additions & 0 deletions src/core/network/qgsnetworkaccessmanager.cpp
Expand Up @@ -43,6 +43,7 @@
#include <QThreadStorage>
#include <QAuthenticator>
#include <QStandardPaths>
#include <QUuid>

#ifndef QT_NO_SSL
#include <QSslConfiguration>
Expand All @@ -53,6 +54,8 @@

QgsNetworkAccessManager *QgsNetworkAccessManager::sMainNAM = nullptr;

std::vector< std::pair< QString, std::function< void( QNetworkRequest * ) > > > QgsNetworkAccessManager::sCustomPreprocessors;

/// @cond PRIVATE
class QgsNetworkProxyFactory : public QNetworkProxyFactory
{
Expand Down Expand Up @@ -337,6 +340,11 @@ QNetworkReply *QgsNetworkAccessManager::createRequest( QNetworkAccessManager::Op
pReq->setAttribute( QNetworkRequest::CacheSaveControlAttribute, false );
}

for ( const auto &preprocessor : sCustomPreprocessors )
{
preprocessor.second( pReq );
}

static QAtomicInt sRequestId = 0;
const int requestId = ++sRequestId;
QByteArray content;
Expand Down Expand Up @@ -806,6 +814,23 @@ QgsNetworkReplyContent QgsNetworkAccessManager::blockingPost( QNetworkRequest &r
return br.reply();
}

QString QgsNetworkAccessManager::setRequestPreprocessor( const std::function<void ( QNetworkRequest * )> &processor )
{
QString id = QUuid::createUuid().toString();
sCustomPreprocessors.emplace_back( std::make_pair( id, processor ) );
return id;
}

bool QgsNetworkAccessManager::removeRequestPreprocessor( const QString &id )
{
const size_t prevCount = sCustomPreprocessors.size();
sCustomPreprocessors.erase( std::remove_if( sCustomPreprocessors.begin(), sCustomPreprocessors.end(), [id]( std::pair< QString, std::function< void( QNetworkRequest * ) > > &a )
{
return a.first == id;
} ), sCustomPreprocessors.end() );
return prevCount != sCustomPreprocessors.size();
}


//
// QgsNetworkRequestParameters
Expand Down
57 changes: 57 additions & 0 deletions src/core/network/qgsnetworkaccessmanager.h
Expand Up @@ -516,6 +516,61 @@ class CORE_EXPORT QgsNetworkAccessManager : public QNetworkAccessManager
*/
static QgsNetworkReplyContent blockingPost( QNetworkRequest &request, const QByteArray &data, const QString &authCfg = QString(), bool forceRefresh = false, QgsFeedback *feedback = nullptr );

/**
* Sets a request pre-processor function, which allows to manipulate a network request before it is processed.
*
* The \a processor function takes the QNetworkRequest as its argument, and can mutate the request if neccessary.
*
* \returns An auto-generated string uniquely identifying the preprocessor, which can later be
* used to remove the preprocessor (via a call to removeRequestPreprocessor()).
*
* \see removeRequestPreprocessor()
* \since QGIS 3.12
*/
#ifndef SIP_RUN
static QString setRequestPreprocessor( const std::function< void( QNetworkRequest *request )> &processor );
#else
static QString setRequestPreprocessor( SIP_PYCALLABLE / AllowNone / );
% MethodCode
PyObject *s = 0;
Py_BEGIN_ALLOW_THREADS
Py_XINCREF( a0 );
QString id = QgsNetworkAccessManager::setRequestPreprocessor( [a0]( QNetworkRequest *arg )
{
SIP_BLOCK_THREADS
Py_XDECREF( sipCallMethod( NULL, a0, "D", &arg, sipType_QNetworkRequest, NULL ) );
SIP_UNBLOCK_THREADS
} );

s = sipConvertFromNewType( new QString( id ), sipType_QString, 0 );
Py_END_ALLOW_THREADS
return s;
% End
#endif

/**
* Removes the custom pre-processor function with matching \a id.
*
* The \a id must correspond to a pre-processor previously added via a call to setRequestPreprocessor().
*
* Returns TRUE if processor existed and was removed.
*
* \see setRequestPreprocessor()
* \since QGIS 3.12
*/
#ifndef SIP_RUN
static bool removeRequestPreprocessor( const QString &id );
#else
static void removeRequestPreprocessor( const QString &id );
% MethodCode
if ( !QgsNetworkAccessManager::removeRequestPreprocessor( *a0 ) )
{
PyErr_SetString( PyExc_KeyError, QStringLiteral( "No processor with id %1 exists." ).arg( *a0 ).toUtf8().constData() );
sipIsErr = 1;
}
% End
#endif

/**
* Forwards an external browser login \a url opening request to the authentication handler.
*
Expand Down Expand Up @@ -758,6 +813,8 @@ class CORE_EXPORT QgsNetworkAccessManager : public QNetworkAccessManager
// only in use by worker threads, unused in main thread
QWaitCondition mAuthRequestWaitCondition;

static std::vector< std::pair< QString, std::function< void( QNetworkRequest * ) > > > sCustomPreprocessors;

};

#endif // QGSNETWORKACCESSMANAGER_H

0 comments on commit 307bce8

Please sign in to comment.