Skip to content

Commit

Permalink
QgsBaseNetworkRequest: add an argument for Accept header in GET requests
Browse files Browse the repository at this point in the history
Funded by Planet
  • Loading branch information
rouault authored and nyalldawson committed Oct 25, 2019
1 parent f693f30 commit a1adb32
Show file tree
Hide file tree
Showing 8 changed files with 58 additions and 28 deletions.
70 changes: 49 additions & 21 deletions src/providers/wfs/qgsbasenetworkrequest.cpp
Expand Up @@ -50,7 +50,7 @@ void QgsBaseNetworkRequest::requestTimedOut( QNetworkReply *reply )
mTimedout = true;
}

bool QgsBaseNetworkRequest::sendGET( const QUrl &url, bool synchronous, bool forceRefresh, bool cache )
bool QgsBaseNetworkRequest::sendGET( const QUrl &url, const QString &acceptHeader, bool synchronous, bool forceRefresh, bool cache )
{
abort(); // cancel previous
mIsAborted = false;
Expand All @@ -73,24 +73,6 @@ bool QgsBaseNetworkRequest::sendGET( const QUrl &url, bool synchronous, bool for
modifiedUrlString = QUrl::fromPercentEncoding( modifiedUrlString.toUtf8() );
QgsDebugMsgLevel( QStringLiteral( "Get %1" ).arg( modifiedUrlString ), 4 );
modifiedUrlString = modifiedUrlString.mid( QStringLiteral( "http://" ).size() );
QString args = modifiedUrlString.mid( modifiedUrlString.indexOf( '?' ) );
if ( modifiedUrlString.size() > 256 )
{
args = QCryptographicHash::hash( args.toUtf8(), QCryptographicHash::Md5 ).toHex();
}
else
{
args.replace( QLatin1String( "?" ), QLatin1String( "_" ) );
args.replace( QLatin1String( "&" ), QLatin1String( "_" ) );
args.replace( QLatin1String( "<" ), QLatin1String( "_" ) );
args.replace( QLatin1String( ">" ), QLatin1String( "_" ) );
args.replace( QLatin1String( "'" ), QLatin1String( "_" ) );
args.replace( QLatin1String( "\"" ), QLatin1String( "_" ) );
args.replace( QLatin1String( " " ), QLatin1String( "_" ) );
args.replace( QLatin1String( ":" ), QLatin1String( "_" ) );
args.replace( QLatin1String( "/" ), QLatin1String( "_" ) );
args.replace( QLatin1String( "\n" ), QLatin1String( "_" ) );
}
#ifdef Q_OS_WIN
// Passing "urls" like "http://c:/path" to QUrl 'eats' the : after c,
// so we must restore it
Expand All @@ -99,14 +81,60 @@ bool QgsBaseNetworkRequest::sendGET( const QUrl &url, bool synchronous, bool for
modifiedUrlString = modifiedUrlString[0] + ":/" + modifiedUrlString.mid( 2 );
}
#endif
modifiedUrlString = modifiedUrlString.mid( 0, modifiedUrlString.indexOf( '?' ) ) + args;

// For REST API using URL subpaths, normalize the subpaths
int afterEndpointStartPos = modifiedUrlString.indexOf( "fake_qgis_http_endpoint" ) + strlen( "fake_qgis_http_endpoint" );
QString afterEndpointStart = modifiedUrlString.mid( afterEndpointStartPos );
afterEndpointStart.replace( QLatin1String( "/" ), QLatin1String( "_" ) );
modifiedUrlString = modifiedUrlString.mid( 0, afterEndpointStartPos ) + afterEndpointStart;

if ( !acceptHeader.isEmpty() )
{
if ( modifiedUrlString.indexOf( '?' ) > 0 )
{
modifiedUrlString += QStringLiteral( "&Accept=" ) + acceptHeader;
}
else
{
modifiedUrlString += QStringLiteral( "?Accept=" ) + acceptHeader;
}
}
auto posQuotationMark = modifiedUrlString.indexOf( '?' );
if ( posQuotationMark > 0 )
{
QString args = modifiedUrlString.mid( posQuotationMark );
if ( modifiedUrlString.size() > 256 )
{
QgsDebugMsgLevel( QStringLiteral( "Args before MD5: %1" ).arg( args ), 4 );
args = QCryptographicHash::hash( args.toUtf8(), QCryptographicHash::Md5 ).toHex();
}
else
{
args.replace( QLatin1String( "?" ), QLatin1String( "_" ) );
args.replace( QLatin1String( "&" ), QLatin1String( "_" ) );
args.replace( QLatin1String( "<" ), QLatin1String( "_" ) );
args.replace( QLatin1String( ">" ), QLatin1String( "_" ) );
args.replace( QLatin1String( "'" ), QLatin1String( "_" ) );
args.replace( QLatin1String( "\"" ), QLatin1String( "_" ) );
args.replace( QLatin1String( " " ), QLatin1String( "_" ) );
args.replace( QLatin1String( ":" ), QLatin1String( "_" ) );
args.replace( QLatin1String( "/" ), QLatin1String( "_" ) );
args.replace( QLatin1String( "\n" ), QLatin1String( "_" ) );
}
modifiedUrlString = modifiedUrlString.mid( 0, modifiedUrlString.indexOf( '?' ) ) + args;
}
QgsDebugMsgLevel( QStringLiteral( "Get %1 (after laundering)" ).arg( modifiedUrlString ), 4 );
modifiedUrl = QUrl::fromLocalFile( modifiedUrlString );
}

QgsDebugMsgLevel( QStringLiteral( "Calling: %1" ).arg( modifiedUrl.toDisplayString( ) ), 4 );

QNetworkRequest request( modifiedUrl );
if ( !acceptHeader.isEmpty() )
{
request.setRawHeader( "Accept", acceptHeader.toUtf8() );
}

QgsSetRequestInitiatorClass( request, QStringLiteral( "QgsBaseNetworkRequest" ) );
if ( !mAuth.setAuthorization( request ) )
{
Expand Down Expand Up @@ -241,7 +269,7 @@ bool QgsBaseNetworkRequest::sendPOST( const QUrl &url, const QString &contentTyp
// Hack for testing purposes
QUrl modifiedUrl( url );
modifiedUrl.addQueryItem( QStringLiteral( "POSTDATA" ), QString::fromUtf8( data ) );
return sendGET( modifiedUrl, true, true, false );
return sendGET( modifiedUrl, QString(), true, true, false );
}

QNetworkRequest request( url );
Expand Down
2 changes: 1 addition & 1 deletion src/providers/wfs/qgsbasenetworkrequest.h
Expand Up @@ -35,7 +35,7 @@ class QgsBaseNetworkRequest : public QObject
~QgsBaseNetworkRequest() override;

//! \brief proceed to sending a GET request
bool sendGET( const QUrl &url, bool synchronous, bool forceRefresh = false, bool cache = true );
bool sendGET( const QUrl &url, const QString &acceptHeader, bool synchronous, bool forceRefresh = false, bool cache = true );

//! \brief proceed to sending a synchronous POST request
bool sendPOST( const QUrl &url, const QString &contentTypeHeader, const QByteArray &data );
Expand Down
2 changes: 1 addition & 1 deletion src/providers/wfs/qgswfscapabilities.cpp
Expand Up @@ -50,7 +50,7 @@ bool QgsWfsCapabilities::requestCapabilities( bool synchronous, bool forceRefres
else
url.addQueryItem( QStringLiteral( "VERSION" ), version );

if ( !sendGET( url, synchronous, forceRefresh ) )
if ( !sendGET( url, QString(), synchronous, forceRefresh ) )
{
emit gotCapabilities();
return false;
Expand Down
2 changes: 1 addition & 1 deletion src/providers/wfs/qgswfsdescribefeaturetype.cpp
Expand Up @@ -44,7 +44,7 @@ bool QgsWFSDescribeFeatureType::requestFeatureType( const QString &WFSVersion,
url.addQueryItem( QStringLiteral( "NAMESPACE" ), namespaceValue );
}

return sendGET( url, true, false );
return sendGET( url, QString(), true, false );
}

QString QgsWFSDescribeFeatureType::errorMessageWithReason( const QString &reason )
Expand Down
2 changes: 2 additions & 0 deletions src/providers/wfs/qgswfsfeatureiterator.cpp
Expand Up @@ -48,6 +48,7 @@ QgsWFSFeatureHitsAsyncRequest::QgsWFSFeatureHitsAsyncRequest( QgsWFSDataSourceUR
void QgsWFSFeatureHitsAsyncRequest::launch( const QUrl &url )
{
sendGET( url,
QString(), // content-type
false, /* synchronous */
true, /* forceRefresh */
false /* cache */ );
Expand Down Expand Up @@ -525,6 +526,7 @@ void QgsWFSFeatureDownloaderImpl::run( bool serializeFeatures, int maxFeatures )
}

sendGET( url,
QString(), // content-type
false, /* synchronous */
true, /* forceRefresh */
false /* cache */ );
Expand Down
2 changes: 1 addition & 1 deletion src/providers/wfs/qgswfsprovider.cpp
Expand Up @@ -1380,7 +1380,7 @@ bool QgsWFSProvider::readAttributesFromSchema( QDomDocument &schemaDoc,
QgsDebugMsgLevel( QStringLiteral( "DescribeFeatureType response redirects to: %1" ).arg( schemaLocation ), 4 );

QgsWFSDescribeFeatureType describeFeatureType( mShared->mURI );
if ( !describeFeatureType.sendGET( schemaLocation, true, false ) )
if ( !describeFeatureType.sendGET( schemaLocation, QString(), true, false ) )
{
errorMsg = tr( "Cannot find schema indicated in DescribeFeatureType response." );
QgsMessageLog::logMessage( tr( "DescribeFeatureType network request failed for url %1: %2" ).
Expand Down
4 changes: 2 additions & 2 deletions src/providers/wfs/qgswfsshareddata.cpp
Expand Up @@ -270,7 +270,7 @@ int QgsWFSFeatureHitsRequest::getFeatureCount( const QString &WFSVersion,
}
getFeatureUrl.addQueryItem( QStringLiteral( "RESULTTYPE" ), QStringLiteral( "hits" ) );

if ( !sendGET( getFeatureUrl, true ) )
if ( !sendGET( getFeatureUrl, QString(), true ) )
return -1;

const QByteArray &buffer = response();
Expand Down Expand Up @@ -337,7 +337,7 @@ QgsRectangle QgsWFSSingleFeatureRequest::getExtent()
else
getFeatureUrl.addQueryItem( QStringLiteral( "MAXFEATURES" ), QString::number( 1 ) );

if ( !sendGET( getFeatureUrl, true ) )
if ( !sendGET( getFeatureUrl, QString(), true ) )
return QgsRectangle();

const QByteArray &buffer = response();
Expand Down
2 changes: 1 addition & 1 deletion tests/src/python/test_provider_wfs.py
Expand Up @@ -44,7 +44,7 @@

def sanitize(endpoint, x):
if len(endpoint + x) > 256:
ret = endpoint + hashlib.md5(x.encode()).hexdigest()
ret = endpoint + hashlib.md5(x.replace('/', '_').encode()).hexdigest()
#print('Before: ' + endpoint + x)
#print('After: ' + ret)
return ret
Expand Down

0 comments on commit a1adb32

Please sign in to comment.