Skip to content

Commit 0768dde

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 1e09a27 commit 0768dde

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" ) );
@@ -393,8 +393,9 @@ QUrl QgsWFSFeatureDownloader::buildURL( qint64 startIndex, int maxFeatures, bool
393393

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

400401
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
@@ -425,32 +425,17 @@ bool QgsWFSProvider::processSQL( const QString &sqlString, QString &errorMsg, QS
425425
}
426426

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

436+
QByteArray response = describeFeatureType.response();
437+
438+
454439
QDomDocument describeFeatureDocument;
455440
errorMsg.clear();
456441
if ( !describeFeatureDocument.setContent( response, true, &errorMsg ) )
@@ -1286,44 +1271,16 @@ bool QgsWFSProvider::describeFeatureType( QString &geometryAttribute, QgsFields
12861271

12871272
QgsWFSDescribeFeatureType describeFeatureType( mShared->mURI );
12881273

1289-
bool bUsePlural = false;
1290-
QByteArray response;
1291-
1292-
for ( int i = 0; i < 2; i++ )
1274+
if ( !describeFeatureType.requestFeatureType( mShared->mWFSVersion,
1275+
mShared->mURI.typeName(), mShared->mCaps ) )
12931276
{
1294-
if ( !describeFeatureType.requestFeatureType( mShared->mWFSVersion,
1295-
mShared->mURI.typeName(), mShared->mCaps, bUsePlural ) )
1296-
{
1297-
QgsMessageLog::logMessage( tr( "DescribeFeatureType network request failed for url %1: %2" ).
1298-
arg( dataSourceUri(), describeFeatureType.errorMessage() ), tr( "WFS" ) );
1299-
return false;
1300-
}
1301-
1302-
response = describeFeatureType.response();
1303-
// "http://geoportal.samregion.ru/wfs12?SERVICE=WFS&REQUEST=DescribeFeatureType&TYPENAME=EC_1_132&VERSION=2.0.0"
1304-
// returns a <ExceptionText><![CDATA[Missing typeNames parameter]]></ExceptionText>
1305-
if ( i == 0 && response.indexOf( "<![CDATA[Missing typeNames parameter]]>" ) >= 0 )
1306-
{
1307-
QgsDebugMsg( QStringLiteral( "Server does not accept TYPENAME parameter for DescribeFeatureType. Re-trying with TYPENAMES" ) );
1308-
bUsePlural = true;
1309-
}
1310-
// "http://services.cuzk.cz/wfs/inspire-cp-wfs.asp?SERVICE=WFS&REQUEST=DescribeFeatureType&VERSION=2.0.0&TYPENAME=cp:CadastralParcel" returns
1311-
// <!--Generated by Marushka, version 4.2.5.0, GEOVAP, spol. s r.o., 31.05.2018.-->
1312-
// <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">
1313-
// <Exception exceptionCode="OperationProcessingFailed" />
1314-
// </ExceptionReport>
1315-
else if ( i == 0 && response.indexOf( "<!--Generated by Marushka" ) >= 0 &&
1316-
response.indexOf( "OperationProcessingFailed" ) >= 0 )
1317-
{
1318-
QgsDebugMsg( QStringLiteral( "Server does not accept TYPENAME parameter for DescribeFeatureType. Re-trying with TYPENAMES" ) );
1319-
bUsePlural = true;
1320-
}
1321-
else
1322-
{
1323-
break;
1324-
}
1277+
QgsMessageLog::logMessage( tr( "DescribeFeatureType network request failed for url %1: %2" ).
1278+
arg( dataSourceUri(), describeFeatureType.errorMessage() ), tr( "WFS" ) );
1279+
return false;
13251280
}
13261281

1282+
QByteArray response = describeFeatureType.response();
1283+
13271284
QDomDocument describeFeatureDocument;
13281285
QString errorMsg;
13291286
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
@@ -1356,16 +1356,14 @@ int QgsWFSFeatureHitsRequest::getFeatureCount( const QString &WFSVersion,
13561356
{
13571357
getFeatureUrl.addQueryItem( QStringLiteral( "TYPENAMES" ), typeName );
13581358
}
1359-
else
1360-
{
1361-
getFeatureUrl.addQueryItem( QStringLiteral( "TYPENAME" ), typeName );
1362-
}
1359+
getFeatureUrl.addQueryItem( QStringLiteral( "TYPENAME" ), typeName );
13631360

13641361
QString namespaceValue( caps.getNamespaceParameterValue( WFSVersion, typeName ) );
13651362
if ( !namespaceValue.isEmpty() )
13661363
{
1367-
getFeatureUrl.addQueryItem( WFSVersion.startsWith( QLatin1String( "2.0" ) ) ?
1368-
QStringLiteral( "NAMESPACES" ) : QStringLiteral( "NAMESPACE" ), namespaceValue );
1364+
if ( WFSVersion.startsWith( QLatin1String( "2.0" ) ) )
1365+
getFeatureUrl.addQueryItem( QStringLiteral( "NAMESPACES" ), namespaceValue );
1366+
getFeatureUrl.addQueryItem( QStringLiteral( "NAMESPACE" ), namespaceValue );
13691367
}
13701368

13711369
if ( !filter.isEmpty() )
@@ -1426,14 +1424,14 @@ QgsRectangle QgsWFSSingleFeatureRequest::getExtent()
14261424
getFeatureUrl.addQueryItem( QStringLiteral( "VERSION" ), mShared->mWFSVersion );
14271425
if ( mShared->mWFSVersion .startsWith( QLatin1String( "2.0" ) ) )
14281426
getFeatureUrl.addQueryItem( QStringLiteral( "TYPENAMES" ), mUri.typeName() );
1429-
else
1430-
getFeatureUrl.addQueryItem( QStringLiteral( "TYPENAME" ), mUri.typeName() );
1427+
getFeatureUrl.addQueryItem( QStringLiteral( "TYPENAME" ), mUri.typeName() );
14311428

14321429
QString namespaceValue( mShared->mCaps.getNamespaceParameterValue( mShared->mWFSVersion, mUri.typeName() ) );
14331430
if ( !namespaceValue.isEmpty() )
14341431
{
1435-
getFeatureUrl.addQueryItem( mShared->mWFSVersion.startsWith( QLatin1String( "2.0" ) ) ?
1436-
QStringLiteral( "NAMESPACES" ) : QStringLiteral( "NAMESPACE" ), namespaceValue );
1432+
if ( mShared->mWFSVersion.startsWith( QLatin1String( "2.0" ) ) )
1433+
getFeatureUrl.addQueryItem( QStringLiteral( "NAMESPACES" ), namespaceValue );
1434+
getFeatureUrl.addQueryItem( QStringLiteral( "NAMESPACE" ), namespaceValue );
14371435
}
14381436

14391437
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
@@ -217,7 +217,7 @@ def test(self):
217217
self.addWfsLayer_layer_name = None
218218
main_dialog.addVectorLayer.connect(self.slotAddWfsLayer)
219219
QTest.mouseClick(buttonAdd, Qt.LeftButton)
220-
self.assertEqual(self.addWfsLayer_uri, ' restrictToRequestBBOX=\'1\' srsname=\'EPSG:4326\' typename=\'my:typename\' url=\'' + "http://" + expected_endpoint + '\' version=\'auto\' table="" sql=')
220+
self.assertEqual(self.addWfsLayer_uri, ' pagingEnabled=\'true\' restrictToRequestBBOX=\'1\' srsname=\'EPSG:4326\' typename=\'my:typename\' url=\'' + "http://" + expected_endpoint + '\' version=\'auto\' table="" sql=')
221221
self.assertEqual(self.addWfsLayer_layer_name, 'my:typename')
222222

223223
# Click on Build Query
@@ -233,7 +233,7 @@ def test(self):
233233

234234
# Click again but with valid DescribeFeatureType
235235

236-
with open(sanitize(endpoint, '?SERVICE=WFS&REQUEST=DescribeFeatureType&VERSION=2.0.0&TYPENAME=my:typename'), 'wb') as f:
236+
with open(sanitize(endpoint, '?SERVICE=WFS&REQUEST=DescribeFeatureType&VERSION=2.0.0&TYPENAMES=my:typename&TYPENAME=my:typename'), 'wb') as f:
237237
f.write("""
238238
<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">
239239
<xsd:import namespace="http://www.opengis.net/gml/3.2"/>
@@ -290,7 +290,7 @@ def test(self):
290290
self.addWfsLayer_layer_name = None
291291
main_dialog.addVectorLayer.connect(self.slotAddWfsLayer)
292292
QTest.mouseClick(buttonAdd, Qt.LeftButton)
293-
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')
293+
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')
294294
self.assertEqual(self.addWfsLayer_layer_name, 'my:typename')
295295

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

0 commit comments

Comments
 (0)
Please sign in to comment.