diff --git a/docs/source/configuration.rst b/docs/source/configuration.rst index 02631aee2..cb50aba24 100644 --- a/docs/source/configuration.rst +++ b/docs/source/configuration.rst @@ -250,6 +250,7 @@ default. mimetype: application/json # required: format mimetype options: # optional options to pass to provider (i.e. GDAL creation) option_name: option_value + include_extra_query_parameters: false # include extra query parameters that are not part of the collection properties (default: false) hello-world: # name of process type: process # REQUIRED (collection, process, or stac-collection) diff --git a/docs/source/data-publishing/ogcapi-features.rst b/docs/source/data-publishing/ogcapi-features.rst index 79ad13f31..11f3098dc 100644 --- a/docs/source/data-publishing/ogcapi-features.rst +++ b/docs/source/data-publishing/ogcapi-features.rst @@ -804,6 +804,32 @@ To publish a TinyDB (`see website `_) index, the id_field: identifier time_field: datetimefield +.. _including-extra-query-parameters: + +Including extra query parameters +-------------------------------- + +By default, pygeoapi ignores any extra query parameters. For example, for a given ``.../items`` query, the query key-value pair ``foo1=bar1`` (if ``foo1`` is not a valid property of a given collection) would be ignored by pygeoapi as well as the underlying provider. + +To include/accept extra query parameters, the ``include_extra_query_parameters`` directive can be set in provider configuration: + +.. code-block:: yaml + + providers: + - type: feature + editable: true|false # optional, default is false + name: TinyDB + data: /path/to/file.db + id_field: identifier + time_field: datetimefield + include_extra_query_parameters: true + + +With the above configuration, pygeoapi will pass ``foo1=bar1`` to the underlying provider. If the underlying provider does not have ``foo1`` as a queryable property, then an exception will be returned citing an unknown property. + +Extra query parameters are useful for custom providers who may wish for specific functionality to be triggered by query parameters that are not bound to a given collection's properties. + + Controlling the order of properties ----------------------------------- diff --git a/docs/source/data-publishing/ogcapi-records.rst b/docs/source/data-publishing/ogcapi-records.rst index e06f08035..fda95bdbd 100644 --- a/docs/source/data-publishing/ogcapi-records.rst +++ b/docs/source/data-publishing/ogcapi-records.rst @@ -96,6 +96,11 @@ CSW Record core model is supported as a baseline. title_field: title +Including extra query parameters +-------------------------------- + +See the :ref:`publishing vector section ` for more information on including extra query parameters. + Metadata search examples ------------------------ diff --git a/pygeoapi/api/itemtypes.py b/pygeoapi/api/itemtypes.py index 25d37ef5f..1fbb53921 100644 --- a/pygeoapi/api/itemtypes.py +++ b/pygeoapi/api/itemtypes.py @@ -415,13 +415,16 @@ def get_collection_items( LOGGER.debug('processing property parameters') for k, v in request.params.items(): + include_query_param = False if k not in reserved_fieldnames: - if k in list(p.fields.keys()): - LOGGER.debug(f'Adding property filter {k}={v}') - else: - LOGGER.debug(f'Adding additional property filter {k}={v}') + if k in list(p.fields.keys()) or p.include_extra_query_parameters: + include_query_param = True + if include_query_param: + LOGGER.debug(f'Including query parameter {k}={v}') properties.append((k, v)) + else: + LOGGER.debug(f'Discarding query parameter {k}={v}') LOGGER.debug('processing sort parameter') val = request.params.get('sortby') diff --git a/pygeoapi/formatter/csv_.py b/pygeoapi/formatter/csv_.py index 51a6ded17..d5e856665 100644 --- a/pygeoapi/formatter/csv_.py +++ b/pygeoapi/formatter/csv_.py @@ -82,7 +82,6 @@ def write(self, options: dict = {}, data: dict = None) -> str: # TODO: implement wkt geometry serialization LOGGER.debug('not a point geometry, skipping') - print("JJJ", fields) LOGGER.debug(f'CSV fields: {fields}') try: diff --git a/pygeoapi/provider/base.py b/pygeoapi/provider/base.py index 0d48cd1a3..4fc94302f 100644 --- a/pygeoapi/provider/base.py +++ b/pygeoapi/provider/base.py @@ -74,6 +74,7 @@ def __init__(self, provider_def): self.title_field = provider_def.get('title_field') self.properties = provider_def.get('properties', []) self.file_types = provider_def.get('file_types', []) + self.include_extra_query_parameters = provider_def.get('include_extra_query_parameters', False) # noqa self._fields = {} self.filename = None diff --git a/pygeoapi/schemas/config/pygeoapi-config-0.x.yml b/pygeoapi/schemas/config/pygeoapi-config-0.x.yml index 0dbf7ea49..c1e925c39 100644 --- a/pygeoapi/schemas/config/pygeoapi-config-0.x.yml +++ b/pygeoapi/schemas/config/pygeoapi-config-0.x.yml @@ -573,6 +573,10 @@ properties: year in the Gregorian calendar. example: 2017-03-25 in the Gregorian calendar is epoch 2017.23 + include_extra_query_parameters: + type: boolean + description: whether to include extra query parameters + default: false required: - type - name diff --git a/tests/api/test_itemtypes.py b/tests/api/test_itemtypes.py index 5750448fe..ecd89ba21 100644 --- a/tests/api/test_itemtypes.py +++ b/tests/api/test_itemtypes.py @@ -385,6 +385,21 @@ def test_get_collection_items(config, api_): assert code == HTTPStatus.BAD_REQUEST +def test_get_collection_items_include_extra_query_parameters(config, api_): + req = mock_api_request() + rsp_headers, code, response = get_collection_items(api_, req, 'obs') + + assert code == HTTPStatus.OK + response = json.loads(response) + assert response['numberMatched'] == 5 + + api_.config['resources']['obs']['providers'][0]['include_extra_query_parameters'] = True # noqa + req = mock_api_request({'foo': 'bar'}) + rsp_headers, code, response = get_collection_items(api_, req, 'obs') + + assert code == HTTPStatus.BAD_REQUEST + + def test_collection_items_gzip_csv(config, api_, openapi): # Add gzip to server config['server']['gzip'] = True diff --git a/tests/cite/cite.config.yml b/tests/cite/cite.config.yml index 104fb09b5..45e77e914 100644 --- a/tests/cite/cite.config.yml +++ b/tests/cite/cite.config.yml @@ -10,7 +10,7 @@ server: pretty_print: true limits: default_items: 10 - max_items: 10 + max_items: 50 # templates: /path/to/templates map: url: https://tile.openstreetmap.org/{z}/{x}/{y}.png