Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Add custom QNetworkRequest::Attributes for initiator network request …
…class name and internal id

And allow these to be retrieved from QgsNetworkRequestParameters.
This allows logging code to identify the area of code where a request
originated from, making debugging much easier!

Tag all requests created with appropriate class name and IDs
  • Loading branch information
nyalldawson committed Jan 25, 2019
1 parent a491e90 commit ca06d40
Show file tree
Hide file tree
Showing 20 changed files with 121 additions and 7 deletions.
28 changes: 28 additions & 0 deletions python/core/auto_generated/qgsnetworkaccessmanager.sip.in
Expand Up @@ -10,6 +10,7 @@




class QgsNetworkRequestParameters
{
%Docstring
Expand All @@ -23,6 +24,12 @@ Encapsulates parameters and properties of a network request.
%End
public:

enum RequestAttributes
{
AttributeInitiatorClass,
AttributeInitiatorRequestId,
};

QgsNetworkRequestParameters();
%Docstring
Default constructor.
Expand Down Expand Up @@ -64,6 +71,27 @@ Returns a unique ID identifying the request.
%Docstring
Returns the request's content. This is only used for POST or PUT operation
requests.
%End

QString initiatorClassName() const;
%Docstring
Returns the class name of the object which initiated this request.

This is only available for QNetworkRequests which have had the
QgsNetworkRequestParameters.AttributeInitiatorClass attribute set.

.. seealso:: :py:func:`initiatorRequestId`
%End

QVariant initiatorRequestId() const;
%Docstring
Returns the internal ID used by the object which initiated this request to identify
individual requests.

This is only available for QNetworkRequests which have had the
QgsNetworkRequestParameters.AttributeInitiatorRequestId attribute set.

.. seealso:: :py:func:`initiatorClassName`
%End

};
Expand Down
4 changes: 3 additions & 1 deletion python/pyplugin_installer/installer.py
Expand Up @@ -32,7 +32,7 @@
from qgis.PyQt.QtNetwork import QNetworkRequest

import qgis
from qgis.core import Qgis, QgsApplication, QgsNetworkAccessManager, QgsSettings
from qgis.core import Qgis, QgsApplication, QgsNetworkAccessManager, QgsSettings, QgsNetworkRequestParameters
from qgis.gui import QgsMessageBar, QgsPasswordLineEdit
from qgis.utils import (iface, startPlugin, unloadPlugin, loadPlugin,
reloadPlugin, updateAvailablePlugins)
Expand Down Expand Up @@ -527,6 +527,8 @@ def sendVote(self, plugin_id, vote):
url = "http://plugins.qgis.org/plugins/RPC2/"
params = {"id": "djangorpc", "method": "plugin.vote", "params": [str(plugin_id), str(vote)]}
req = QNetworkRequest(QUrl(url))
req.setAttribute(QNetworkRequest.Attribute(QgsNetworkRequestParameters.AttributeInitiatorClass), "QgsPluginInstaller")
req.setAttribute(QNetworkRequest.Attribute(QgsNetworkRequestParameters.AttributeInitiatorRequestId), "sendVote")
req.setRawHeader(b"Content-Type", b"application/json")
QgsNetworkAccessManager.instance().post(req, bytes(json.dumps(params), "utf-8"))
return True
Expand Down
3 changes: 2 additions & 1 deletion python/pyplugin_installer/installer_data.py
Expand Up @@ -28,7 +28,7 @@
QLocale, QByteArray)
from qgis.PyQt.QtXml import QDomDocument
from qgis.PyQt.QtNetwork import QNetworkRequest, QNetworkReply
from qgis.core import Qgis, QgsSettings
from qgis.core import Qgis, QgsSettings, QgsNetworkRequestParameters
import sys
import os
import codecs
Expand Down Expand Up @@ -322,6 +322,7 @@ def requestFetching(self, key, url=None, redirectionCounter=0):
# url.addQueryItem('qgis', '.'.join([str(int(s)) for s in [v[0], v[1:3]]]) ) # don't include the bugfix version!

