From 7eaad506d1d00d9f6cc5ab118fcac2ebeab5567b Mon Sep 17 00:00:00 2001 From: Diederik van der Boor Date: Tue, 10 Dec 2024 14:39:43 +0100 Subject: [PATCH] Hide the erroneous output formats for FME from GetCapabilities This output format doesn't have to be advertised. It only needs to be accepted as valid option. --- docs/compliance.rst | 3 +++ gisserver/operations/base.py | 3 +++ gisserver/operations/wfs20.py | 15 +++++++++++---- .../gisserver/wfs/2.0.0/get_capabilities.xml | 4 ++-- 4 files changed, 19 insertions(+), 6 deletions(-) diff --git a/docs/compliance.rst b/docs/compliance.rst index 64a46e0..23e1bad 100644 --- a/docs/compliance.rst +++ b/docs/compliance.rst @@ -60,6 +60,9 @@ To support these clients, the following logic is also implemented: * The ``TYPENAME`` parameter instead of ``TYPENAMES`` (used by the CITE test suite!). * Using ``A`` and ``D`` as sort direction in ``SORTBY`` / ```` instead of ``ASC`` and ``DESC``. +The FME (Feature Manipulation Engine) software sent ``OUTPUTFORMAT=application/gml+xml; version=3.2`` +to all methods, including ``GetCapabilities`` and ``DescribeFeatureType``. These are also silently accepted. + For CITE test suite compliance, ``urn:ogc:def:query:OGC-WFS::GetFeatureById`` query returns an HTTP 404 for an invalid resource ID format, even though the WFS 2 specification states it should return an ``InvalidParameterValue``. Likewise, the ```` query returns an empty list instead diff --git a/gisserver/operations/base.py b/gisserver/operations/base.py index 9809df4..1b96690 100644 --- a/gisserver/operations/base.py +++ b/gisserver/operations/base.py @@ -134,6 +134,7 @@ def __init__( renderer_class=None, max_page_size=None, title=None, + in_capabilities=True, **extra, ): """ @@ -142,6 +143,7 @@ def __init__( If it's not given, the operation renders it's output using an XML template. :param max_page_size: Used to override the ``max_page_size`` of the renderer_class. :param title: A human-friendly name for an HTML overview page. + :param in_capabilities: Whether this format needs to be advertised in GetCapabilities. :param extra: Any additional key-value pairs for the definition. Could include ``subtype`` as a shorter alias for the MIME-type. """ @@ -150,6 +152,7 @@ def __init__( self.subtype = self.extra.get("subtype") self.renderer_class = renderer_class self.title = title + self.in_capabilities = in_capabilities self._max_page_size = max_page_size def matches(self, value): diff --git a/gisserver/operations/wfs20.py b/gisserver/operations/wfs20.py index 9c52595..06e9af0 100644 --- a/gisserver/operations/wfs20.py +++ b/gisserver/operations/wfs20.py @@ -47,8 +47,14 @@ class GetCapabilities(WFSMethod): """This operation returns map features, and available operations this WFS server supports.""" output_formats = [ - OutputFormat("application/gml+xml", version="3.2", title="GML"), # for FME OutputFormat("text/xml"), + OutputFormat( + # for FME (Feature Manipulation Engine) + "application/gml+xml", + version="3.2", + title="GML", + in_capabilities=False, + ), ] xml_template_name = "get_capabilities.xml" @@ -143,13 +149,14 @@ class DescribeFeatureType(WFSTypeNamesMethod): output_formats = [ OutputFormat("XMLSCHEMA", renderer_class=output.XMLSchemaRenderer), - # At least one version of FME seems to sends a DescribeFeatureType - # request with this output format. Do what mapserver does and just - # send it XML Schema. + # At least one version of FME (Feature Manipulation Engine) seems to + # send a DescribeFeatureType request with this GML as output format. + # Do what mapserver does and just send it XML Schema. OutputFormat( "application/gml+xml", version="3.2", renderer_class=output.XMLSchemaRenderer, + in_capabilities=False, ), # OutputFormat("text/xml", subtype="gml/3.1.1"), ] diff --git a/gisserver/templates/gisserver/wfs/2.0.0/get_capabilities.xml b/gisserver/templates/gisserver/wfs/2.0.0/get_capabilities.xml index fd35975..333afd1 100644 --- a/gisserver/templates/gisserver/wfs/2.0.0/get_capabilities.xml +++ b/gisserver/templates/gisserver/wfs/2.0.0/get_capabilities.xml @@ -97,8 +97,8 @@ {% endif %} {{ feature_type.crs }}{% for crs in feature_type.other_crs %} {{ crs }}{% endfor %} - {% for output in feature_output_formats %} - {{ output }}{% endfor %} + {% for output in feature_output_formats %}{% if output.in_capabilities %} + {{ output }}{% endif %}{% endfor %} {% if BOUNDING_BOX %}{% with bbox=feature_type.get_bounding_box %}{% if bbox %} {{ bbox.lower_corner|join:" " }}