diff --git a/.github/workflows/containers.yml b/.github/workflows/containers.yml index 04897a440..f04834da5 100644 --- a/.github/workflows/containers.yml +++ b/.github/workflows/containers.yml @@ -25,7 +25,7 @@ jobs: contents: read steps: - name: Check out the repo - uses: actions/checkout@v3 + uses: actions/checkout@master - name: Set up QEMU uses: docker/setup-qemu-action@v2.1.0 diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 0da62d013..9de9ab025 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -23,8 +23,8 @@ jobs: include: - python-version: '3.10' steps: - - uses: actions/checkout@v2 - - uses: actions/setup-python@v2 + - uses: actions/checkout@master + - uses: actions/setup-python@v5 name: Setup Python ${{ matrix.python-version }} with: python-version: ${{ matrix.python-version }} diff --git a/.github/workflows/flake8.yml b/.github/workflows/flake8.yml index 284b93655..b57ba36c2 100644 --- a/.github/workflows/flake8.yml +++ b/.github/workflows/flake8.yml @@ -7,8 +7,8 @@ jobs: flake8_py3: runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v3 - - uses: actions/setup-python@v3 + - uses: actions/checkout@master + - uses: actions/setup-python@v5 name: setup Python with: python-version: '3.10' diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index c17169819..49421bc07 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -37,8 +37,8 @@ jobs: - name: Chown user run: | sudo chown -R $USER:$USER $GITHUB_WORKSPACE - - uses: actions/checkout@v2 - - uses: actions/setup-python@v2 + - uses: actions/checkout@master + - uses: actions/setup-python@v5 name: Setup Python ${{ matrix.python-version }} with: python-version: ${{ matrix.python-version }} @@ -69,13 +69,13 @@ jobs: security-disabled: true port: 9209 - name: Install and run MongoDB - uses: supercharge/mongodb-github-action@1.5.0 + uses: supercharge/mongodb-github-action@1.12.0 with: mongodb-version: 4.4 - name: Install and run SensorThingsAPI uses: cgs-earth/sensorthings-action@v0.1.0 - name: Install sqlite and gpkg dependencies - uses: awalsh128/cache-apt-pkgs-action@latest + uses: awalsh128/cache-apt-pkgs-action@v1.4.3 with: packages: libsqlite3-mod-spatialite version: 4.3.0a-6build1 @@ -83,7 +83,7 @@ jobs: run: sudo add-apt-repository ppa:ubuntugis/ubuntugis-unstable && sudo apt update shell: bash - name: Install GDAL with Python bindings - uses: awalsh128/cache-apt-pkgs-action@latest + uses: awalsh128/cache-apt-pkgs-action@v1.4.3 with: packages: gdal-bin libgdal-dev version: 3.8.4 diff --git a/docker/default.config.yml b/docker/default.config.yml index 29174bbf5..d75298f9f 100644 --- a/docker/default.config.yml +++ b/docker/default.config.yml @@ -46,7 +46,9 @@ server: cors: true pretty_print: true admin: ${PYGEOAPI_SERVER_ADMIN:-false} - limit: 10 + limits: + default_items: 10 + max_items: 50 # templates: /path/to/templates map: url: https://tile.openstreetmap.org/{z}/{x}/{y}.png diff --git a/docs/source/configuration.rst b/docs/source/configuration.rst index 9dff49a17..8123a00bc 100644 --- a/docs/source/configuration.rst +++ b/docs/source/configuration.rst @@ -49,7 +49,15 @@ For more information related to API design rules (the ``api_rules`` property in gzip: false # default server config to gzip/compress responses to requests with gzip in the Accept-Encoding header cors: true # boolean on whether server should support CORS pretty_print: true # whether JSON responses should be pretty-printed - limit: 10 # server limit on number of items to return + + limits: # server limits on number of items to return. This property can also be defined at the resource level to override global server settings + default_items: 50 + max_items: 1000 + max_distance_x: 25 + max_distance_y: 25 + max_distance_units: m + on_exceed: throttle # throttle or error (default=throttle) + admin: false # whether to enable the Admin API # optional configuration to specify a different set of templates for HTML pages. Recommend using absolute paths. Omit this to use the default provided templates @@ -254,6 +262,41 @@ default. .. seealso:: :ref:`plugins` for more information on plugins +Using environment variables +--------------------------- + +pygeoapi configuration supports using system environment variables, which can be helpful +for deploying into `12 factor `_ environments for example. + +Below is an example of how to integrate system environment variables in pygeoapi. + +.. code-block:: yaml + + server: + bind: + host: ${MY_HOST} + port: ${MY_PORT} + +Multiple environment variables are supported as follows: + +.. code-block:: yaml + + data: ${MY_HOST}:${MY_PORT} + +It is also possible to define a default value for a variable in case it does not exist in +the environment using a syntax like: ``value: ${ENV_VAR:-the default}`` + +.. code-block:: yaml + + server: + bind: + host: ${MY_HOST:-localhost} + port: ${MY_PORT:-5000} + metadata: + identification: + title: + en: This is pygeoapi host ${MY_HOST} and port ${MY_PORT:-5000}, nice to meet you! + Adding links to collections --------------------------- @@ -389,53 +432,6 @@ If omitted, no header will be added. Common names for this header are ``API-Vers Note that pygeoapi already adds a ``X-Powered-By`` header by default that includes the software version number. -Validating the configuration ----------------------------- - -To ensure your configuration is valid, pygeoapi provides a validation -utility that can be run as follows: - -.. code-block:: bash - - pygeoapi config validate -c /path/to/my-pygeoapi-config.yml - - -Using environment variables ---------------------------- - -pygeoapi configuration supports using system environment variables, which can be helpful -for deploying into `12 factor `_ environments for example. - -Below is an example of how to integrate system environment variables in pygeoapi. - -.. code-block:: yaml - - server: - bind: - host: ${MY_HOST} - port: ${MY_PORT} - -Multiple environment variables are supported as follows: - -.. code-block:: yaml - - data: ${MY_HOST}:${MY_PORT} - -It is also possible to define a default value for a variable in case it does not exist in -the environment using a syntax like: ``value: ${ENV_VAR:-the default}`` - -.. code-block:: yaml - - server: - bind: - host: ${MY_HOST:-localhost} - port: ${MY_PORT:-5000} - metadata: - identification: - title: - en: This is pygeoapi host ${MY_HOST} and port ${MY_PORT:-5000}, nice to meet you! - - Hierarchical collections ------------------------ @@ -507,6 +503,36 @@ Examples: curl https://example.org/collections/lakes/items # only the name attribute is returned in properties curl https://example.org/collections/lakes/items/{item_id} # only the name attribute is returned in properties +Limiting data responses +----------------------- + +pygeoapi defines a ``limits`` configuration parameter that will allow a user to define default and maximum limits for multiple data types. This parameter is defined at the server level (``server.limits``) with the ability to override at resource level (``resources[*].limits``). An example of this setting is shown below: + +.. code-block:: yaml + + limits: + default_items: 10 # applies to vector data + max_items: 500 # applies to vector data + max_distance_x: 123 # applies to all datasets + max_distance_y: 456 # applies to all datasets + max_distance_units: m # as per UCUM https://ucum.org/ucum#section-Tables-of-Terminal-Symbols + on_exceed: error # one of error, throttle + +The ``limits`` setting is applied as follows: + +- can be defined at both the server and resources levels, with resource limits overriding server wide limits settings +- ``on_exceed`` can be set to ``error`` or ``throttle`` (default). If a client specified limit exceeds those set by the server: + - when set to ``error``, an exception is returned + - when set to ``throttle`` the maximum data allowed by the collection/server/provider is returned + +Vector data (features, records) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- when a limit not specified by the client, ``limits.default_items`` can be used to set the result set size +- when a limit is specified by the client, the minimum of the ``limit`` parameter and ``limits.max_items`` is calculated to set the result set size + +Raster data (coverages, environmental data retrieval) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- when a bbox or spatial subset is specified by the client, ``limits.max_distance_x``, ``limits.max_distance_y`` and ``limits.max_distance_units`` are used to determine whether a request has asked for more data than the collection is configured to provide and respond accordingly (via ``on_exceed``) Linked Data ----------- @@ -638,6 +664,17 @@ deployment flexibility, the path can be specified with string interpolation of e The template ``tests/data/base.jsonld`` renders the unmodified JSON-LD. For more information on the capacities of Jinja2 templates, see :ref:`html-templating`. +Validating the configuration +---------------------------- + +To ensure your configuration is valid, pygeoapi provides a validation +utility that can be run as follows: + +.. code-block:: bash + + pygeoapi config validate -c /path/to/my-pygeoapi-config.yml + + Summary ------- diff --git a/pygeoapi-config.yml b/pygeoapi-config.yml index 1ba1c618f..b260c76d2 100644 --- a/pygeoapi-config.yml +++ b/pygeoapi-config.yml @@ -2,7 +2,7 @@ # # Authors: Tom Kralidis # -# Copyright (c) 2020 Tom Kralidis +# Copyright (c) 2025 Tom Kralidis # # Permission is hereby granted, free of charge, to any person # obtaining a copy of this software and associated documentation @@ -41,7 +41,9 @@ server: - fr-CA # cors: true pretty_print: true - limit: 10 + limits: + default_items: 20 + max_items: 50 # templates: # path: /path/to/Jinja2/templates # static: /path/to/static/folder # css/js/img diff --git a/pygeoapi/api/__init__.py b/pygeoapi/api/__init__.py index 5b0a59c67..44f01f540 100644 --- a/pygeoapi/api/__init__.py +++ b/pygeoapi/api/__init__.py @@ -40,7 +40,7 @@ Returns content from plugins and sets responses. """ -from collections import OrderedDict +from collections import ChainMap, OrderedDict from copy import deepcopy from datetime import datetime from functools import partial @@ -1623,3 +1623,43 @@ def validate_subset(value: str) -> dict: subsets[subset_name] = list(map(get_typed_value, values)) return subsets + + +def evaluate_limit(requested: Union[None, int], server_limits: dict, + collection_limits: dict) -> int: + """ + Helper function to evaluate limit parameter + + :param requested: the limit requested by the client + :param server_limits: `dict` of server limits + :param collection_limits: `dict` of collection limits + + :returns: `int` of evaluated limit + """ + + effective_limits = ChainMap(collection_limits, server_limits) + + default = effective_limits.get('default_items', 10) + max_ = effective_limits.get('max_items', 10) + on_exceed = effective_limits.get('on_exceed', 'throttle') + + LOGGER.debug(f'Requested limit: {requested}') + LOGGER.debug(f'Default limit: {default}') + LOGGER.debug(f'Maximum limit: {max_}') + LOGGER.debug(f'On exceed: {on_exceed}') + + if requested is None: + LOGGER.debug('no limit requested; returning default') + return default + + requested2 = get_typed_value(requested) + if not isinstance(requested2, int): + raise ValueError('limit value should be an integer') + + if requested2 <= 0: + raise ValueError('limit value should be strictly positive') + elif requested2 > max_ and on_exceed == 'error': + raise RuntimeError('Limit exceeded; throwing errror') + else: + LOGGER.debug('limit requested') + return min(requested2, max_) diff --git a/pygeoapi/api/environmental_data_retrieval.py b/pygeoapi/api/environmental_data_retrieval.py index e6f1dcf5b..6977b9f4e 100644 --- a/pygeoapi/api/environmental_data_retrieval.py +++ b/pygeoapi/api/environmental_data_retrieval.py @@ -47,6 +47,7 @@ from shapely.wkt import loads as shapely_loads from pygeoapi import l10n +from pygeoapi.api import evaluate_limit from pygeoapi.plugin import load_plugin, PLUGINS from pygeoapi.provider.base import ( ProviderGenericError, ProviderItemNotFoundError) @@ -342,6 +343,21 @@ def get_collection_edr_query(api: API, request: APIRequest, HTTPStatus.BAD_REQUEST, headers, request.format, 'InvalidParameterValue', msg) + LOGGER.debug('Processing limit parameter') + if api.config['server'].get('limit') is not None: + msg = ('server.limit is no longer supported! ' + 'Please use limits at the server or collection ' + 'level (RFC5)') + LOGGER.warning(msg) + try: + limit = evaluate_limit(request.params.get('limit'), + api.config['server'].get('limits', {}), + collections[dataset].get('limits', {})) + except ValueError as err: + return api.get_exception( + HTTPStatus.BAD_REQUEST, headers, request.format, + 'InvalidParameterValue', str(err)) + query_args = dict( query_type=query_type, instance=instance, @@ -353,8 +369,8 @@ def get_collection_edr_query(api: API, request: APIRequest, bbox=bbox, within=within, within_units=within_units, - limit=int(api.config['server']['limit']), - location_id=location_id, + limit=limit, + location_id=location_id ) try: diff --git a/pygeoapi/api/itemtypes.py b/pygeoapi/api/itemtypes.py index c001a051b..e6606c9d3 100644 --- a/pygeoapi/api/itemtypes.py +++ b/pygeoapi/api/itemtypes.py @@ -48,6 +48,7 @@ from pyproj.exceptions import CRSError from pygeoapi import l10n +from pygeoapi.api import evaluate_limit from pygeoapi.formatter.base import FormatterSerializationError from pygeoapi.linked_data import geojson2jsonld from pygeoapi.plugin import load_plugin, PLUGINS @@ -239,33 +240,29 @@ def get_collection_items( return api.get_exception( HTTPStatus.BAD_REQUEST, headers, request.format, 'InvalidParameterValue', msg) - except TypeError as err: - LOGGER.warning(err) - offset = 0 except ValueError: msg = 'offset value should be an integer' return api.get_exception( HTTPStatus.BAD_REQUEST, headers, request.format, 'InvalidParameterValue', msg) + except TypeError as err: + LOGGER.warning(err) + offset = 0 LOGGER.debug('Processing limit parameter') + if api.config['server'].get('limit') is not None: + msg = ('server.limit is no longer supported! ' + 'Please use limits at the server or collection ' + 'level (RFC5)') + LOGGER.warning(msg) try: - limit = int(request.params.get('limit')) - # TODO: We should do more validation, against the min and max - # allowed by the server configuration - if limit <= 0: - msg = 'limit value should be strictly positive' - return api.get_exception( - HTTPStatus.BAD_REQUEST, headers, request.format, - 'InvalidParameterValue', msg) - except TypeError as err: - LOGGER.warning(err) - limit = int(api.config['server']['limit']) - except ValueError: - msg = 'limit value should be an integer' + limit = evaluate_limit(request.params.get('limit'), + api.config['server'].get('limits', {}), + collections[dataset].get('limits', {})) + except ValueError as err: return api.get_exception( HTTPStatus.BAD_REQUEST, headers, request.format, - 'InvalidParameterValue', msg) + 'InvalidParameterValue', str(err)) resulttype = request.params.get('resulttype') or 'results' diff --git a/pygeoapi/api/processes.py b/pygeoapi/api/processes.py index 470d4b705..298fc5918 100644 --- a/pygeoapi/api/processes.py +++ b/pygeoapi/api/processes.py @@ -49,6 +49,7 @@ import urllib.parse from pygeoapi import l10n +from pygeoapi.api import evaluate_limit from pygeoapi.util import ( json_serial, render_j2_template, JobStatus, RequestedProcessExecutionMode, to_json, DATETIME_FORMAT) @@ -100,24 +101,20 @@ def describe_processes(api: API, request: APIRequest, relevant_processes = [process] else: LOGGER.debug('Processing limit parameter') + if api.config['server'].get('limit') is not None: + msg = ('server.limit is no longer supported! ' + 'Please use limits at the server or collection ' + 'level (RFC5)') + LOGGER.warning(msg) try: - limit = int(request.params.get('limit')) - - if limit <= 0: - msg = 'limit value should be strictly positive' - return api.get_exception( - HTTPStatus.BAD_REQUEST, headers, request.format, - 'InvalidParameterValue', msg) - + limit = evaluate_limit(request.params.get('limit'), + api.config['server'].get('limits', {}), + {}) relevant_processes = list(api.manager.processes)[:limit] - except TypeError: - LOGGER.debug('returning all processes') - relevant_processes = api.manager.processes.keys() - except ValueError: - msg = 'limit value should be an integer' + except ValueError as err: return api.get_exception( HTTPStatus.BAD_REQUEST, headers, request.format, - 'InvalidParameterValue', msg) + 'InvalidParameterValue', str(err)) for key in relevant_processes: p = api.manager.get_processor(key) @@ -244,21 +241,13 @@ def get_jobs(api: API, request: APIRequest, **api.api_headers) LOGGER.debug('Processing limit parameter') try: - limit = int(request.params.get('limit')) - - if limit <= 0: - msg = 'limit value should be strictly positive' - return api.get_exception( - HTTPStatus.BAD_REQUEST, headers, request.format, - 'InvalidParameterValue', msg) - except TypeError: - limit = int(api.config['server']['limit']) - LOGGER.debug('returning all jobs') - except ValueError: - msg = 'limit value should be an integer' + limit = evaluate_limit(request.params.get('limit'), + api.config['server'].get('limits', {}), + {}) + except ValueError as err: return api.get_exception( HTTPStatus.BAD_REQUEST, headers, request.format, - 'InvalidParameterValue', msg) + 'InvalidParameterValue', str(err)) LOGGER.debug('Processing offset parameter') try: diff --git a/pygeoapi/schemas/config/pygeoapi-config-0.x.yml b/pygeoapi/schemas/config/pygeoapi-config-0.x.yml index ecc146c8c..dc41a250e 100644 --- a/pygeoapi/schemas/config/pygeoapi-config-0.x.yml +++ b/pygeoapi/schemas/config/pygeoapi-config-0.x.yml @@ -60,8 +60,38 @@ properties: default: false limit: type: integer - description: server limit on number of items to return default: 10 + description: "limit of items to return. DEPRECATED: use limits instead" + limits: &x-limits + type: object + description: server level data limiting + properties: + max_items: + type: integer + description: maximum limit of items to return for item type providers + minimum: 1 + default: 10 + default_items: + type: integer + description: default limit of items to return for item type providers + minimum: 1 + default: 10 + max_distance_x: + type: number + description: maximum distance in x for all data providers + max_distance_y: + type: number + description: maximum distance in y for all data providers + max_distance_units: + type: string + description: maximum distance units as per UCUM https://ucum.org/ucum#section-Tables-of-Terminal-Symbols + on_exceed: + type: string + description: how to handle limit exceeding + default: throttle + enum: + - error + - throttle templates: type: object description: optional configuration to specify a different set of templates for HTML pages. Recommend using absolute paths. Omit this to use the default provided templates @@ -417,6 +447,9 @@ properties: default: 'http://www.opengis.net/def/uom/ISO-8601/0/Gregorian' required: - spatial + limits: + <<: *x-limits + description: collection level data limiting providers: type: array description: required connection information diff --git a/tests/api/test_api.py b/tests/api/test_api.py index 09dd8e6fa..90492b613 100644 --- a/tests/api/test_api.py +++ b/tests/api/test_api.py @@ -40,7 +40,7 @@ from pygeoapi.api import ( API, APIRequest, FORMAT_TYPES, F_HTML, F_JSON, F_JSONLD, F_GZIP, - __version__, validate_bbox, validate_datetime, + __version__, validate_bbox, validate_datetime, evaluate_limit, validate_subset, landing_page, openapi_, conformance, describe_collections, get_collection_schema, ) @@ -848,3 +848,42 @@ def test_get_exception(config, api_): assert content['description'] == 'oops' d = api_.get_exception(500, {}, 'html', 'NoApplicableCode', 'oops') + + +def test_evaluate_limit(): + collection = {} + server = {} + + with pytest.raises(ValueError): + assert evaluate_limit('1.1', server, collection) == 10 + + with pytest.raises(ValueError): + assert evaluate_limit('-12', server, collection) == 10 + + assert evaluate_limit('1', server, collection) == 1 + + collection = {} + server = {'default_items': 2, 'max_items': 3} + + assert evaluate_limit(None, server, collection) == 2 + assert evaluate_limit('1', server, collection) == 1 + assert evaluate_limit('4', server, collection) == 3 + + collection = {'default_items': 10, 'max_items': 50} + server = {'default_items': 100, 'max_items': 1000} + + assert evaluate_limit(None, server, collection) == 10 + assert evaluate_limit('40', server, collection) == 40 + assert evaluate_limit('60', server, collection) == 50 + + collection = {} + server = {'default_items': 2, 'max_items': 3, 'on_exceed': 'error'} + + with pytest.raises(RuntimeError): + assert evaluate_limit('40', server, collection) == 40 + + collection = {'default_items': 10} + server = {'default_items': 2, 'max_items': 3} + + assert evaluate_limit(None, server, collection) == 10 + assert evaluate_limit('40', server, collection) == 3 diff --git a/tests/api/test_itemtypes.py b/tests/api/test_itemtypes.py index ae19c28d6..cc41b39a7 100644 --- a/tests/api/test_itemtypes.py +++ b/tests/api/test_itemtypes.py @@ -179,7 +179,7 @@ def test_get_collection_items(config, api_): assert len(features['features']) == 0 # Invalid limit - req = mock_api_request({'limit': 0}) + req = mock_api_request({'limit': '0'}) rsp_headers, code, response = get_collection_items(api_, req, 'obs') features = json.loads(response) @@ -199,7 +199,7 @@ def test_get_collection_items(config, api_): assert len(features['features']) == 1 assert features['numberMatched'] == 1 - req = mock_api_request({'limit': 2}) + req = mock_api_request({'limit': '2'}) rsp_headers, code, response = get_collection_items(api_, req, 'obs') features = json.loads(response) @@ -246,8 +246,8 @@ def test_get_collection_items(config, api_): assert links[4]['rel'] == 'collection' req = mock_api_request({ - 'offset': 1, - 'limit': 1, + 'offset': '1', + 'limit': '1', 'bbox': '-180,90,180,90' }) rsp_headers, code, response = get_collection_items(api_, req, 'obs') @@ -536,7 +536,7 @@ def test_manage_collection_item_editable_options_req(config, openapi): def test_get_collection_items_json_ld(config, api_): req = mock_api_request({ 'f': 'jsonld', - 'limit': 2 + 'limit': '2' }) rsp_headers, code, response = get_collection_items(api_, req, 'obs') diff --git a/tests/api/test_processes.py b/tests/api/test_processes.py index 6062f5666..5f22e2c98 100644 --- a/tests/api/test_processes.py +++ b/tests/api/test_processes.py @@ -46,7 +46,7 @@ def test_describe_processes(config, api_): - req = mock_api_request({'limit': 1}) + req = mock_api_request({'limit': '1'}) # Test for description of single processes rsp_headers, code, response = describe_processes(api_, req) data = json.loads(response) @@ -471,7 +471,7 @@ def test_get_jobs_pagination(api_): headers, code, response = get_jobs( api_, - mock_api_request({'limit': 10, 'offset': 9}), + mock_api_request({'limit': '10', 'offset': '9'}), job_id=None) job_response_offset = json.loads(response) # check to get 1 same job id with an offset of 9 and limit of 10 @@ -486,8 +486,8 @@ def test_get_jobs_pagination(api_): # test custom limit headers, code, response = get_jobs( api_, - mock_api_request({'limit': 20}), + mock_api_request({'limit': '20'}), job_id=None) job_response = json.loads(response) # might be more than 11 due to test interaction - assert len(job_response['jobs']) > 10 + assert len(job_response['jobs']) >= 10 diff --git a/tests/cite/cite.config.yml b/tests/cite/cite.config.yml index 1481cb37d..104fb09b5 100644 --- a/tests/cite/cite.config.yml +++ b/tests/cite/cite.config.yml @@ -8,7 +8,9 @@ server: language: en-US cors: true pretty_print: true - limit: 100 + limits: + default_items: 10 + max_items: 10 # templates: /path/to/templates map: url: https://tile.openstreetmap.org/{z}/{x}/{y}.png diff --git a/tests/pygeoapi-test-config-admin.yml b/tests/pygeoapi-test-config-admin.yml index fa9b08d84..760f92b37 100644 --- a/tests/pygeoapi-test-config-admin.yml +++ b/tests/pygeoapi-test-config-admin.yml @@ -39,7 +39,9 @@ server: - en-US cors: true pretty_print: true - limit: 10 + limits: + default_items: 10 + max_items: 10 map: url: https://tile.openstreetmap.org/{z}/{x}/{y}.png attribution: '© OpenStreetMap contributors' diff --git a/tests/pygeoapi-test-config-apirules.yml b/tests/pygeoapi-test-config-apirules.yml index 6aba4c71c..951abb5df 100644 --- a/tests/pygeoapi-test-config-apirules.yml +++ b/tests/pygeoapi-test-config-apirules.yml @@ -43,7 +43,9 @@ server: - fr-CA cors: true pretty_print: true - limit: 10 + limits: + default_items: 10 + max_items: 10 # templates: /path/to/templates map: url: https://tile.openstreetmap.org/{z}/{x}/{y}.png diff --git a/tests/pygeoapi-test-config-enclosure.yml b/tests/pygeoapi-test-config-enclosure.yml index aa65b0595..5f31eb660 100644 --- a/tests/pygeoapi-test-config-enclosure.yml +++ b/tests/pygeoapi-test-config-enclosure.yml @@ -41,7 +41,9 @@ server: - fr-CA cors: true pretty_print: true - limit: 10 + limits: + default_items: 10 + max_items: 10 # templates: /path/to/templates map: url: https://tile.openstreetmap.org/{z}/{x}/{y}.png diff --git a/tests/pygeoapi-test-config-envvars.yml b/tests/pygeoapi-test-config-envvars.yml index 3784f13dd..e4ddf4290 100644 --- a/tests/pygeoapi-test-config-envvars.yml +++ b/tests/pygeoapi-test-config-envvars.yml @@ -38,7 +38,9 @@ server: gzip: false cors: true pretty_print: true - limit: 10 + limits: + default_items: 10 + max_items: 10 # templates: /path/to/templates map: url: https://tile.openstreetmap.org/{z}/{x}/{y}.png diff --git a/tests/pygeoapi-test-config-hidden-resources.yml b/tests/pygeoapi-test-config-hidden-resources.yml index 3682bc2c9..dd8074419 100644 --- a/tests/pygeoapi-test-config-hidden-resources.yml +++ b/tests/pygeoapi-test-config-hidden-resources.yml @@ -41,7 +41,9 @@ server: - fr-CA cors: true pretty_print: true - limit: 10 + limits: + default_items: 10 + max_items: 10 # templates: /path/to/templates map: url: https://tile.openstreetmap.org/{z}/{x}/{y}.png diff --git a/tests/pygeoapi-test-config-ogr.yml b/tests/pygeoapi-test-config-ogr.yml index e4237941a..373985dca 100644 --- a/tests/pygeoapi-test-config-ogr.yml +++ b/tests/pygeoapi-test-config-ogr.yml @@ -38,7 +38,9 @@ server: cors: true gzip: false pretty_print: true - limit: 10 + limits: + default_items: 10 + max_items: 10 # templates: /path/to/templates map: url: https://tile.openstreetmap.org/{z}/{x}/{y}.png diff --git a/tests/pygeoapi-test-config-postgresql-manager.yml b/tests/pygeoapi-test-config-postgresql-manager.yml index e0fe947d0..7ddd39e60 100644 --- a/tests/pygeoapi-test-config-postgresql-manager.yml +++ b/tests/pygeoapi-test-config-postgresql-manager.yml @@ -41,7 +41,9 @@ server: - fr-CA cors: true pretty_print: true - limit: 10 + limits: + default_items: 10 + max_items: 10 # templates: /path/to/templates map: url: https://tile.openstreetmap.org/{z}/{x}/{y}.png diff --git a/tests/pygeoapi-test-config-postgresql.yml b/tests/pygeoapi-test-config-postgresql.yml index 05a09668e..a3d0cf43a 100644 --- a/tests/pygeoapi-test-config-postgresql.yml +++ b/tests/pygeoapi-test-config-postgresql.yml @@ -43,7 +43,9 @@ server: - fr-CA # cors: true pretty_print: true - limit: 100 + limits: + default_items: 100 + max_items: 100 # templates: # path: /path/to/Jinja2/templates # static: /path/to/static/folder # css/js/img diff --git a/tests/pygeoapi-test-config.yml b/tests/pygeoapi-test-config.yml index 58b62484f..c31ddb6cc 100644 --- a/tests/pygeoapi-test-config.yml +++ b/tests/pygeoapi-test-config.yml @@ -41,7 +41,9 @@ server: - fr-CA cors: true pretty_print: true - limit: 10 + limits: + default_items: 10 + max_items: 10 # templates: /path/to/templates map: url: https://tile.openstreetmap.org/{z}/{x}/{y}.png