Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit cb7af3c

Browse files
committedMay 25, 2019
[WFS provider] Emit TYPENAME and TYPENAMES for WFS 2.0 DescribeFeatureType & GetFeature
Fixes Redmine #21768 and #9849 Due to confusion in the WFS 2.0 sepecification the situation is that WFS 2.0 servers 'randomly' recognize TYPENAME or TYPENAMES depending on DescribeFeatureType and GetFeature requests. So emit both parameters as tests show that it fixes issues and doesn't seem to cause harm.
1 parent 465e6f0 commit cb7af3c

File tree

7 files changed

+99
-188
lines changed

7 files changed

+99
-188
lines changed
 

‎src/providers/wfs/qgswfsdescribefeaturetype.cpp

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,18 +22,26 @@ QgsWFSDescribeFeatureType::QgsWFSDescribeFeatureType( QgsWFSDataSourceURI &uri )
2222
}
2323

2424
bool QgsWFSDescribeFeatureType::requestFeatureType( const QString &WFSVersion,
25-
const QString &typeName, const QgsWfsCapabilities::Capabilities &caps, bool bUsePlural )
25+
const QString &typeName, const QgsWfsCapabilities::Capabilities &caps )
2626
{
2727
QUrl url( mUri.requestUrl( QStringLiteral( "DescribeFeatureType" ) ) );
2828
url.addQueryItem( QStringLiteral( "VERSION" ), WFSVersion );
2929

30-
url.addQueryItem( bUsePlural ?
31-
QStringLiteral( "TYPENAMES" ) : QStringLiteral( "TYPENAME" ), typeName );
3230
QString namespaceValue( caps.getNamespaceParameterValue( WFSVersion, typeName ) );
31+
32+
if ( WFSVersion.startsWith( QLatin1String( "2.0" ) ) )
33+
{
34+
url.addQueryItem( QStringLiteral( "TYPENAMES" ), typeName );
35+
if ( !namespaceValue.isEmpty() )
36+
{
37+
url.addQueryItem( QStringLiteral( "NAMESPACES" ), namespaceValue );
38+
}
39+
}
40+
41+
url.addQueryItem( QStringLiteral( "TYPENAME" ), typeName );
3342
if ( !namespaceValue.isEmpty() )
3443
{
35-
url.addQueryItem( bUsePlural ?
36-
QStringLiteral( "NAMESPACES" ) : QStringLiteral( "NAMESPACE" ), namespaceValue );
44+
url.addQueryItem( QStringLiteral( "NAMESPACE" ), namespaceValue );
3745
}
3846

3947
return sendGET( url, true, false );

‎src/providers/wfs/qgswfsdescribefeaturetype.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,7 @@ class QgsWFSDescribeFeatureType : public QgsWfsRequest
2828
//! Issue the request
2929
bool requestFeatureType( const QString &WFSVersion,
3030
const QString &typeName,
31-
const QgsWfsCapabilities::Capabilities &caps,
32-
bool bUsePlural );
31+
const QgsWfsCapabilities::Capabilities &caps );
3332

3433
protected:
3534
QString errorMessageWithReason( const QString &reason ) override;

