From 2f58550f46f6f03ac4b8e2097b621be088847a37 Mon Sep 17 00:00:00 2001
From: Vincent Privat
Date: Wed, 29 Jan 2025 14:54:46 +0100
Subject: [PATCH] Configure which OGC APIs are available
---
pygeoapi-config.yml | 7 ++
pygeoapi/api/__init__.py | 107 ++++++++++------
pygeoapi/django_/urls.py | 105 +++++++++++-----
pygeoapi/django_/views.py | 35 ++++--
pygeoapi/flask_app.py | 174 ++++++++++++++++++---------
pygeoapi/openapi.py | 86 ++++++-------
pygeoapi/starlette_app.py | 101 +++++++++++++---
pygeoapi/templates/landing_page.html | 2 +
8 files changed, 422 insertions(+), 195 deletions(-)
diff --git a/pygeoapi-config.yml b/pygeoapi-config.yml
index b260c76d2..416b8b6d0 100644
--- a/pygeoapi-config.yml
+++ b/pygeoapi-config.yml
@@ -56,6 +56,13 @@ server:
# output_dir: /tmp/
# ogc_schemas_location: /opt/schemas.opengis.net
admin: false # enable admin api
+ coverages: true # enable ogcapi-coverages
+ edr: true # enable ogcapi-edr
+ features: true # enable ogcapi-features
+ maps: true # enable ogcapi-maps
+ processes: true # enable ogcapi-processes
+ stac: true # enable ogcapi-stac
+ tiles: true # enable ogcapi-tiles
logging:
level: ERROR
diff --git a/pygeoapi/api/__init__.py b/pygeoapi/api/__init__.py
index 44f01f540..5c85d609d 100644
--- a/pygeoapi/api/__init__.py
+++ b/pygeoapi/api/__init__.py
@@ -122,7 +122,7 @@
DEFAULT_STORAGE_CRS = DEFAULT_CRS
-def all_apis() -> dict:
+def all_apis(server_cfg: dict = {}) -> dict:
"""
Return all supported API modules
@@ -131,18 +131,36 @@ def all_apis() -> dict:
:returns: `dict` of API provider type, API module
"""
- from . import (coverages, environmental_data_retrieval, itemtypes, maps,
- processes, tiles, stac)
-
- return {
- 'coverage': coverages,
- 'edr': environmental_data_retrieval,
- 'itemtypes': itemtypes,
- 'map': maps,
- 'process': processes,
- 'tile': tiles,
- 'stac': stac
- }
+ apis: dict = {}
+
+ from . import itemtypes
+ apis['itemtypes'] = itemtypes
+
+ if server_cfg.get('coverages', True):
+ from . import coverages
+ apis['coverage'] = coverages
+
+ if server_cfg.get('edr', True):
+ from . import environmental_data_retrieval
+ apis['edr'] = environmental_data_retrieval
+
+ if server_cfg.get('maps', True):
+ from . import maps
+ apis['map'] = maps
+
+ if server_cfg.get('processes', True):
+ from . import processes
+ apis['process'] = processes
+
+ if server_cfg.get('tiles', True):
+ from . import tiles
+ apis['tile'] = tiles
+
+ if server_cfg.get('stac', True):
+ from . import stac
+ apis['stac'] = stac
+
+ return apis
def apply_gzip(headers: dict, content: Union[str, bytes]) -> Union[str, bytes]:
@@ -742,6 +760,10 @@ def landing_page(api: API,
request.locale)
}
+ processes_enabled = api.config['server'].get('processes', True)
+ stac_enabled = api.config['server'].get('stac', True)
+ tiles_enabled = api.config['server'].get('tiles', True)
+
LOGGER.debug('Creating links')
# TODO: put title text in config or translatable files?
fcm['links'] = [{
@@ -788,42 +810,48 @@ def landing_page(api: API,
'type': FORMAT_TYPES[F_JSON],
'title': l10n.translate('Collections', request.locale),
'href': api.get_collections_url()
- }, {
- 'rel': 'http://www.opengis.net/def/rel/ogc/1.0/processes',
- 'type': FORMAT_TYPES[F_JSON],
- 'title': l10n.translate('Processes', request.locale),
- 'href': f"{api.base_url}/processes"
- }, {
- 'rel': 'http://www.opengis.net/def/rel/ogc/1.0/job-list',
- 'type': FORMAT_TYPES[F_JSON],
- 'title': l10n.translate('Jobs', request.locale),
- 'href': f"{api.base_url}/jobs"
- }, {
- 'rel': 'http://www.opengis.net/def/rel/ogc/1.0/tiling-schemes',
- 'type': FORMAT_TYPES[F_JSON],
- 'title': l10n.translate('The list of supported tiling schemes as JSON', request.locale), # noqa
- 'href': f"{api.base_url}/TileMatrixSets?f=json"
- }, {
- 'rel': 'http://www.opengis.net/def/rel/ogc/1.0/tiling-schemes',
- 'type': FORMAT_TYPES[F_HTML],
- 'title': l10n.translate('The list of supported tiling schemes as HTML', request.locale), # noqa
- 'href': f"{api.base_url}/TileMatrixSets?f=html"
}]
+ if processes_enabled:
+ fcm['links'].extend([{
+ 'rel': 'http://www.opengis.net/def/rel/ogc/1.0/processes',
+ 'type': FORMAT_TYPES[F_JSON],
+ 'title': l10n.translate('Processes', request.locale),
+ 'href': f"{api.base_url}/processes"
+ }, {
+ 'rel': 'http://www.opengis.net/def/rel/ogc/1.0/job-list',
+ 'type': FORMAT_TYPES[F_JSON],
+ 'title': l10n.translate('Jobs', request.locale),
+ 'href': f"{api.base_url}/jobs"
+ }])
+ if tiles_enabled:
+ fcm['links'].extend([{
+ 'rel': 'http://www.opengis.net/def/rel/ogc/1.0/tiling-schemes',
+ 'type': FORMAT_TYPES[F_JSON],
+ 'title': l10n.translate('The list of supported tiling schemes as JSON', request.locale), # noqa
+ 'href': f"{api.base_url}/TileMatrixSets?f=json"
+ }, {
+ 'rel': 'http://www.opengis.net/def/rel/ogc/1.0/tiling-schemes',
+ 'type': FORMAT_TYPES[F_HTML],
+ 'title': l10n.translate('The list of supported tiling schemes as HTML', request.locale), # noqa
+ 'href': f"{api.base_url}/TileMatrixSets?f=html"
+ }])
+
headers = request.get_response_headers(**api.api_headers)
if request.format == F_HTML: # render
fcm['processes'] = False
fcm['stac'] = False
fcm['collection'] = False
+ fcm['tiles'] = tiles_enabled
if filter_dict_by_key_value(api.config['resources'],
'type', 'process'):
- fcm['processes'] = True
+ fcm['processes'] = processes_enabled
if filter_dict_by_key_value(api.config['resources'],
'type', 'stac-collection'):
- fcm['stac'] = True
+ fcm['stac'] = stac_enabled
if filter_dict_by_key_value(api.config['resources'],
'type', 'collection'):
@@ -882,14 +910,17 @@ def conformance(api, request: APIRequest) -> Tuple[dict, int, str]:
:returns: tuple of headers, status code, content
"""
- apis_dict = all_apis()
+ apis_dict = all_apis(api.config['server'])
+
+ processes_enabled = api.config['server'].get('processes', True)
conformance_list = CONFORMANCE_CLASSES
for key, value in api.config['resources'].items():
if value['type'] == 'process':
- conformance_list.extend(
- apis_dict['process'].CONFORMANCE_CLASSES)
+ if processes_enabled:
+ conformance_list.extend(
+ apis_dict['process'].CONFORMANCE_CLASSES)
else:
for provider in value['providers']:
if provider['type'] in apis_dict:
diff --git a/pygeoapi/django_/urls.py b/pygeoapi/django_/urls.py
index 5736b2dea..6f148b0d6 100644
--- a/pygeoapi/django_/urls.py
+++ b/pygeoapi/django_/urls.py
@@ -58,6 +58,15 @@
from . import views
+coverages_enabled = settings.PYGEOAPI_CONFIG['server'].get('coverages', True)
+edr_enabled = settings.PYGEOAPI_CONFIG['server'].get('edr', True)
+features_enabled = settings.PYGEOAPI_CONFIG['server'].get('features', True)
+maps_enabled = settings.PYGEOAPI_CONFIG['server'].get('maps', True)
+processes_enabled = settings.PYGEOAPI_CONFIG['server'].get('processes', True)
+stac_enabled = settings.PYGEOAPI_CONFIG['server'].get('stac', True)
+tiles_enabled = settings.PYGEOAPI_CONFIG['server'].get('tiles', True)
+admin_enabled = settings.PYGEOAPI_CONFIG['server'].get('admin', False)
+
def apply_slash_rule(url: str):
""" Strip trailing slashes if the API rules are strict about it.
@@ -76,16 +85,6 @@ def apply_slash_rule(url: str):
views.conformance,
name='conformance'
),
- path(
- apply_slash_rule('TileMatrixSets/'),
- views.tilematrixsets,
- name='tilematrixsets'
- ),
- path(
- apply_slash_rule('TileMatrixSets/'),
- views.tilematrixsets,
- name='tilematrixset'
- ),
path(
apply_slash_rule('collections/'),
views.collections,
@@ -106,6 +105,9 @@ def apply_slash_rule(url: str):
views.collection_queryables,
name='collection-queryables',
),
+]
+
+features_urlpatterns = [
path(
apply_slash_rule('collections//items/'),
views.collection_items,
@@ -116,30 +118,21 @@ def apply_slash_rule(url: str):
views.collection_item,
name='collection-item',
),
+]
+
+if features_enabled:
+ urlpatterns.extend(features_urlpatterns)
+
+tiles_urlpatterns = [
path(
- apply_slash_rule('collections//coverage/'),
- views.collection_coverage,
- name='collection-coverage',
- ),
- path(
- 'collections//map',
- views.collection_map,
- name='collection-map',
- ),
- path(
- 'collections//styles//map',
- views.collection_style_map,
- name='collection-style-map',
- ),
- path(
- apply_slash_rule('collections//tiles/'),
- views.collection_tiles,
- name='collection-tiles',
+ apply_slash_rule('TileMatrixSets/'),
+ views.tilematrixsets,
+ name='tilematrixsets'
),
path(
- 'collections//tiles/',
- views.collection_tiles_metadata,
- name='collection-tiles-metadata',
+ apply_slash_rule('TileMatrixSets/'),
+ views.tilematrixsets,
+ name='tilematrixset'
),
path(
'collections//tiles//metadata',
@@ -152,6 +145,39 @@ def apply_slash_rule(url: str):
views.collection_item_tiles,
name='collection-item-tiles',
),
+]
+
+if tiles_enabled:
+ urlpatterns.extend(tiles_urlpatterns)
+
+coverages_urlpatterns = [
+ path(
+ apply_slash_rule('collections//coverage/'),
+ views.collection_coverage,
+ name='collection-coverage',
+ ),
+]
+
+if coverages_enabled:
+ urlpatterns.extend(coverages_urlpatterns)
+
+maps_urlpatterns = [
+ path(
+ 'collections//map',
+ views.collection_map,
+ name='collection-map',
+ ),
+ path(
+ 'collections//styles//map',
+ views.collection_style_map,
+ name='collection-style-map',
+ ),
+]
+
+if maps_enabled:
+ urlpatterns.extend(maps_urlpatterns)
+
+edr_urlpatterns = [
path(
'collections//position',
views.get_collection_edr_query,
@@ -242,6 +268,12 @@ def apply_slash_rule(url: str):
views.get_collection_edr_query,
name='collection-edr-corridor',
),
+]
+
+if edr_enabled:
+ urlpatterns.extend(edr_urlpatterns)
+
+processes_urlpatterns = [
path(apply_slash_rule('processes/'), views.processes, name='processes'),
path('processes/', views.processes, name='process-detail'),
path('processes//execution', views.process_execution,
@@ -258,6 +290,12 @@ def apply_slash_rule(url: str):
views.job_results_resource,
name='job-results-resource',
),
+]
+
+if processes_enabled:
+ urlpatterns.extend(processes_urlpatterns)
+
+stac_urlpatterns = [
path(
apply_slash_rule('stac/'),
views.stac_catalog_root,
@@ -265,6 +303,9 @@ def apply_slash_rule(url: str):
)
]
+if stac_enabled:
+ urlpatterns.extend(stac_urlpatterns)
+
url_route_prefix = settings.API_RULES.get_url_prefix('django')
if url_route_prefix:
# Add a URL prefix to all routes if configured
@@ -272,7 +313,7 @@ def apply_slash_rule(url: str):
path(url_route_prefix, include(urlpatterns))
]
-if settings.PYGEOAPI_CONFIG['server'].get('admin', False):
+if admin_enabled:
admin_urlpatterns = [
path(
apply_slash_rule('admin/config'),
diff --git a/pygeoapi/django_/views.py b/pygeoapi/django_/views.py
index 682ef51ce..cce34a299 100644
--- a/pygeoapi/django_/views.py
+++ b/pygeoapi/django_/views.py
@@ -42,15 +42,36 @@
from pygeoapi.api import API, APIRequest, apply_gzip
import pygeoapi.api as core_api
-import pygeoapi.api.coverages as coverages_api
-import pygeoapi.api.environmental_data_retrieval as edr_api
import pygeoapi.api.itemtypes as itemtypes_api
-import pygeoapi.api.maps as maps_api
-import pygeoapi.api.processes as processes_api
-import pygeoapi.api.stac as stac_api
-import pygeoapi.api.tiles as tiles_api
-if settings.PYGEOAPI_CONFIG['server'].get('admin'):
+coverages_enabled = settings.PYGEOAPI_CONFIG['server'].get('coverages', True)
+edr_enabled = settings.PYGEOAPI_CONFIG['server'].get('edr', True)
+features_enabled = settings.PYGEOAPI_CONFIG['server'].get('features', True)
+maps_enabled = settings.PYGEOAPI_CONFIG['server'].get('maps', True)
+processes_enabled = settings.PYGEOAPI_CONFIG['server'].get('processes', True)
+stac_enabled = settings.PYGEOAPI_CONFIG['server'].get('stac', True)
+tiles_enabled = settings.PYGEOAPI_CONFIG['server'].get('tiles', True)
+admin_enabled = settings.PYGEOAPI_CONFIG['server'].get('admin', False)
+
+if coverages_enabled:
+ import pygeoapi.api.coverages as coverages_api
+
+if edr_enabled:
+ import pygeoapi.api.environmental_data_retrieval as edr_api
+
+if maps_enabled:
+ import pygeoapi.api.maps as maps_api
+
+if processes_enabled:
+ import pygeoapi.api.processes as processes_api
+
+if stac_enabled:
+ import pygeoapi.api.stac as stac_api
+
+if tiles_enabled:
+ import pygeoapi.api.tiles as tiles_api
+
+if admin_enabled:
import pygeoapi.admin as admin_api
diff --git a/pygeoapi/flask_app.py b/pygeoapi/flask_app.py
index 744862d4f..7ec4dc066 100644
--- a/pygeoapi/flask_app.py
+++ b/pygeoapi/flask_app.py
@@ -39,13 +39,7 @@
from pygeoapi.api import API, APIRequest, apply_gzip
import pygeoapi.api as core_api
-import pygeoapi.api.coverages as coverages_api
-import pygeoapi.api.environmental_data_retrieval as edr_api
import pygeoapi.api.itemtypes as itemtypes_api
-import pygeoapi.api.maps as maps_api
-import pygeoapi.api.processes as processes_api
-import pygeoapi.api.stac as stac_api
-import pygeoapi.api.tiles as tiles_api
from pygeoapi.openapi import load_openapi_document
from pygeoapi.config import get_config
from pygeoapi.util import get_mimetype, get_api_rules
@@ -54,12 +48,39 @@
CONFIG = get_config()
OPENAPI = load_openapi_document()
-API_RULES = get_api_rules(CONFIG)
+coverages_enabled = CONFIG['server'].get('coverages', True)
+edr_enabled = CONFIG['server'].get('edr', True)
+features_enabled = CONFIG['server'].get('features', True)
+maps_enabled = CONFIG['server'].get('maps', True)
+processes_enabled = CONFIG['server'].get('processes', True)
+stac_enabled = CONFIG['server'].get('stac', True)
+tiles_enabled = CONFIG['server'].get('tiles', True)
+admin_enabled = CONFIG['server'].get('admin', False)
+
+if coverages_enabled:
+ import pygeoapi.api.coverages as coverages_api
+
+if edr_enabled:
+ import pygeoapi.api.environmental_data_retrieval as edr_api
+
+if maps_enabled:
+ import pygeoapi.api.maps as maps_api
+
+if processes_enabled:
+ import pygeoapi.api.processes as processes_api
-if CONFIG['server'].get('admin'):
+if stac_enabled:
+ import pygeoapi.api.stac as stac_api
+
+if tiles_enabled:
+ import pygeoapi.api.tiles as tiles_api
+
+if admin_enabled:
import pygeoapi.admin as admin_api
from pygeoapi.admin import Admin
+API_RULES = get_api_rules(CONFIG)
+
STATIC_FOLDER = 'static'
if 'templates' in CONFIG['server']:
STATIC_FOLDER = CONFIG['server']['templates'].get('static', 'static')
@@ -67,12 +88,33 @@
APP = Flask(__name__, static_folder=STATIC_FOLDER, static_url_path='/static')
APP.url_map.strict_slashes = API_RULES.strict_slashes
-BLUEPRINT = Blueprint(
- 'pygeoapi',
- __name__,
- static_folder=STATIC_FOLDER,
- url_prefix=API_RULES.get_url_prefix('flask')
-)
+url_prefix = API_RULES.get_url_prefix('flask')
+
+BLUEPRINT = Blueprint('pygeoapi', __name__,
+ static_folder=STATIC_FOLDER,
+ url_prefix=url_prefix)
+COVERAGES_BLUEPRINT = Blueprint('pygeoapi-coverages', __name__,
+ static_folder=STATIC_FOLDER,
+ url_prefix=url_prefix)
+EDR_BLUEPRINT = Blueprint('pygeoapi-edr', __name__,
+ static_folder=STATIC_FOLDER,
+ url_prefix=url_prefix)
+FEATURES_BLUEPRINT = Blueprint('pygeoapi-features', __name__,
+ static_folder=STATIC_FOLDER,
+ url_prefix=url_prefix)
+MAPS_BLUEPRINT = Blueprint('pygeoapi-maps', __name__,
+ static_folder=STATIC_FOLDER,
+ url_prefix=url_prefix)
+PROCESSES_BLUEPRINT = Blueprint('pygeoapi-processes', __name__,
+ static_folder=STATIC_FOLDER,
+ url_prefix=url_prefix)
+STAC_BLUEPRINT = Blueprint('pygeoapi-stac', __name__,
+ static_folder=STATIC_FOLDER,
+ url_prefix=url_prefix)
+TILES_BLUEPRINT = Blueprint('pygeoapi-tiles', __name__,
+ static_folder=STATIC_FOLDER,
+ url_prefix=url_prefix)
+
ADMIN_BLUEPRINT = Blueprint('admin', __name__, static_folder=STATIC_FOLDER)
# CORS: optionally enable from config.
@@ -187,7 +229,7 @@ def conformance():
return execute_from_flask(core_api.conformance, request)
-@BLUEPRINT.route('/TileMatrixSets/')
+@TILES_BLUEPRINT.route('/TileMatrixSets/')
def get_tilematrix_set(tileMatrixSetId=None):
"""
OGC API TileMatrixSet endpoint
@@ -201,7 +243,7 @@ def get_tilematrix_set(tileMatrixSetId=None):
tileMatrixSetId)
-@BLUEPRINT.route('/TileMatrixSets')
+@TILES_BLUEPRINT.route('/TileMatrixSets')
def get_tilematrix_sets():
"""
OGC API TileMatrixSets endpoint
@@ -255,12 +297,12 @@ def collection_queryables(collection_id=None):
collection_id)
-@BLUEPRINT.route('/collections//items',
- methods=['GET', 'POST', 'OPTIONS'],
- provide_automatic_options=False)
-@BLUEPRINT.route('/collections//items/',
- methods=['GET', 'PUT', 'DELETE', 'OPTIONS'],
- provide_automatic_options=False)
+@FEATURES_BLUEPRINT.route('/collections//items',
+ methods=['GET', 'POST', 'OPTIONS'],
+ provide_automatic_options=False)
+@FEATURES_BLUEPRINT.route('/collections//items/', # noqa
+ methods=['GET', 'PUT', 'DELETE', 'OPTIONS'],
+ provide_automatic_options=False)
def collection_items(collection_id, item_id=None):
"""
OGC API collections items endpoint
@@ -309,7 +351,7 @@ def collection_items(collection_id, item_id=None):
collection_id, item_id)
-@BLUEPRINT.route('/collections//coverage')
+@COVERAGES_BLUEPRINT.route('/collections//coverage')
def collection_coverage(collection_id):
"""
OGC API - Coverages coverage endpoint
@@ -323,7 +365,7 @@ def collection_coverage(collection_id):
collection_id, skip_valid_check=True)
-@BLUEPRINT.route('/collections//tiles')
+@TILES_BLUEPRINT.route('/collections//tiles')
def get_collection_tiles(collection_id=None):
"""
OGC open api collections tiles access point
@@ -337,8 +379,8 @@ def get_collection_tiles(collection_id=None):
collection_id)
-@BLUEPRINT.route('/collections//tiles/')
-@BLUEPRINT.route('/collections//tiles//metadata') # noqa
+@TILES_BLUEPRINT.route('/collections//tiles/') # noqa
+@TILES_BLUEPRINT.route('/collections//tiles//metadata') # noqa
def get_collection_tiles_metadata(collection_id=None, tileMatrixSetId=None):
"""
OGC open api collection tiles service metadata
@@ -354,7 +396,7 @@ def get_collection_tiles_metadata(collection_id=None, tileMatrixSetId=None):
skip_valid_check=True)
-@BLUEPRINT.route('/collections//tiles/\
+@TILES_BLUEPRINT.route('/collections//tiles/\
///')
def get_collection_tiles_data(collection_id=None, tileMatrixSetId=None,
tileMatrix=None, tileRow=None, tileCol=None):
@@ -377,8 +419,8 @@ def get_collection_tiles_data(collection_id=None, tileMatrixSetId=None,
)
-@BLUEPRINT.route('/collections//map')
-@BLUEPRINT.route('/collections//styles//map')
+@MAPS_BLUEPRINT.route('/collections//map')
+@MAPS_BLUEPRINT.route('/collections//styles//map')
def collection_map(collection_id, style_id=None):
"""
OGC API - Maps map render endpoint
@@ -394,8 +436,8 @@ def collection_map(collection_id, style_id=None):
)
-@BLUEPRINT.route('/processes')
-@BLUEPRINT.route('/processes/')
+@PROCESSES_BLUEPRINT.route('/processes')
+@PROCESSES_BLUEPRINT.route('/processes/')
def get_processes(process_id=None):
"""
OGC API - Processes description endpoint
@@ -409,9 +451,9 @@ def get_processes(process_id=None):
process_id)
-@BLUEPRINT.route('/jobs')
-@BLUEPRINT.route('/jobs/',
- methods=['GET', 'DELETE'])
+@PROCESSES_BLUEPRINT.route('/jobs')
+@PROCESSES_BLUEPRINT.route('/jobs/',
+ methods=['GET', 'DELETE'])
def get_jobs(job_id=None):
"""
OGC API - Processes jobs endpoint
@@ -431,7 +473,8 @@ def get_jobs(job_id=None):
return execute_from_flask(processes_api.get_jobs, request, job_id)
-@BLUEPRINT.route('/processes//execution', methods=['POST'])
+@PROCESSES_BLUEPRINT.route('/processes//execution',
+ methods=['POST'])
def execute_process_jobs(process_id):
"""
OGC API - Processes execution endpoint
@@ -445,8 +488,8 @@ def execute_process_jobs(process_id):
process_id)
-@BLUEPRINT.route('/jobs//results',
- methods=['GET'])
+@PROCESSES_BLUEPRINT.route('/jobs//results',
+ methods=['GET'])
def get_job_result(job_id=None):
"""
OGC API - Processes job result endpoint
@@ -459,24 +502,24 @@ def get_job_result(job_id=None):
return execute_from_flask(processes_api.get_job_result, request, job_id)
-@BLUEPRINT.route('/collections//position')
-@BLUEPRINT.route('/collections//area')
-@BLUEPRINT.route('/collections//cube')
-@BLUEPRINT.route('/collections//radius')
-@BLUEPRINT.route('/collections//trajectory')
-@BLUEPRINT.route('/collections//corridor')
-@BLUEPRINT.route('/collections//locations/')
-@BLUEPRINT.route('/collections//locations')
-@BLUEPRINT.route('/collections//instances//position') # noqa
-@BLUEPRINT.route('/collections//instances//area') # noqa
-@BLUEPRINT.route('/collections//instances//cube') # noqa
-@BLUEPRINT.route('/collections//instances//radius') # noqa
-@BLUEPRINT.route('/collections//instances//trajectory') # noqa
-@BLUEPRINT.route('/collections//instances//corridor') # noqa
-@BLUEPRINT.route('/collections//instances//locations/') # noqa
-@BLUEPRINT.route('/collections//instances//locations') # noqa
-@BLUEPRINT.route('/collections//instances/')
-@BLUEPRINT.route('/collections//instances')
+@EDR_BLUEPRINT.route('/collections//position')
+@EDR_BLUEPRINT.route('/collections//area')
+@EDR_BLUEPRINT.route('/collections//cube')
+@EDR_BLUEPRINT.route('/collections//radius')
+@EDR_BLUEPRINT.route('/collections//trajectory')
+@EDR_BLUEPRINT.route('/collections//corridor')
+@EDR_BLUEPRINT.route('/collections//locations/') # noqa
+@EDR_BLUEPRINT.route('/collections//locations') # noqa
+@EDR_BLUEPRINT.route('/collections//instances//position') # noqa
+@EDR_BLUEPRINT.route('/collections//instances//area') # noqa
+@EDR_BLUEPRINT.route('/collections//instances//cube') # noqa
+@EDR_BLUEPRINT.route('/collections//instances//radius') # noqa
+@EDR_BLUEPRINT.route('/collections//instances//trajectory') # noqa
+@EDR_BLUEPRINT.route('/collections//instances//corridor') # noqa
+@EDR_BLUEPRINT.route('/collections//instances//locations/') # noqa
+@EDR_BLUEPRINT.route('/collections//instances//locations') # noqa
+@EDR_BLUEPRINT.route('/collections//instances/') # noqa
+@EDR_BLUEPRINT.route('/collections//instances') # noqa
def get_collection_edr_query(collection_id, instance_id=None,
location_id=None):
"""
@@ -508,7 +551,7 @@ def get_collection_edr_query(collection_id, instance_id=None,
)
-@BLUEPRINT.route('/stac')
+@STAC_BLUEPRINT.route('/stac')
def stac_catalog_root():
"""
STAC root endpoint
@@ -519,7 +562,7 @@ def stac_catalog_root():
return execute_from_flask(stac_api.get_stac_root, request)
-@BLUEPRINT.route('/stac/')
+@STAC_BLUEPRINT.route('/stac/')
def stac_catalog_path(path):
"""
STAC path endpoint
@@ -603,7 +646,22 @@ def admin_config_resource(resource_id):
APP.register_blueprint(BLUEPRINT)
-if CONFIG['server'].get('admin'):
+if coverages_enabled:
+ APP.register_blueprint(COVERAGES_BLUEPRINT)
+if edr_enabled:
+ APP.register_blueprint(EDR_BLUEPRINT)
+if features_enabled:
+ APP.register_blueprint(FEATURES_BLUEPRINT)
+if maps_enabled:
+ APP.register_blueprint(MAPS_BLUEPRINT)
+if processes_enabled:
+ APP.register_blueprint(PROCESSES_BLUEPRINT)
+if stac_enabled:
+ APP.register_blueprint(STAC_BLUEPRINT)
+if tiles_enabled:
+ APP.register_blueprint(TILES_BLUEPRINT)
+
+if admin_enabled:
admin_ = Admin(CONFIG, OPENAPI)
APP.register_blueprint(ADMIN_BLUEPRINT)
diff --git a/pygeoapi/openapi.py b/pygeoapi/openapi.py
index 31adce7c2..f8a39dd26 100644
--- a/pygeoapi/openapi.py
+++ b/pygeoapi/openapi.py
@@ -443,6 +443,9 @@ def get_oas_30(cfg: dict, fail_on_invalid_collection: bool = True) -> dict:
items_f = deepcopy(oas['components']['parameters']['f'])
items_f['schema']['enum'].append('csv')
+ tiles_enabled = cfg['server'].get('tiles', True)
+ admin_enabled = cfg['server'].get('admin', False)
+
LOGGER.debug('setting up datasets')
for k, v in get_visible_collections(cfg).items():
@@ -484,58 +487,59 @@ def get_oas_30(cfg: dict, fail_on_invalid_collection: bool = True) -> dict:
}
}
- oas['components']['responses'].update({
- 'Tiles': {
- 'description': 'Retrieves the tiles description for this collection', # noqa
- 'content': {
- 'application/json': {
- 'schema': {
- '$ref': '#/components/schemas/tiles'
+ if tiles_enabled:
+ oas['components']['responses'].update({
+ 'Tiles': {
+ 'description': 'Retrieves the tiles description for this collection', # noqa
+ 'content': {
+ 'application/json': {
+ 'schema': {
+ '$ref': '#/components/schemas/tiles'
+ }
}
}
}
}
- }
- )
-
- oas['components']['schemas'].update({
- 'tilematrixsetlink': {
- 'type': 'object',
- 'required': ['tileMatrixSet'],
- 'properties': {
- 'tileMatrixSet': {
- 'type': 'string'
- },
- 'tileMatrixSetURI': {
- 'type': 'string'
+ )
+
+ oas['components']['schemas'].update({
+ 'tilematrixsetlink': {
+ 'type': 'object',
+ 'required': ['tileMatrixSet'],
+ 'properties': {
+ 'tileMatrixSet': {
+ 'type': 'string'
+ },
+ 'tileMatrixSetURI': {
+ 'type': 'string'
+ }
}
- }
- },
- 'tiles': {
- 'type': 'object',
- 'required': [
- 'tileMatrixSetLinks',
- 'links'
- ],
- 'properties': {
- 'tileMatrixSetLinks': {
- 'type': 'array',
- 'items': {
- '$ref': '#/components/schemas/tilematrixsetlink' # noqa
+ },
+ 'tiles': {
+ 'type': 'object',
+ 'required': [
+ 'tileMatrixSetLinks',
+ 'links'
+ ],
+ 'properties': {
+ 'tileMatrixSetLinks': {
+ 'type': 'array',
+ 'items': {
+ '$ref': '#/components/schemas/tilematrixsetlink' # noqa
+ }
+ },
+ 'links': {
+ 'type': 'array',
+ 'items': {'$ref': f"{OPENAPI_YAML['oapit']}#/components/schemas/link"} # noqa
}
- },
- 'links': {
- 'type': 'array',
- 'items': {'$ref': f"{OPENAPI_YAML['oapit']}#/components/schemas/link"} # noqa
}
}
}
- }
- )
+ )
oas['paths'] = paths
- for api_name, api_module in all_apis().items():
+ for api_name, api_module in all_apis(cfg['server']).items():
LOGGER.debug(f'Adding OpenAPI definitions for {api_name}')
try:
@@ -548,7 +552,7 @@ def get_oas_30(cfg: dict, fail_on_invalid_collection: bool = True) -> dict:
else:
LOGGER.warning(f'Resource not added to OpenAPI: {err}')
- if cfg['server'].get('admin', False):
+ if admin_enabled:
schema_dict = get_config_schema()
oas['definitions'] = schema_dict['definitions']
LOGGER.debug('Adding admin endpoints')
diff --git a/pygeoapi/starlette_app.py b/pygeoapi/starlette_app.py
index 984e62302..982d6224d 100644
--- a/pygeoapi/starlette_app.py
+++ b/pygeoapi/starlette_app.py
@@ -51,13 +51,7 @@
from pygeoapi.api import API, APIRequest, apply_gzip
import pygeoapi.api as core_api
-import pygeoapi.api.coverages as coverages_api
-import pygeoapi.api.environmental_data_retrieval as edr_api
import pygeoapi.api.itemtypes as itemtypes_api
-import pygeoapi.api.maps as maps_api
-import pygeoapi.api.processes as processes_api
-import pygeoapi.api.stac as stac_api
-import pygeoapi.api.tiles as tiles_api
from pygeoapi.openapi import load_openapi_document
from pygeoapi.config import get_config
from pygeoapi.util import get_api_rules
@@ -69,7 +63,34 @@
OPENAPI = load_openapi_document()
-if CONFIG['server'].get('admin'):
+coverages_enabled = CONFIG['server'].get('coverages', True)
+edr_enabled = CONFIG['server'].get('edr', True)
+features_enabled = CONFIG['server'].get('features', True)
+maps_enabled = CONFIG['server'].get('maps', True)
+processes_enabled = CONFIG['server'].get('processes', True)
+stac_enabled = CONFIG['server'].get('stac', True)
+tiles_enabled = CONFIG['server'].get('tiles', True)
+admin_enabled = CONFIG['server'].get('admin', False)
+
+if coverages_enabled:
+ import pygeoapi.api.coverages as coverages_api
+
+if edr_enabled:
+ import pygeoapi.api.environmental_data_retrieval as edr_api
+
+if maps_enabled:
+ import pygeoapi.api.maps as maps_api
+
+if processes_enabled:
+ import pygeoapi.api.processes as processes_api
+
+if stac_enabled:
+ import pygeoapi.api.stac as stac_api
+
+if tiles_enabled:
+ import pygeoapi.api.tiles as tiles_api
+
+if admin_enabled:
import pygeoapi.admin as admin_api
from pygeoapi.admin import Admin
@@ -649,25 +670,60 @@ async def __call__(self, scope: Scope,
Route('/', landing_page),
Route('/openapi', openapi),
Route('/conformance', conformance),
- Route('/TileMatrixSets/{tileMatrixSetId}', get_tilematrix_set),
- Route('/TileMatrixSets', get_tilematrix_sets),
+ Route('/collections', collections),
+ Route('/collections/{collection_id:path}', collections),
Route('/collections/{collection_id:path}/schema', collection_schema),
Route('/collections/{collection_id:path}/queryables', collection_queryables), # noqa
+]
+
+features_routes = [
+ Route('/collections/{collection_id:path}/items', collection_items, methods=['GET', 'POST', 'OPTIONS']), # noqa
+ Route('/collections/{collection_id:path}/items/{item_id:path}', collection_items, methods=['GET', 'PUT', 'DELETE', 'OPTIONS']) # noqa
+]
+
+if features_enabled:
+ api_routes.extend(features_routes)
+
+tiles_routes = [
+ Route('/TileMatrixSets/{tileMatrixSetId}', get_tilematrix_set),
+ Route('/TileMatrixSets', get_tilematrix_sets),
Route('/collections/{collection_id:path}/tiles', get_collection_tiles),
Route('/collections/{collection_id:path}/tiles/{tileMatrixSetId}', get_collection_tiles_metadata), # noqa
Route('/collections/{collection_id:path}/tiles/{tileMatrixSetId}/metadata', get_collection_tiles_metadata), # noqa
- Route('/collections/{collection_id:path}/tiles/{tileMatrixSetId}/{tile_matrix}/{tileRow}/{tileCol}', get_collection_items_tiles), # noqa
- Route('/collections/{collection_id:path}/items', collection_items, methods=['GET', 'POST', 'OPTIONS']), # noqa
- Route('/collections/{collection_id:path}/items/{item_id:path}', collection_items, methods=['GET', 'PUT', 'DELETE', 'OPTIONS']), # noqa
- Route('/collections/{collection_id:path}/coverage', collection_coverage), # noqa
+ Route('/collections/{collection_id:path}/tiles/{tileMatrixSetId}/{tile_matrix}/{tileRow}/{tileCol}', get_collection_items_tiles) # noqa
+]
+
+if tiles_enabled:
+ api_routes.extend(tiles_routes)
+
+coverages_routes = [
+ Route('/collections/{collection_id:path}/coverage', collection_coverage) # noqa
+]
+
+if coverages_enabled:
+ api_routes.extend(coverages_routes)
+
+maps_routes = [
Route('/collections/{collection_id:path}/map', collection_map),
- Route('/collections/{collection_id:path}/styles/{style_id:path}/map', collection_map), # noqa
+ Route('/collections/{collection_id:path}/styles/{style_id:path}/map', collection_map) # noqa
+]
+
+if maps_enabled:
+ api_routes.extend(maps_routes)
+
+processes_routes = [
Route('/processes', get_processes),
Route('/processes/{process_id}', get_processes),
Route('/jobs', get_jobs),
Route('/jobs/{job_id}', get_jobs, methods=['GET', 'DELETE']),
Route('/processes/{process_id}/execution', execute_process_jobs, methods=['POST']), # noqa
- Route('/jobs/{job_id}/results', get_job_result),
+ Route('/jobs/{job_id}/results', get_job_result)
+]
+
+if processes_enabled:
+ api_routes.extend(processes_routes)
+
+edr_routes = [
Route('/collections/{collection_id:path}/position', get_collection_edr_query), # noqa
Route('/collections/{collection_id:path}/area', get_collection_edr_query),
Route('/collections/{collection_id:path}/cube', get_collection_edr_query),
@@ -685,13 +741,20 @@ async def __call__(self, scope: Scope,
Route('/collections/{collection_id:path}/instances/{instance_id}/trajectory', get_collection_edr_query), # noqa
Route('/collections/{collection_id:path}/instances/{instance_id}/corridor', get_collection_edr_query), # noqa
Route('/collections/{collection_id:path}/instances/{instance_id}/locations', get_collection_edr_query), # noqa
- Route('/collections/{collection_id:path}/instances/{instance_id}/locations/{location_id}', get_collection_edr_query), # noqa
- Route('/collections', collections),
- Route('/collections/{collection_id:path}', collections),
+ Route('/collections/{collection_id:path}/instances/{instance_id}/locations/{location_id}', get_collection_edr_query) # noqa
+]
+
+if edr_enabled:
+ api_routes.extend(edr_routes)
+
+stac_routes = [
Route('/stac', stac_catalog_root),
Route('/stac/{path:path}', stac_catalog_path)
]
+if stac_enabled:
+ api_routes.extend(stac_routes)
+
admin_routes = [
Route('/admin/config', admin_config, methods=['GET', 'PUT', 'PATCH']),
Route('/admin/config/resources', admin_config_resources, methods=['GET', 'POST']), # noqa
@@ -699,7 +762,7 @@ async def __call__(self, scope: Scope,
methods=['GET', 'PUT', 'PATCH', 'DELETE'])
]
-if CONFIG['server'].get('admin', False):
+if admin_enabled:
ADMIN = Admin(CONFIG, OPENAPI)
api_routes.extend(admin_routes)
diff --git a/pygeoapi/templates/landing_page.html b/pygeoapi/templates/landing_page.html
index 147b2a9c6..f0a6baf98 100644
--- a/pygeoapi/templates/landing_page.html
+++ b/pygeoapi/templates/landing_page.html
@@ -97,12 +97,14 @@ {% trans %}Conformance{% endtrans %}
{% trans %}View the conformance classes of this service{% endtrans %}
+ {% if data['tiles'] %}
+ {% endif %}