self.mRepositories[key]["QRequest"] = QNetworkRequest(url)
self.mRepositories[key]["QRequest"].setAttribute(QNetworkRequest.Attribute(QgsNetworkRequestParameters.AttributeInitiatorClass), "Relay")
authcfg = self.mRepositories[key]["authcfg"]
if authcfg and isinstance(authcfg, str):
if not QgsApplication.authManager().updateNetworkRequest(
Expand Down
Expand Up @@ -30,7 +30,7 @@
from qgis.PyQt.QtNetwork import QNetworkRequest, QNetworkReply

import qgis
from qgis.core import QgsNetworkAccessManager, QgsApplication
from qgis.core import QgsNetworkAccessManager, QgsApplication, QgsNetworkRequestParameters

from .ui_qgsplugininstallerinstallingbase import Ui_QgsPluginInstallerInstallingDialogBase
from .installer_data import removeDir, repositories
Expand Down Expand Up @@ -62,6 +62,7 @@ def __init__(self, parent, plugin):

def requestDownloading(self):
self.request = QNetworkRequest(self.url)
self.request.setAttribute(QNetworkRequest.Attribute(QgsNetworkRequestParameters.AttributeInitiatorClass), "QgsPluginInstallerInstallingDialog")
authcfg = repositories.all()[self.plugin["zip_repository"]]["authcfg"]
if authcfg and isinstance(authcfg, str):
if not QgsApplication.authManager().updateNetworkRequest(
Expand Down
2 changes: 2 additions & 0 deletions src/auth/oauth2/qgsauthoauth2edit.cpp
Expand Up @@ -1119,6 +1119,7 @@ void QgsAuthOAuth2Edit::registerSoftStatement( const QString &registrationUrl )
bool res = false;
QByteArray json = QJsonWrapper::toJson( QVariant( mSoftwareStatement ), &res, &errStr );
QNetworkRequest registerRequest( regUrl );
QgsSetRequestInitiatorClass( registerRequest, QStringLiteral( "QgsAuthOAuth2Edit" ) );
registerRequest.setHeader( QNetworkRequest::ContentTypeHeader, QLatin1Literal( "application/json" ) );
QNetworkReply *registerReply;
// For testability: use GET if protocol is file://
Expand All @@ -1142,6 +1143,7 @@ void QgsAuthOAuth2Edit::getSoftwareStatementConfig()
QString config = leSoftwareStatementConfigUrl->text();
QUrl configUrl( config );
QNetworkRequest configRequest( configUrl );
QgsSetRequestInitiatorClass( configRequest, QStringLiteral( "QgsAuthOAuth2Edit" ) );
QNetworkReply *configReply = QgsNetworkAccessManager::instance()->get( configRequest );
mDownloading = true;
connect( configReply, &QNetworkReply::finished, this, &QgsAuthOAuth2Edit::configReplyFinished, Qt::QueuedConnection );
Expand Down
3 changes: 3 additions & 0 deletions src/auth/oauth2/qgso2.cpp
Expand Up @@ -20,6 +20,7 @@
#include "qgsapplication.h"
#include "qgsauthoauth2config.h"
#include "qgslogger.h"
#include "qgsnetworkaccessmanager.h"

#include <QDir>
#include <QSettings>
Expand Down Expand Up @@ -230,6 +231,7 @@ void QgsO2::link()

QUrl url( tokenUrl_ );
QNetworkRequest tokenRequest( url );
QgsSetRequestInitiatorClass( tokenRequest, QStringLiteral( "QgsO2" ) );
tokenRequest.setHeader( QNetworkRequest::ContentTypeHeader, QLatin1Literal( "application/x-www-form-urlencoded" ) );
QNetworkReply *tokenReply = manager_->post( tokenRequest, payload );

Expand Down Expand Up @@ -291,6 +293,7 @@ void QgsO2::onVerificationReceived( QMap<QString, QString> response )
if ( !apiKey_.isEmpty() )
query = QStringLiteral( "?=%1" ).arg( QString( O2_OAUTH2_API_KEY ), apiKey_ );
QNetworkRequest tokenRequest( QUrl( tokenUrl_.toString() + query ) );
QgsSetRequestInitiatorClass( tokenRequest, QStringLiteral( "QgsO2" ) );
tokenRequest.setHeader( QNetworkRequest::ContentTypeHeader, O2_MIME_TYPE_XFORM );
QMap<QString, QString> parameters;
parameters.insert( O2_OAUTH2_GRANT_TYPE_CODE, code() );
Expand Down
3 changes: 2 additions & 1 deletion src/core/geocms/geonode/qgsgeonoderequest.cpp
Expand Up @@ -185,7 +185,7 @@ void QgsGeoNodeRequest::replyFinished()
else
{
QNetworkRequest request( toUrl );

QgsSetRequestInitiatorClass( request, QStringLiteral( "QgsGeoNodeRequest" ) );
request.setAttribute( QNetworkRequest::CacheLoadControlAttribute, mForceRefresh ? QNetworkRequest::AlwaysNetwork : QNetworkRequest::PreferCache );
request.setAttribute( QNetworkRequest::CacheSaveControlAttribute, true );

Expand Down Expand Up @@ -519,6 +519,7 @@ bool QgsGeoNodeRequest::requestBlocking( const QString &endPoint )
QNetworkReply *QgsGeoNodeRequest::requestUrl( const QString &url )
{
QNetworkRequest request( url );
QgsSetRequestInitiatorClass( request, QStringLiteral( "QgsGeoNodeRequest" ) );
// Add authentication check here

request.setAttribute( QNetworkRequest::CacheLoadControlAttribute, mForceRefresh ? QNetworkRequest::AlwaysNetwork : QNetworkRequest::PreferCache );
Expand Down
2 changes: 2 additions & 0 deletions src/core/qgsabstractcontentcache.h
Expand Up @@ -23,6 +23,7 @@
#include "qgslogger.h"
#include "qgsmessagelog.h"
#include "qgsapplication.h"
#include "qgsnetworkaccessmanager.h"

#include <QObject>
#include <QMutex>
Expand Down Expand Up @@ -322,6 +323,7 @@ class CORE_EXPORT QgsAbstractContentCache : public QgsAbstractContentCacheBase
mPendingRemoteUrls.insert( path );
//fire up task to fetch content in background
QNetworkRequest request( url );
QgsSetRequestInitiatorClass( request, QStringLiteral( "QgsAbstractContentCache<%1>" ).arg( mTypeString ) );
request.setAttribute( QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache );
request.setAttribute( QNetworkRequest::CacheSaveControlAttribute, true );

Expand Down
1 change: 1 addition & 0 deletions src/core/qgsfiledownloader.cpp
Expand Up @@ -51,6 +51,7 @@ void QgsFileDownloader::startDownload()
QgsNetworkAccessManager *nam = QgsNetworkAccessManager::instance();

QNetworkRequest request( mUrl );
QgsSetRequestInitiatorClass( request, QStringLiteral( "QgsFileDownloader" ) );
if ( !mAuthCfg.isEmpty() )
{
QgsApplication::authManager()->updateNetworkRequest( request, mAuthCfg );
Expand Down
2 changes: 2 additions & 0 deletions src/core/qgsgml.cpp
Expand Up @@ -61,6 +61,8 @@ int QgsGml::getFeatures( const QString &uri, QgsWkbTypes::Type *wkbType, QgsRect
mExtent.setMinimal();

QNetworkRequest request( uri );
QgsSetRequestInitiatorClass( request, QStringLiteral( "QgsGml" ) );

if ( !authcfg.isEmpty() )
{
if ( !QgsApplication::authManager()->updateNetworkRequest( request, authcfg ) )
Expand Down
2 changes: 2 additions & 0 deletions src/core/qgsnetworkaccessmanager.cpp
Expand Up @@ -450,5 +450,7 @@ QgsNetworkRequestParameters::QgsNetworkRequestParameters( QNetworkAccessManager:
, mOriginatingThreadId( QStringLiteral( "0x%2" ).arg( reinterpret_cast<quintptr>( QThread::currentThread() ), 2 * QT_POINTER_SIZE, 16, QLatin1Char( '0' ) ) )
, mRequestId( requestId )
, mContent( content )
, mInitiatorClass( request.attribute( static_cast< QNetworkRequest::Attribute >( QgsNetworkRequestParameters::AttributeInitiatorClass ) ).toString() )
, mInitiatorRequestId( request.attribute( static_cast< QNetworkRequest::Attribute >( QgsNetworkRequestParameters::AttributeInitiatorRequestId ) ) )
{
}
38 changes: 38 additions & 0 deletions src/core/qgsnetworkaccessmanager.h
Expand Up @@ -29,6 +29,14 @@
#include "qgis_core.h"
#include "qgis_sip.h"

#ifndef SIP_RUN
#include "qgsconfig.h"
constexpr int sFilePrefixLength = CMAKE_SOURCE_DIR[sizeof( CMAKE_SOURCE_DIR ) - 1] == '/' ? sizeof( CMAKE_SOURCE_DIR ) + 1 : sizeof( CMAKE_SOURCE_DIR );

#define QgsSetRequestInitiatorClass(request, _class) request.setAttribute( static_cast< QNetworkRequest::Attribute >( QgsNetworkRequestParameters::AttributeInitiatorClass ), _class ); request.setAttribute( static_cast< QNetworkRequest::Attribute >( QgsNetworkRequestParameters::AttributeInitiatorRequestId ), QString( __FILE__ ).mid( sFilePrefixLength ) + ':' + QString::number( __LINE__ ) + " (" + __FUNCTION__ + ")" );
#define QgsSetRequestInitiatorId(request, str) request.setAttribute( static_cast< QNetworkRequest::Attribute >( QgsNetworkRequestParameters::AttributeInitiatorRequestId ), QString( __FILE__ ).mid( sFilePrefixLength ) + ':' + QString::number( __LINE__ ) + " (" + __FUNCTION__ + "): " + str );
#endif

/**
* \class QgsNetworkRequestParameters
* \ingroup core
Expand All @@ -39,6 +47,13 @@ class CORE_EXPORT QgsNetworkRequestParameters
{
public:

//! Custom request attributes
enum RequestAttributes
{
AttributeInitiatorClass = QNetworkRequest::User + 3000, //!< Class name of original object which created the request
AttributeInitiatorRequestId, //!< Internal ID used by originator object to identify requests
};

/**
* Default constructor.
*/
Expand Down Expand Up @@ -82,13 +97,36 @@ class CORE_EXPORT QgsNetworkRequestParameters
*/
QByteArray content() const { return mContent; }

/**
* Returns the class name of the object which initiated this request.
*
* This is only available for QNetworkRequests which have had the
* QgsNetworkRequestParameters::AttributeInitiatorClass attribute set.
*
* \see initiatorRequestId()
*/
QString initiatorClassName() const { return mInitiatorClass; }

/**
* Returns the internal ID used by the object which initiated this request to identify
* individual requests.
*
* This is only available for QNetworkRequests which have had the
* QgsNetworkRequestParameters::AttributeInitiatorRequestId attribute set.
*
* \see initiatorClassName()
*/
QVariant initiatorRequestId() const { return mInitiatorRequestId; }

private:

QNetworkAccessManager::Operation mOperation;
QNetworkRequest mRequest;
QString mOriginatingThreadId;
int mRequestId = 0;
QByteArray mContent;
QString mInitiatorClass;
QVariant mInitiatorRequestId;
};

/**
Expand Down
6 changes: 6 additions & 0 deletions src/providers/arcgisrest/qgsarcgisrestutils.cpp
Expand Up @@ -476,6 +476,7 @@ QByteArray QgsArcGisRestUtils::queryService( const QUrl &u, const QString &authc
QUrl url = parseUrl( u );

QNetworkRequest request( url );
QgsSetRequestInitiatorClass( request, QStringLiteral( "QgsArcGisRestUtils" ) );
for ( auto it = requestHeaders.constBegin(); it != requestHeaders.constEnd(); ++it )
{
request.setRawHeader( it.key().toUtf8(), it.value().toUtf8() );
Expand Down Expand Up @@ -1136,6 +1137,7 @@ void QgsArcGisAsyncQuery::start( const QUrl &url, QByteArray *result, bool allow
{
mResult = result;
QNetworkRequest request( url );
QgsSetRequestInitiatorClass( request, QStringLiteral( "QgsArcGisAsyncQuery" ) );
if ( allowCache )
{
request.setAttribute( QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache );
Expand All @@ -1161,6 +1163,7 @@ void QgsArcGisAsyncQuery::handleReply()
if ( !redirect.isNull() )
{
QNetworkRequest request = mReply->request();
QgsSetRequestInitiatorClass( request, QStringLiteral( "QgsArcGisAsyncQuery" ) );
QgsDebugMsg( "redirecting to " + redirect.toUrl().toString() );
request.setUrl( redirect.toUrl() );
mReply = QgsNetworkAccessManager::instance()->get( request );
Expand Down Expand Up @@ -1188,6 +1191,8 @@ void QgsArcGisAsyncParallelQuery::start( const QVector<QUrl> &urls, QVector<QByt
for ( int i = 0, n = urls.size(); i < n; ++i )
{
QNetworkRequest request( urls[i] );
QgsSetRequestInitiatorClass( request, QStringLiteral( "QgsArcGisAsyncParallelQuery" ) );
QgsSetRequestInitiatorId( request, QString::number( i ) );
request.setAttribute( QNetworkRequest::HttpPipeliningAllowedAttribute, true );
if ( allowCache )
{
Expand Down Expand Up @@ -1217,6 +1222,7 @@ void QgsArcGisAsyncParallelQuery::handleReply()
{
// Handle HTTP redirects
QNetworkRequest request = reply->request();
QgsSetRequestInitiatorClass( request, QStringLiteral( "QgsArcGisAsyncParallelQuery" ) );
QgsDebugMsg( "redirecting to " + redirect.toUrl().toString() );
request.setUrl( redirect.toUrl() );
reply = QgsNetworkAccessManager::instance()->get( request );
Expand Down
3 changes: 3 additions & 0 deletions src/providers/wcs/qgswcscapabilities.cpp
Expand Up @@ -130,6 +130,7 @@ bool QgsWcsCapabilities::sendRequest( QString const &url )
QgsDebugMsg( "url = " + url );
mError.clear();
QNetworkRequest request( url );
QgsSetRequestInitiatorClass( request, QStringLiteral( "QgsWcsCapabilities" ) );
if ( !setAuthorization( request ) )
{
mError = tr( "Download of capabilities failed: network request update failed for authentication config" );
Expand Down Expand Up @@ -347,6 +348,7 @@ void QgsWcsCapabilities::capabilitiesReplyFinished()
emit statusChanged( tr( "Capabilities request redirected." ) );

QNetworkRequest request( redirect.toUrl() );
QgsSetRequestInitiatorClass( request, QStringLiteral( "QgsWcsCapabilities" ) );
if ( !setAuthorization( request ) )
{
mCapabilitiesResponse.clear();
Expand Down Expand Up @@ -387,6 +389,7 @@ void QgsWcsCapabilities::capabilitiesReplyFinished()
{
// Resend request if AlwaysCache
QNetworkRequest request = mCapabilitiesReply->request();
QgsSetRequestInitiatorClass( request, QStringLiteral( "QgsWcsCapabilities" ) );
if ( request.attribute( QNetworkRequest::CacheLoadControlAttribute ).toInt() == QNetworkRequest::AlwaysCache )
{
QgsDebugMsg( QStringLiteral( "Resend request with PreferCache" ) );
Expand Down
3 changes: 3 additions & 0 deletions src/providers/wcs/qgswcsprovider.cpp
Expand Up @@ -1626,6 +1626,7 @@ QgsWcsDownloadHandler::QgsWcsDownloadHandler( const QUrl &url, QgsWcsAuthorizati
}

QNetworkRequest request( url );
QgsSetRequestInitiatorClass( request, QStringLiteral( "QgsWcsDownloadHandler" ) );
if ( !mAuth.setAuthorization( request ) )
{
QgsMessageLog::logMessage( tr( "Network request update failed for authentication config" ),
Expand Down Expand Up @@ -1676,6 +1677,7 @@ void QgsWcsDownloadHandler::cacheReplyFinished()

QgsDebugMsg( QStringLiteral( "redirected getmap: %1" ).arg( redirect.toString() ) );
QNetworkRequest request( redirect.toUrl() );
QgsSetRequestInitiatorClass( request, QStringLiteral( "QgsWcsDownloadHandler" ) );
if ( !mAuth.setAuthorization( request ) )
{
QgsMessageLog::logMessage( tr( "Network request update failed for authentication config" ),
Expand Down Expand Up @@ -1851,6 +1853,7 @@ void QgsWcsDownloadHandler::cacheReplyFinished()
{
// Resend request if AlwaysCache
QNetworkRequest request = mCacheReply->request();
QgsSetRequestInitiatorClass( request, QStringLiteral( "QgsWcsDownloadHandler" ) );
if ( request.attribute( QNetworkRequest::CacheLoadControlAttribute ).toInt() == QNetworkRequest::AlwaysCache )
{
QgsDebugMsg( QStringLiteral( "Resend request with PreferCache" ) );
Expand Down
3 changes: 3 additions & 0 deletions src/providers/wfs/qgswfsrequest.cpp
Expand Up @@ -114,6 +114,7 @@ bool QgsWfsRequest::sendGET( const QUrl &url, bool synchronous, bool forceRefres
QgsDebugMsgLevel( QStringLiteral( "Calling: %1" ).arg( modifiedUrl.toDisplayString( ) ), 4 );

QNetworkRequest request( modifiedUrl );
QgsSetRequestInitiatorClass( request, QStringLiteral( "QgsWfsRequest" ) );
if ( !mUri.auth().setAuthorization( request ) )
{
mErrorCode = QgsWfsRequest::NetworkError;
Expand Down Expand Up @@ -252,6 +253,7 @@ bool QgsWfsRequest::sendPOST( const QUrl &url, const QString &contentTypeHeader,
}

QNetworkRequest request( url );
QgsSetRequestInitiatorClass( request, QStringLiteral( "QgsWfsRequest" ) );
if ( !mUri.auth().setAuthorization( request ) )
{
mErrorCode = QgsWfsRequest::NetworkError;
Expand Down Expand Up @@ -336,6 +338,7 @@ void QgsWfsRequest::replyFinished()
else
{
QNetworkRequest request( toUrl );
QgsSetRequestInitiatorClass( request, QStringLiteral( "QgsWfsRequest" ) );
if ( !mUri.auth().setAuthorization( request ) )
{
mResponse.clear();
Expand Down
2 changes: 2 additions & 0 deletions src/providers/wms/qgswmscapabilities.cpp
Expand Up @@ -1948,6 +1948,7 @@ bool QgsWmsCapabilitiesDownload::downloadCapabilities()
mError.clear();

QNetworkRequest request( url );
QgsSetRequestInitiatorClass( request, QStringLiteral( "QgsWmsCapabilitiesDownload" ) );
if ( !mAuth.setAuthorization( request ) )
{
mError = tr( "Download of capabilities failed: network request update failed for authentication config" );
Expand Down Expand Up @@ -2016,6 +2017,7 @@ void QgsWmsCapabilitiesDownload::capabilitiesReplyFinished()
else
{
QNetworkRequest request( toUrl );
QgsSetRequestInitiatorClass( request, QStringLiteral( "QgsWmsCapabilitiesDownload" ) );
if ( !mAuth.setAuthorization( request ) )
{
mHttpCapabilitiesResponse.clear();
Expand Down

0 comments on commit ca06d40

Please sign in to comment.