‎src/providers/wfs/qgswfsfeatureiterator.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -235,8 +235,8 @@ QUrl QgsWFSFeatureDownloader::buildURL( qint64 startIndex, int maxFeatures, bool
235235
}
236236
if ( mShared->mWFSVersion.startsWith( QLatin1String( "2.0" ) ) )
237237
getFeatureUrl.addQueryItem( QStringLiteral( "TYPENAMES" ), typenames );
238-
else
239-
getFeatureUrl.addQueryItem( QStringLiteral( "TYPENAME" ), typenames );
238+
getFeatureUrl.addQueryItem( QStringLiteral( "TYPENAME" ), typenames );
239+
240240
if ( forHits )
241241
{
242242
getFeatureUrl.addQueryItem( QStringLiteral( "RESULTTYPE" ), QStringLiteral( "hits" ) );
@@ -392,8 +392,9 @@ QUrl QgsWFSFeatureDownloader::buildURL( qint64 startIndex, int maxFeatures, bool
392392

393393
if ( !namespaces.isEmpty() )
394394
{
395-
getFeatureUrl.addQueryItem( QStringLiteral( "NAMESPACES" ),
396-
namespaces );
395+
if ( mShared->mWFSVersion.startsWith( QLatin1String( "2.0" ) ) )
396+
getFeatureUrl.addQueryItem( QStringLiteral( "NAMESPACES" ), namespaces );
397+
getFeatureUrl.addQueryItem( QStringLiteral( "NAMESPACE" ), namespaces );
397398
}
398399

399400
QgsDebugMsgLevel( QStringLiteral( "WFS GetFeature URL: %1" ).arg( getFeatureUrl.toDisplayString( ) ), 2 );

‎src/providers/wfs/qgswfsprovider.cpp

Lines changed: 15 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -420,32 +420,17 @@ bool QgsWFSProvider::processSQL( const QString &sqlString, QString &errorMsg, QS
420420
}
421421

422422
QgsWFSDescribeFeatureType describeFeatureType( mShared->mURI );
423-
bool bUsePlural = false;
424-
QByteArray response;
425-
for ( int i = 0; i < 2; i++ )
423+
if ( !describeFeatureType.requestFeatureType( mShared->mWFSVersion,
424+
concatenatedTypenames, mShared->mCaps ) )
426425
{
427-
if ( !describeFeatureType.requestFeatureType( mShared->mWFSVersion,
428-
concatenatedTypenames, mShared->mCaps, bUsePlural ) )
429-
{
430-
errorMsg = tr( "DescribeFeatureType failed for url %1: %2" ).
431-
arg( dataSourceUri(), describeFeatureType.errorMessage() );
432-
return false;
433-
}
434-
435-
response = describeFeatureType.response();
436-
// "http://geoportal.samregion.ru/wfs12?SERVICE=WFS&REQUEST=DescribeFeatureType&TYPENAME=EC_1_132&VERSION=2.0.0"
437-
// returns a <ExceptionText><![CDATA[Missing typeNames parameter]]></ExceptionText>
438-
if ( i == 0 && response.indexOf( "<![CDATA[Missing typeNames parameter]]>" ) >= 0 )
439-
{
440-
QgsDebugMsg( QStringLiteral( "Server does not accept TYPENAME parameter for DescribeFeatureType. Re-trying with TYPENAMES" ) );
441-
bUsePlural = true;
442-
}
443-
else
444-
{
445-
break;
446-
}
426+
errorMsg = tr( "DescribeFeatureType failed for url %1: %2" ).
427+
arg( dataSourceUri(), describeFeatureType.errorMessage() );
428+
return false;
447429
}
448430

431+
QByteArray response = describeFeatureType.response();
432+
433+
449434
QDomDocument describeFeatureDocument;
450435
errorMsg.clear();
451436
if ( !describeFeatureDocument.setContent( response, true, &errorMsg ) )
@@ -1278,44 +1263,16 @@ bool QgsWFSProvider::describeFeatureType( QString &geometryAttribute, QgsFields
12781263

12791264
QgsWFSDescribeFeatureType describeFeatureType( mShared->mURI );
12801265

1281-
bool bUsePlural = false;
1282-
QByteArray response;
1283-
1284-
for ( int i = 0; i < 2; i++ )
1266+
if ( !describeFeatureType.requestFeatureType( mShared->mWFSVersion,
1267+
mShared->mURI.typeName(), mShared->mCaps ) )
12851268
{
1286-
if ( !describeFeatureType.requestFeatureType( mShared->mWFSVersion,
1287-
mShared->mURI.typeName(), mShared->mCaps, bUsePlural ) )
1288-
{
1289-
QgsMessageLog::logMessage( tr( "DescribeFeatureType network request failed for url %1: %2" ).
1290-
arg( dataSourceUri(), describeFeatureType.errorMessage() ), tr( "WFS" ) );
1291-
return false;
1292-
}
1293-
1294-
response = describeFeatureType.response();
1295-
// "http://geoportal.samregion.ru/wfs12?SERVICE=WFS&REQUEST=DescribeFeatureType&TYPENAME=EC_1_132&VERSION=2.0.0"
1296-
// returns a <ExceptionText><![CDATA[Missing typeNames parameter]]></ExceptionText>
1297-
if ( i == 0 && response.indexOf( "<![CDATA[Missing typeNames parameter]]>" ) >= 0 )
1298-
{
1299-
QgsDebugMsg( QStringLiteral( "Server does not accept TYPENAME parameter for DescribeFeatureType. Re-trying with TYPENAMES" ) );
1300-
bUsePlural = true;
1301-
}
1302-
// "http://services.cuzk.cz/wfs/inspire-cp-wfs.asp?SERVICE=WFS&REQUEST=DescribeFeatureType&VERSION=2.0.0&TYPENAME=cp:CadastralParcel" returns
1303-
// <!--Generated by Marushka, version 4.2.5.0, GEOVAP, spol. s r.o., 31.05.2018.-->
1304-
// <ExceptionReport xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" version="1.0.0" xml:lang="en-US" xmlns="http://www.opengis.net/ows/1.1">
1305-
// <Exception exceptionCode="OperationProcessingFailed" />
1306-
// </ExceptionReport>
1307-
else if ( i == 0 && response.indexOf( "<!--Generated by Marushka" ) >= 0 &&
1308-
response.indexOf( "OperationProcessingFailed" ) >= 0 )
1309-
{
1310-
QgsDebugMsg( QStringLiteral( "Server does not accept TYPENAME parameter for DescribeFeatureType. Re-trying with TYPENAMES" ) );
1311-
bUsePlural = true;
1312-
}
1313-
else
1314-
{
1315-
break;
1316-
}
1269+
QgsMessageLog::logMessage( tr( "DescribeFeatureType network request failed for url %1: %2" ).
1270+
arg( dataSourceUri(), describeFeatureType.errorMessage() ), tr( "WFS" ) );
1271+
return false;
13171272
}
13181273

1274+
QByteArray response = describeFeatureType.response();
1275+
13191276
QDomDocument describeFeatureDocument;
13201277
QString errorMsg;
13211278
if ( !describeFeatureDocument.setContent( response, true, &errorMsg ) )

‎src/providers/wfs/qgswfsshareddata.cpp

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1352,16 +1352,14 @@ int QgsWFSFeatureHitsRequest::getFeatureCount( const QString &WFSVersion,
13521352
{
13531353
getFeatureUrl.addQueryItem( QStringLiteral( "TYPENAMES" ), typeName );
13541354
}
1355-
else
1356-
{
1357-
getFeatureUrl.addQueryItem( QStringLiteral( "TYPENAME" ), typeName );
1358-
}
1355+
getFeatureUrl.addQueryItem( QStringLiteral( "TYPENAME" ), typeName );
13591356

13601357
QString namespaceValue( caps.getNamespaceParameterValue( WFSVersion, typeName ) );
13611358
if ( !namespaceValue.isEmpty() )
13621359
{
1363-
getFeatureUrl.addQueryItem( WFSVersion.startsWith( QLatin1String( "2.0" ) ) ?
1364-
QStringLiteral( "NAMESPACES" ) : QStringLiteral( "NAMESPACE" ), namespaceValue );
1360+
if ( WFSVersion.startsWith( QLatin1String( "2.0" ) ) )
1361+
getFeatureUrl.addQueryItem( QStringLiteral( "NAMESPACES" ), namespaceValue );
1362+
getFeatureUrl.addQueryItem( QStringLiteral( "NAMESPACE" ), namespaceValue );
13651363
}
13661364

13671365
if ( !filter.isEmpty() )
@@ -1422,14 +1420,14 @@ QgsRectangle QgsWFSSingleFeatureRequest::getExtent()
14221420
getFeatureUrl.addQueryItem( QStringLiteral( "VERSION" ), mShared->mWFSVersion );
14231421
if ( mShared->mWFSVersion .startsWith( QLatin1String( "2.0" ) ) )
14241422
getFeatureUrl.addQueryItem( QStringLiteral( "TYPENAMES" ), mUri.typeName() );
1425-
else
1426-
getFeatureUrl.addQueryItem( QStringLiteral( "TYPENAME" ), mUri.typeName() );
1423+
getFeatureUrl.addQueryItem( QStringLiteral( "TYPENAME" ), mUri.typeName() );
14271424

14281425
QString namespaceValue( mShared->mCaps.getNamespaceParameterValue( mShared->mWFSVersion, mUri.typeName() ) );
14291426
if ( !namespaceValue.isEmpty() )
14301427
{
1431-
getFeatureUrl.addQueryItem( mShared->mWFSVersion.startsWith( QLatin1String( "2.0" ) ) ?
1432-
QStringLiteral( "NAMESPACES" ) : QStringLiteral( "NAMESPACE" ), namespaceValue );
1428+
if ( mShared->mWFSVersion.startsWith( QLatin1String( "2.0" ) ) )
1429+
getFeatureUrl.addQueryItem( QStringLiteral( "NAMESPACES" ), namespaceValue );
1430+
getFeatureUrl.addQueryItem( QStringLiteral( "NAMESPACE" ), namespaceValue );
14331431
}
14341432

14351433
if ( mShared->mWFSVersion .startsWith( QLatin1String( "2.0" ) ) )

‎tests/src/python/test_provider_wfs.py

Lines changed: 54 additions & 106 deletions
Large diffs are not rendered by default.

‎tests/src/python/test_provider_wfs_gui.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ def test(self):
219219
self.addWfsLayer_layer_name = None
220220
main_dialog.addVectorLayer.connect(self.slotAddWfsLayer)
221221
QTest.mouseClick(buttonAdd, Qt.LeftButton)
222-
self.assertEqual(self.addWfsLayer_uri, ' restrictToRequestBBOX=\'1\' srsname=\'EPSG:4326\' typename=\'my:typename\' url=\'' + "http://" + expected_endpoint + '\' version=\'auto\' table="" sql=')
222+
self.assertEqual(self.addWfsLayer_uri, ' pagingEnabled=\'true\' restrictToRequestBBOX=\'1\' srsname=\'EPSG:4326\' typename=\'my:typename\' url=\'' + "http://" + expected_endpoint + '\' version=\'auto\' table="" sql=')
223223
self.assertEqual(self.addWfsLayer_layer_name, 'my:typename')
224224

225225
# Click on Build Query
@@ -235,7 +235,7 @@ def test(self):
235235

236236
# Click again but with valid DescribeFeatureType
237237

238-
with open(sanitize(endpoint, '?SERVICE=WFS&REQUEST=DescribeFeatureType&VERSION=2.0.0&TYPENAME=my:typename'), 'wb') as f:
238+
with open(sanitize(endpoint, '?SERVICE=WFS&REQUEST=DescribeFeatureType&VERSION=2.0.0&TYPENAMES=my:typename&TYPENAME=my:typename'), 'wb') as f:
239239
f.write("""
240240
<xsd:schema xmlns:my="http://my" xmlns:gml="http://www.opengis.net/gml/3.2" xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="http://my">
241241
<xsd:import namespace="http://www.opengis.net/gml/3.2"/>
@@ -292,7 +292,7 @@ def test(self):
292292
self.addWfsLayer_layer_name = None
293293
main_dialog.addVectorLayer.connect(self.slotAddWfsLayer)
294294
QTest.mouseClick(buttonAdd, Qt.LeftButton)
295-
self.assertEqual(self.addWfsLayer_uri, ' restrictToRequestBBOX=\'1\' srsname=\'EPSG:4326\' typename=\'my:typename\' url=\'' + "http://" + expected_endpoint + '\' version=\'auto\' table="" sql=SELECT * FROM typename WHERE 1 = 1')
295+
self.assertEqual(self.addWfsLayer_uri, ' pagingEnabled=\'true\' restrictToRequestBBOX=\'1\' srsname=\'EPSG:4326\' typename=\'my:typename\' url=\'' + "http://" + expected_endpoint + '\' version=\'auto\' table="" sql=SELECT * FROM typename WHERE 1 = 1')
296296
self.assertEqual(self.addWfsLayer_layer_name, 'my:typename')
297297

298298
# main_dialog.setProperty("hideDialogs", None)

0 commit comments

Comments
 (0)
Please sign in to comment.