Skip to content

Commit

Permalink
Fix MapServer provider ignores referer setting
Browse files Browse the repository at this point in the history
  • Loading branch information
nyalldawson committed May 30, 2019
1 parent 9fd2866 commit f44ce97
Show file tree
Hide file tree
Showing 7 changed files with 52 additions and 18 deletions.
16 changes: 11 additions & 5 deletions src/providers/arcgisrest/qgsamsdataitems.cpp
Expand Up @@ -74,7 +74,7 @@ void QgsAmsRootItem::onConnectionsChanged()

void QgsAmsRootItem::newConnection()
{
QgsNewHttpConnection nc( nullptr, QgsNewHttpConnection::ConnectionOther, QStringLiteral( "qgis/connections-arcgismapserver/" ) );
QgsNewHttpConnection nc( nullptr, QgsNewHttpConnection::ConnectionOther, QStringLiteral( "qgis/connections-arcgismapserver/" ), QString(), QgsNewHttpConnection::FlagShowHttpSettings );
nc.setWindowTitle( tr( "Create a New ArcGIS Map Server Connection" ) );

if ( nc.exec() )
Expand All @@ -98,11 +98,15 @@ QVector<QgsDataItem *> QgsAmsConnectionItem::createChildren()
const QgsOwsConnection connection( QStringLiteral( "ARCGISMAPSERVER" ), mConnName );
const QString url = connection.uri().param( QStringLiteral( "url" ) );
const QString authcfg = connection.uri().param( QStringLiteral( "authcfg" ) );
const QString referer = connection.uri().param( QStringLiteral( "referer" ) );
QgsStringMap headers;
if ( ! referer.isEmpty() )
headers[ QStringLiteral( "Referer" )] = referer;

QVector<QgsDataItem *> layers;
QString errorTitle, errorMessage;

QVariantMap serviceData = QgsArcGisRestUtils::getServiceInfo( url, authcfg, errorTitle, errorMessage );
QVariantMap serviceData = QgsArcGisRestUtils::getServiceInfo( url, authcfg, errorTitle, errorMessage, headers );
if ( serviceData.isEmpty() )
{
if ( !errorMessage.isEmpty() )
Expand Down Expand Up @@ -140,7 +144,7 @@ QVector<QgsDataItem *> QgsAmsConnectionItem::createChildren()
{
QVariantMap layerInfoMap = layerInfo.toMap();
QString id = layerInfoMap[QStringLiteral( "id" )].toString();
QgsAmsLayerItem *layer = new QgsAmsLayerItem( this, mName, url, id, layerInfoMap[QStringLiteral( "name" )].toString(), authid, format, authcfg );
QgsAmsLayerItem *layer = new QgsAmsLayerItem( this, mName, url, id, layerInfoMap[QStringLiteral( "name" )].toString(), authid, format, authcfg, headers );
layers.append( layer );
}

Expand Down Expand Up @@ -177,7 +181,7 @@ QList<QAction *> QgsAmsConnectionItem::actions( QWidget *parent )

void QgsAmsConnectionItem::editConnection()
{
QgsNewHttpConnection nc( nullptr, QgsNewHttpConnection::ConnectionOther, QStringLiteral( "qgis/connections-arcgismapserver/" ), mName );
QgsNewHttpConnection nc( nullptr, QgsNewHttpConnection::ConnectionOther, QStringLiteral( "qgis/connections-arcgismapserver/" ), mName, QgsNewHttpConnection::FlagShowHttpSettings );
nc.setWindowTitle( tr( "Modify ArcGIS Map Server Connection" ) );

if ( nc.exec() )
Expand All @@ -195,12 +199,14 @@ void QgsAmsConnectionItem::deleteConnection()

///////////////////////////////////////////////////////////////////////////////

QgsAmsLayerItem::QgsAmsLayerItem( QgsDataItem *parent, const QString &, const QString &url, const QString &id, const QString &title, const QString &authid, const QString &format, const QString &authcfg )
QgsAmsLayerItem::QgsAmsLayerItem( QgsDataItem *parent, const QString &, const QString &url, const QString &id, const QString &title, const QString &authid, const QString &format, const QString &authcfg, const QgsStringMap &headers )
: QgsLayerItem( parent, title, url + '/' + id, QString(), QgsLayerItem::Raster, QStringLiteral( "arcgismapserver" ) )
{
mUri = QStringLiteral( "crs='%1' format='%2' layer='%3' url='%4'" ).arg( authid, format, id, url );
if ( !authcfg.isEmpty() )
mUri += QStringLiteral( " authcfg='%1'" ).arg( authcfg );
if ( !headers.value( QStringLiteral( "Referer" ) ).isEmpty() )
mUri += QStringLiteral( " referer='%1'" ).arg( headers.value( QStringLiteral( "Referer" ) ) );
setState( Populated );
mIconName = QStringLiteral( "mIconAms.svg" );
setToolTip( mPath );
Expand Down
2 changes: 1 addition & 1 deletion src/providers/arcgisrest/qgsamsdataitems.h
Expand Up @@ -77,7 +77,7 @@ class QgsAmsLayerItem : public QgsLayerItem
Q_OBJECT

public:
QgsAmsLayerItem( QgsDataItem *parent, const QString &name, const QString &url, const QString &id, const QString &title, const QString &authid, const QString &format, const QString &authcfg );
QgsAmsLayerItem( QgsDataItem *parent, const QString &name, const QString &url, const QString &id, const QString &title, const QString &authid, const QString &format, const QString &authcfg, const QgsStringMap &headers );
};


Expand Down
22 changes: 16 additions & 6 deletions src/providers/arcgisrest/qgsamsprovider.cpp
Expand Up @@ -52,10 +52,14 @@ void QgsAmsLegendFetcher::start()
// http://sampleserver5.arcgisonline.com/arcgis/rest/services/CommunityAddressing/MapServer/legend?f=pjson
QgsDataSourceUri dataSource( mProvider->dataSourceUri() );
const QString authCfg = dataSource.authConfigId();
const QString referer = dataSource.param( QStringLiteral( "referer" ) );
QgsStringMap headers;
if ( !referer.isEmpty() )
headers[ QStringLiteral( "Referer" )] = referer;

QUrl queryUrl( dataSource.param( QStringLiteral( "url" ) ) + "/legend" );
queryUrl.addQueryItem( QStringLiteral( "f" ), QStringLiteral( "json" ) );
mQuery->start( queryUrl, authCfg, &mQueryReply );
mQuery->start( queryUrl, authCfg, &mQueryReply, false, headers );
}

void QgsAmsLegendFetcher::handleError( const QString &errorTitle, const QString &errorMsg )
Expand Down Expand Up @@ -134,13 +138,18 @@ void QgsAmsLegendFetcher::handleFinished()
QgsAmsProvider::QgsAmsProvider( const QString &uri, const ProviderOptions &options )
: QgsRasterDataProvider( uri, options )
{
QgsDataSourceUri dataSource( dataSourceUri() );
const QString referer = dataSource.param( QStringLiteral( "referer" ) );
if ( !referer.isEmpty() )
mRequestHeaders[ QStringLiteral( "Referer" )] = referer;

mLegendFetcher = new QgsAmsLegendFetcher( this );

QgsDataSourceUri dataSource( dataSourceUri() );

const QString authcfg = dataSource.authConfigId();

mServiceInfo = QgsArcGisRestUtils::getServiceInfo( dataSource.param( QStringLiteral( "url" ) ), authcfg, mErrorTitle, mError );
mLayerInfo = QgsArcGisRestUtils::getLayerInfo( dataSource.param( QStringLiteral( "url" ) ) + "/" + dataSource.param( QStringLiteral( "layer" ) ), authcfg, mErrorTitle, mError );
mServiceInfo = QgsArcGisRestUtils::getServiceInfo( dataSource.param( QStringLiteral( "url" ) ), authcfg, mErrorTitle, mError, mRequestHeaders );
mLayerInfo = QgsArcGisRestUtils::getLayerInfo( dataSource.param( QStringLiteral( "url" ) ) + "/" + dataSource.param( QStringLiteral( "layer" ) ), authcfg, mErrorTitle, mError, mRequestHeaders );

const QVariantMap extentData = mLayerInfo.value( QStringLiteral( "extent" ) ).toMap();
mExtent.setXMinimum( extentData[QStringLiteral( "xmin" )].toDouble() );
Expand Down Expand Up @@ -176,6 +185,7 @@ QgsAmsProvider::QgsAmsProvider( const QgsAmsProvider &other, const QgsDataProvid
, mExtent( other.mExtent )
, mSubLayers( other.mSubLayers )
, mSubLayerVisibilities( other.mSubLayerVisibilities )
, mRequestHeaders( other.mRequestHeaders )
// intentionally omitted:
// - mErrorTitle
// - mError
Expand Down Expand Up @@ -350,7 +360,7 @@ void QgsAmsProvider::draw( const QgsRectangle &viewExtent, int pixelWidth, int p
queries[( iy - iyStart ) * ixCount + ( ix - ixStart )] = QUrl( dataSource.param( QStringLiteral( "url" ) ) + QStringLiteral( "/tile/%1/%2/%3" ).arg( level ).arg( iy ).arg( ix ) );
}
}
QgsArcGisAsyncParallelQuery query( authcfg );
QgsArcGisAsyncParallelQuery query( authcfg, mRequestHeaders );
QEventLoop evLoop;
connect( &query, &QgsArcGisAsyncParallelQuery::finished, &evLoop, &QEventLoop::quit );
query.start( queries, &results, true );
Expand Down Expand Up @@ -384,7 +394,7 @@ void QgsAmsProvider::draw( const QgsRectangle &viewExtent, int pixelWidth, int p
mError.clear();
mErrorTitle.clear();
QString contentType;
QByteArray reply = QgsArcGisRestUtils::queryService( requestUrl, authcfg, mErrorTitle, mError, QgsStringMap(), feedback, &contentType );
QByteArray reply = QgsArcGisRestUtils::queryService( requestUrl, authcfg, mErrorTitle, mError, mRequestHeaders, feedback, &contentType );
if ( !mError.isEmpty() )
{
mCachedImage = QImage();
Expand Down
1 change: 1 addition & 0 deletions src/providers/arcgisrest/qgsamsprovider.h
Expand Up @@ -105,6 +105,7 @@ class QgsAmsProvider : public QgsRasterDataProvider
QString mError;
QImage mCachedImage;
QgsRectangle mCachedImageExtent;
QgsStringMap mRequestHeaders;
};

#endif // QGSMAPSERVERPROVIDER_H
9 changes: 7 additions & 2 deletions src/providers/arcgisrest/qgsamssourceselect.cpp
Expand Up @@ -39,7 +39,12 @@ bool QgsAmsSourceSelect::connectToService( const QgsOwsConnection &connection )
QString errorTitle, errorMessage;

const QString authcfg = connection.uri().param( QStringLiteral( "authcfg" ) );
const QVariantMap serviceInfoMap = QgsArcGisRestUtils::getServiceInfo( connection.uri().param( QStringLiteral( "url" ) ), authcfg, errorTitle, errorMessage );
const QString referer = connection.uri().param( QStringLiteral( "referer" ) );
QgsStringMap headers;
if ( ! referer.isEmpty() )
headers[ QStringLiteral( "Referer" )] = referer;

const QVariantMap serviceInfoMap = QgsArcGisRestUtils::getServiceInfo( connection.uri().param( QStringLiteral( "url" ) ), authcfg, errorTitle, errorMessage, headers );
if ( serviceInfoMap.isEmpty() )
{
QMessageBox::warning( this, tr( "Error" ), tr( "Failed to retrieve service capabilities:\n%1: %2" ).arg( errorTitle, errorMessage ) );
Expand All @@ -60,7 +65,7 @@ bool QgsAmsSourceSelect::connectToService( const QgsOwsConnection &connection )

// Get layer info
QVariantMap layerData = QgsArcGisRestUtils::getLayerInfo( connection.uri().param( QStringLiteral( "url" ) ) + "/" + layerInfoMap[QStringLiteral( "id" )].toString(),
authcfg, errorTitle, errorMessage );
authcfg, errorTitle, errorMessage, headers );
if ( layerData.isEmpty() )
{
layerErrors.append( QStringLiteral( "Layer %1: %2 - %3" ).arg( layerInfoMap[QStringLiteral( "id" )].toString(), errorTitle, errorMessage ) );
Expand Down
15 changes: 13 additions & 2 deletions src/providers/arcgisrest/qgsarcgisrestutils.cpp
Expand Up @@ -1126,11 +1126,16 @@ QgsArcGisAsyncQuery::~QgsArcGisAsyncQuery()
mReply->deleteLater();
}

void QgsArcGisAsyncQuery::start( const QUrl &url, const QString &authCfg, QByteArray *result, bool allowCache )
void QgsArcGisAsyncQuery::start( const QUrl &url, const QString &authCfg, QByteArray *result, bool allowCache, const QgsStringMap &headers )
{
mResult = result;
QNetworkRequest request( url );

for ( auto it = headers.constBegin(); it != headers.constEnd(); ++it )
{
request.setRawHeader( it.key().toUtf8(), it.value().toUtf8() );
}

if ( !authCfg.isEmpty() && !QgsApplication::authManager()->updateNetworkRequest( request, authCfg ) )
{
const QString error = tr( "network request update failed for authentication config" );
Expand Down Expand Up @@ -1179,9 +1184,10 @@ void QgsArcGisAsyncQuery::handleReply()

///////////////////////////////////////////////////////////////////////////////

QgsArcGisAsyncParallelQuery::QgsArcGisAsyncParallelQuery( const QString &authcfg, QObject *parent )
QgsArcGisAsyncParallelQuery::QgsArcGisAsyncParallelQuery( const QString &authcfg, const QgsStringMap &requestHeaders, QObject *parent )
: QObject( parent )
, mAuthCfg( authcfg )
, mRequestHeaders( requestHeaders )
{
}

Expand All @@ -1195,6 +1201,11 @@ void QgsArcGisAsyncParallelQuery::start( const QVector<QUrl> &urls, QVector<QByt
QNetworkRequest request( urls[i] );
QgsSetRequestInitiatorClass( request, QStringLiteral( "QgsArcGisAsyncParallelQuery" ) );
QgsSetRequestInitiatorId( request, QString::number( i ) );

for ( auto it = mRequestHeaders.constBegin(); it != mRequestHeaders.constEnd(); ++it )
{
request.setRawHeader( it.key().toUtf8(), it.value().toUtf8() );
}
if ( !mAuthCfg.isEmpty() && !QgsApplication::authManager()->updateNetworkRequest( request, mAuthCfg ) )
{
const QString error = tr( "network request update failed for authentication config" );
Expand Down
5 changes: 3 additions & 2 deletions src/providers/arcgisrest/qgsarcgisrestutils.h
Expand Up @@ -107,7 +107,7 @@ class QgsArcGisAsyncQuery : public QObject
QgsArcGisAsyncQuery( QObject *parent = nullptr );
~QgsArcGisAsyncQuery() override;

void start( const QUrl &url, const QString &authCfg, QByteArray *result, bool allowCache = false );
void start( const QUrl &url, const QString &authCfg, QByteArray *result, bool allowCache = false, const QgsStringMap &headers = QgsStringMap() );
signals:
void finished();
void failed( QString errorTitle, QString errorName );
Expand All @@ -123,7 +123,7 @@ class QgsArcGisAsyncParallelQuery : public QObject
{
Q_OBJECT
public:
QgsArcGisAsyncParallelQuery( const QString &authcfg, QObject *parent = nullptr );
QgsArcGisAsyncParallelQuery( const QString &authcfg, const QgsStringMap &requestHeaders, QObject *parent = nullptr );
void start( const QVector<QUrl> &urls, QVector<QByteArray> *results, bool allowCache = false );

signals:
Expand All @@ -136,6 +136,7 @@ class QgsArcGisAsyncParallelQuery : public QObject
int mPendingRequests = 0;
QStringList mErrors;
QString mAuthCfg;
QgsStringMap mRequestHeaders;
};

#endif // QGSARCGISRESTUTILS_H

0 comments on commit f44ce97

Please sign in to comment.