Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[WFS provider] Re-inject custom query parameters in DCP HTTP URLs (fixes
 #31026)

Backport of #31765

Since f1b5987, we honour DCP HTTP endpoints
exposed in GetCapabilities.
But some (all?) servers fail to add in those endpoints the custom query parameters
the user might have injected in the GetCapabilities URL.
So re-add them manually.
  • Loading branch information
rouault authored and nyalldawson committed Sep 20, 2019
1 parent 5c8dd17 commit 6f17698
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 15 deletions.
49 changes: 40 additions & 9 deletions src/providers/wfs/qgswfsdatasourceuri.cpp
Expand Up @@ -19,6 +19,8 @@
#include "qgswfsdatasourceuri.h"
#include "qgsmessagelog.h"

#include <QUrlQuery>

QgsWFSDataSourceURI::QgsWFSDataSourceURI( const QString &uri )
: mURI( uri )
{
Expand Down Expand Up @@ -118,7 +120,10 @@ QgsWFSDataSourceURI::QgsWFSDataSourceURI( const QString &uri )
break;
}
else if ( lowerName == QLatin1String( "service" ) ||
lowerName == QLatin1String( "request" ) )
lowerName == QLatin1String( "request" ) ||
lowerName == QLatin1String( "typename" ) ||
lowerName == QLatin1String( "typenames" ) ||
lowerName == QLatin1String( "version" ) )
{
url.removeQueryItem( item.first );
somethingChanged = true;
Expand Down Expand Up @@ -176,23 +181,49 @@ QUrl QgsWFSDataSourceURI::baseURL( bool bIncludeServiceWFS ) const

QUrl QgsWFSDataSourceURI::requestUrl( const QString &request, const Method &method ) const
{
QString endpoint;
QUrl url;
QUrlQuery urlQuery;
switch ( method )
{
case Post:
endpoint = mPostEndpoints.contains( request ) ?
mPostEndpoints[ request ] : mURI.param( QgsWFSConstants::URI_PARAM_URL );
url = QUrl( mPostEndpoints.contains( request ) ?
mPostEndpoints[ request ] : mURI.param( QgsWFSConstants::URI_PARAM_URL ) );
urlQuery = QUrlQuery( url );
break;
default:
case Get:
endpoint = mGetEndpoints.contains( request ) ?
mGetEndpoints[ request ] : mURI.param( QgsWFSConstants::URI_PARAM_URL );
{
const auto defaultUrl( QUrl( mURI.param( QgsWFSConstants::URI_PARAM_URL ) ) );
if ( mGetEndpoints.contains( request ) )
{
// If the input URL has query parameters, and those are not found in the
// DCP endpoint, then re-inject them.
// I'm not completely sure this is the job of the client to do that.
// One could argue that the server should expose them in the DCP endpoint.
url = QUrl( mGetEndpoints[ request ] );
urlQuery = QUrlQuery( url );
const QUrlQuery defaultUrlQuery( defaultUrl );
const auto itemsDefaultUrl( defaultUrlQuery.queryItems() );
for ( const auto &item : itemsDefaultUrl )
{
if ( !urlQuery.hasQueryItem( item.first ) )
{
urlQuery.addQueryItem( item.first, item.second );
}
}
}
else
{
url = defaultUrl;
urlQuery = QUrlQuery( url );
}
break;
}
}
QUrl url( endpoint );
url.addQueryItem( QStringLiteral( "SERVICE" ), QStringLiteral( "WFS" ) );
urlQuery.addQueryItem( QStringLiteral( "SERVICE" ), QStringLiteral( "WFS" ) );
if ( method == Method::Get && ! request.isEmpty() )
url.addQueryItem( QStringLiteral( "REQUEST" ), request );
urlQuery.addQueryItem( QStringLiteral( "REQUEST" ), request );
url.setQuery( urlQuery );
return url;
}

Expand Down
12 changes: 6 additions & 6 deletions tests/src/python/test_provider_wfs.py
Expand Up @@ -3039,7 +3039,7 @@ def testWFS10DCP(self):
endpoint = self.__class__.basetestpath + '/fake_qgis_http_endpoint_WFS_DCP_1.0'
endpoint_alternate = self.__class__.basetestpath + '/fake_qgis_http_endpoint_WFS_DCP_1.0_alternate'

with open(sanitize(endpoint, '?SERVICE=WFS?REQUEST=GetCapabilities?VERSION=1.0.0'), 'wb') as f:
with open(sanitize(endpoint, '?FOO=BAR&SERVICE=WFS&REQUEST=GetCapabilities&VERSION=1.0.0'), 'wb') as f:
f.write("""
<WFS_Capabilities version="1.0.0" xmlns="http://www.opengis.net/wfs" xmlns:ogc="http://www.opengis.net/ogc">
<FeatureTypeList>
Expand Down Expand Up @@ -3071,7 +3071,7 @@ def testWFS10DCP(self):
</Operation>
</OperationsMetadata></WFS_Capabilities>""".format(endpoint_alternate).encode('UTF-8'))

with open(sanitize(endpoint_alternate, '?SERVICE=WFS&REQUEST=DescribeFeatureType&VERSION=1.0.0&TYPENAME=my:typename'), 'wb') as f:
with open(sanitize(endpoint_alternate, '?FOO=BAR&SERVICE=WFS&REQUEST=DescribeFeatureType&VERSION=1.0.0&TYPENAME=my:typename'), 'wb') as f:
f.write("""
<xsd:schema xmlns:my="http://my" xmlns:gml="http://www.opengis.net/gml" xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="http://my">
<xsd:import namespace="http://www.opengis.net/gml"/>
Expand All @@ -3094,7 +3094,7 @@ def testWFS10DCP(self):
</xsd:schema>
""".encode('UTF-8'))

vl = QgsVectorLayer("url='http://" + endpoint + "' typename='my:typename' version='1.0.0'", 'test', 'WFS')
vl = QgsVectorLayer("url='http://" + endpoint + "?FOO=BAR&SERVICE=WFS&REQUEST=GetCapabilities&VERSION=1.1.0" + "' typename='my:typename' version='1.0.0'", 'test', 'WFS')
self.assertTrue(vl.isValid())
self.assertEqual(vl.wkbType(), QgsWkbTypes.Point)
self.assertEqual(len(vl.fields()), 5)
Expand All @@ -3103,7 +3103,7 @@ def testWFS10DCP(self):
vl_extent = QgsGeometry.fromRect(vl.extent())
assert QgsGeometry.compare(vl_extent.asPolygon()[0], reference.asPolygon()[0], 0.00001), 'Expected {}, got {}'.format(reference.asWkt(), vl_extent.asWkt())

with open(sanitize(endpoint_alternate, '?SERVICE=WFS&REQUEST=GetFeature&VERSION=1.0.0&TYPENAME=my:typename&SRSNAME=EPSG:32631'), 'wb') as f:
with open(sanitize(endpoint_alternate, '?FOO=BAR&SERVICE=WFS&REQUEST=GetFeature&VERSION=1.0.0&TYPENAME=my:typename&SRSNAME=EPSG:32631'), 'wb') as f:
f.write("""
<wfs:FeatureCollection
xmlns:wfs="http://www.opengis.net/wfs"
Expand Down Expand Up @@ -3158,7 +3158,7 @@ def testWFS10DCP(self):
self.assertFalse(vl.dataProvider().deleteFeatures([0]))

# Test with restrictToRequestBBOX=1
with open(sanitize(endpoint_alternate, '?SERVICE=WFS&REQUEST=GetFeature&VERSION=1.0.0&TYPENAME=my:typename&SRSNAME=EPSG:32631&BBOX=400000,5400000,450000,5500000'), 'wb') as f:
with open(sanitize(endpoint_alternate, '?FOO=BAR&SERVICE=WFS&REQUEST=GetFeature&VERSION=1.0.0&TYPENAME=my:typename&SRSNAME=EPSG:32631&BBOX=400000,5400000,450000,5500000'), 'wb') as f:
f.write("""
<wfs:FeatureCollection
xmlns:wfs="http://www.opengis.net/wfs"
Expand All @@ -3175,7 +3175,7 @@ def testWFS10DCP(self):
</gml:featureMember>
</wfs:FeatureCollection>""".encode('UTF-8'))

vl = QgsVectorLayer("url='http://" + endpoint + "' typename='my:typename' version='1.0.0' restrictToRequestBBOX=1", 'test', 'WFS')
vl = QgsVectorLayer("url='http://" + endpoint + "?FOO=BAR" + "' typename='my:typename' version='1.0.0' restrictToRequestBBOX=1", 'test', 'WFS')

extent = QgsRectangle(400000.0, 5400000.0, 450000.0, 5500000.0)
request = QgsFeatureRequest().setFilterRect(extent)
Expand Down

0 comments on commit 6f17698

Please sign in to comment.