Skip to content

Commit

Permalink
qgswfsgetfeature: Properly handle ogc urns in post requests
Browse files Browse the repository at this point in the history
There are 2 different parameters to check to define the output crs:
- the request parameter (`SRSNAME` from the request)
- the query crs parameter

For a `GET` request, if `SRSNAME` is set, both parameters are set and
equal.
For a `POST` request, only the query parameter is set if defined.

In `writeGetFeature()`, the `outputCrs` correctly takes into account
the query parameter. However, this is not the case for the output srs
name (`srsName`) which only takes into account the query CRS as an
auth id.
Therefore, the output srsName will always be defined as an authid
even if the parameter is an ogc urn.

This issue is fixed by first computing the output srs
name (`outputSrsName`) by taking
into account the query and the query parameters. Then, this name is
used to compute `outputCrs`.
  • Loading branch information
ptitjano authored and troopa81 committed Oct 4, 2024
1 parent 6cdad16 commit a95d791
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 17 deletions.
35 changes: 21 additions & 14 deletions src/server/services/wfs/qgswfsgetfeature.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -414,11 +414,28 @@ namespace QgsWfs
geometryName = QLatin1String( "NONE" );
}
// outputCrs
QgsCoordinateReferenceSystem outputCrs = vlayer->crs();
// if the crs is defined in the parameters, use it
// otherwise fallback:
// - geojson uses 'EPSG:4326' by default
// - other formats use the default CRS (the layer's CRS)
const QString requestSrsName = request.serverParameters().value( QStringLiteral( "SRSNAME" ) );
QString outputSrsName;
if ( !query.srsName.isEmpty() )
{
outputCrs = QgsCoordinateReferenceSystem::fromOgcWmsCrs( query.srsName );
outputSrsName = query.srsName;
}
else if ( !requestSrsName.isEmpty() )
{
outputSrsName = requestSrsName;
}
else
{
// fallback to a default value
// geojson uses 'EPSG:4326' by default
outputSrsName = ( aRequest.outputFormat == QgsWfsParameters::Format::GeoJSON ) ? QStringLiteral( "EPSG:4326" ) : vlayer->crs().authid();
}

const QgsCoordinateReferenceSystem outputCrs = QgsCoordinateReferenceSystem::fromOgcWmsCrs( outputSrsName );

bool forceGeomToMulti = QgsWkbTypes::isMultiType( vlayer->wkbType() );

Expand Down Expand Up @@ -465,19 +482,9 @@ namespace QgsWfs
// It needs to be an EPSG urn, e.g. urn:ogc:def:crs:EPSG::4326
// This follows geoserver convention
// See: https://docs.geoserver.org/stable/en/user/services/wfs/axis_order.html
// if the crs is defined in the parameters, use it
// otherwise:
// - geojson uses 'EPSG:4326' by default
// - other formats use the default CRS (DefaultSRS, which is the layer's CRS)
const QString requestSrsName = request.serverParameters().value( QStringLiteral( "SRSNAME" ) );
const QString srsName
{
!requestSrsName.isEmpty() ? requestSrsName :
( aRequest.outputFormat == QgsWfsParameters::Format::GeoJSON ? QStringLiteral( "EPSG:4326" ) : outputCrs.authid() )
};
const bool invertAxis { mWfsParameters.versionAsNumber() >= QgsProjectVersion( 1, 1, 0 ) &&
outputCrs.hasAxisInverted() &&
! srsName.startsWith( QLatin1String( "EPSG:" ) ) };
! outputSrsName.startsWith( QLatin1String( "EPSG:" ) ) };

const createFeatureParams cfp = { layerPrecision,
layerCrs,
Expand All @@ -487,7 +494,7 @@ namespace QgsWfs
geometryName,
outputCrs,
forceGeomToMulti,
srsName,
outputSrsName,
invertAxis
};
while ( fit.nextFeature( feature ) && ( aRequest.maxFeatures == -1 || sentFeatures < aRequest.maxFeatures ) )
Expand Down
10 changes: 7 additions & 3 deletions tests/src/python/test_qgsserver_wfs.py
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,7 @@ def test_getfeature_post(self):

srsTemplate = """<?xml version="" encoding="UTF-8"?>
<wfs:GetFeature service="WFS" version="{}" {} xmlns:wfs="http://www.opengis.net/wfs" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.1.0/wfs.xsd">
<wfs:Query typeName="testlayer" srsName="EPSG:3857" xmlns:feature="http://www.qgis.org/gml">
<wfs:Query typeName="testlayer" {} xmlns:feature="http://www.qgis.org/gml">
<ogc:Filter xmlns:ogc="http://www.opengis.net/ogc">
<ogc:BBOX>
<ogc:PropertyName>geometry</ogc:PropertyName>
Expand All @@ -327,8 +327,12 @@ def test_getfeature_post(self):
</wfs:Query>
</wfs:GetFeature>
"""
tests.append(('srsname_post_1_0_0', srsTemplate.format('1.0.0', '')))
tests.append(('srsname_post_1_1_0', srsTemplate.format('1.1.0', '')))
tests.append(('srsname_post_1_0_0', srsTemplate.format(
'1.0.0', '', 'srsName="EPSG:3857"')))
tests.append(('srsname_post_1_1_0', srsTemplate.format(
'1.1.0', '', 'srsName="EPSG:3857"')))
tests.append(('srsname_post_1_1_0_urn', srsTemplate.format(
'1.1.0', '', 'srsName="urn:ogc:def:crs:EPSG::3857"')))

# Issue https://github.com/qgis/QGIS/issues/36398
# Check get feature within polygon having srsName=EPSG:4326 (same as the project/layer)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
Content-Type: text/xml; subtype=gml/3.1.1; charset=utf-8

<wfs:FeatureCollection xmlns:wfs="http://www.opengis.net/wfs" xmlns:ogc="http://www.opengis.net/ogc" xmlns:gml="http://www.opengis.net/gml" xmlns:ows="http://www.opengis.net/ows" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:qgs="http://www.qgis.org/gml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.1.0/wfs.xsd http://www.qgis.org/gml ?">
<gml:boundedBy>
<gml:Envelope srsName="EPSG:4326">
<gml:lowerCorner>8 44</gml:lowerCorner>
<gml:upperCorner>9 45</gml:upperCorner>
</gml:Envelope>
</gml:boundedBy>
<gml:featureMember>
<qgs:testlayer gml:id="testlayer.0">
<gml:boundedBy>
<gml:Envelope srsName="urn:ogc:def:crs:EPSG::3857">
<gml:lowerCorner>913209.03579284 5606025.23730414</gml:lowerCorner>
<gml:upperCorner>913209.03579284 5606025.23730414</gml:upperCorner>
</gml:Envelope>
</gml:boundedBy>
<qgs:geometry>
<Point xmlns="http://www.opengis.net/gml" srsName="urn:ogc:def:crs:EPSG::3857">
<pos xmlns="http://www.opengis.net/gml" srsDimension="2">913209.03579284 5606025.23730414</pos>
</Point>
</qgs:geometry>
<qgs:id>1</qgs:id>
<qgs:name>one</qgs:name>
<qgs:utf8nameè>one èé</qgs:utf8nameè>
</qgs:testlayer>
</gml:featureMember>
<gml:featureMember>
<qgs:testlayer gml:id="testlayer.1">
<gml:boundedBy>
<gml:Envelope srsName="urn:ogc:def:crs:EPSG::3857">
<gml:lowerCorner>913214.67407005 5606017.87425818</gml:lowerCorner>
<gml:upperCorner>913214.67407005 5606017.87425818</gml:upperCorner>
</gml:Envelope>
</gml:boundedBy>
<qgs:geometry>
<Point xmlns="http://www.opengis.net/gml" srsName="urn:ogc:def:crs:EPSG::3857">
<pos xmlns="http://www.opengis.net/gml" srsDimension="2">913214.67407005 5606017.87425818</pos>
</Point>
</qgs:geometry>
<qgs:id>2</qgs:id>
<qgs:name>two</qgs:name>
<qgs:utf8nameè>two àò</qgs:utf8nameè>
</qgs:testlayer>
</gml:featureMember>
<gml:featureMember>
<qgs:testlayer gml:id="testlayer.2">
<gml:boundedBy>
<gml:Envelope srsName="urn:ogc:def:crs:EPSG::3857">
<gml:lowerCorner>913204.91280263 5606011.45647302</gml:lowerCorner>
<gml:upperCorner>913204.91280263 5606011.45647302</gml:upperCorner>
</gml:Envelope>
</gml:boundedBy>
<qgs:geometry>
<Point xmlns="http://www.opengis.net/gml" srsName="urn:ogc:def:crs:EPSG::3857">
<pos xmlns="http://www.opengis.net/gml" srsDimension="2">913204.91280263 5606011.45647302</pos>
</Point>
</qgs:geometry>
<qgs:id>3</qgs:id>
<qgs:name>three</qgs:name>
<qgs:utf8nameè>three èé↓</qgs:utf8nameè>
</qgs:testlayer>
</gml:featureMember>
</wfs:FeatureCollection>

0 comments on commit a95d791

Please sign in to comment.