Skip to content

Commit 14a73e5

Browse files
authored
Add CRS parameter support to EDR API (#2170)
* Add CRS parameter support to EDR API * Added EDR CRS support to the documentation
1 parent 751d12a commit 14a73e5

3 files changed

Lines changed: 45 additions & 3 deletions

File tree

docs/source/crs.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ CRS support exists for the following OGC APIs:
3838
:ref:`OGC API - Features<ogcapi-features>`,✅,✅,✅
3939
:ref:`OGC API - Maps<ogcapi-maps>`,✅,❌,❌
4040
:ref:`OGC API - Coverages<ogcapi-coverages>`,✅,❌,❌
41+
:ref:`OGC API - Environmental Data Retrieval<ogcapi-edr>`,❌,❌,✅
4142

4243
Configuration
4344
-------------

pygeoapi/api/environmental_data_retrieval.py

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,13 @@
4343
from typing import Tuple
4444
import urllib
4545

46+
from pyproj.exceptions import CRSError
4647
from shapely.errors import ShapelyError
4748
from shapely.wkt import loads as shapely_loads
4849

4950
from pygeoapi import l10n
5051
from pygeoapi.api import evaluate_limit
52+
from pygeoapi.crs import (create_crs_transform_spec, set_content_crs_header)
5153
from pygeoapi.plugin import load_plugin, PLUGINS
5254
from pygeoapi.provider.base import (
5355
ProviderGenericError, ProviderItemNotFoundError)
@@ -265,8 +267,9 @@ def get_collection_edr_query(api: API, request: APIRequest,
265267

266268
LOGGER.debug('Loading provider')
267269
try:
268-
p = load_plugin('provider', get_provider_by_type(
269-
collections[dataset]['providers'], 'edr'))
270+
provider_def = get_provider_by_type(
271+
collections[dataset]['providers'], 'edr')
272+
p = load_plugin('provider', provider_def)
270273
except ProviderGenericError as err:
271274
return api.get_exception(
272275
err.http_status_code, headers, request.format,
@@ -284,6 +287,21 @@ def get_collection_edr_query(api: API, request: APIRequest,
284287
HTTPStatus.BAD_REQUEST, headers, request.format,
285288
'InvalidParameterValue', msg)
286289

290+
crs_transform_spec = None
291+
query_crs_uri = request.params.get('crs')
292+
if query_crs_uri is not None:
293+
LOGGER.debug('Processing crs parameter')
294+
try:
295+
crs_transform_spec = create_crs_transform_spec(
296+
provider_def, query_crs_uri
297+
)
298+
except (ValueError, CRSError) as err:
299+
msg = str(err)
300+
return api.get_exception(
301+
HTTPStatus.BAD_REQUEST, headers, request.format,
302+
'InvalidParameterValue', msg)
303+
set_content_crs_header(headers, provider_def, query_crs_uri)
304+
287305
LOGGER.debug('Processing query parameters')
288306

289307
LOGGER.debug('Processing datetime parameter')
@@ -377,7 +395,8 @@ def get_collection_edr_query(api: API, request: APIRequest,
377395
within=within,
378396
within_units=within_units,
379397
limit=limit,
380-
location_id=location_id
398+
location_id=location_id,
399+
crs_transform_spec=crs_transform_spec
381400
)
382401

383402
try:
@@ -507,6 +526,7 @@ def get_oas_30(cfg: dict, locale: str) -> tuple[list[dict[str, str]], dict[str,
507526
{'$ref': f"{OPENAPI_YAML['oapif-1']}#/components/parameters/datetime"}, # noqa
508527
{'$ref': f"{OPENAPI_YAML['oaedr']}/parameters/parameter-name.yaml"}, # noqa
509528
{'$ref': f"{OPENAPI_YAML['oaedr']}/parameters/z.yaml"}, # noqa
529+
{'$ref': '#/components/parameters/crs'},
510530
{'$ref': '#/components/parameters/f'}
511531
],
512532
'responses': {
@@ -590,6 +610,7 @@ def get_oas_30(cfg: dict, locale: str) -> tuple[list[dict[str, str]], dict[str,
590610
{'$ref': f"{OPENAPI_YAML['oaedr']}/parameters/locationId.yaml"}, # noqa
591611
{'$ref': f"{OPENAPI_YAML['oapif-1']}#/components/parameters/datetime"}, # noqa
592612
{'$ref': f"{OPENAPI_YAML['oaedr']}/parameters/parameter-name.yaml"}, # noqa
613+
{'$ref': '#/components/parameters/crs'},
593614
{'$ref': '#/components/parameters/f'}
594615
],
595616
'responses': {

tests/api/test_environmental_data_retrieval.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,3 +252,23 @@ def test_get_collection_edr_query(config, api_):
252252
rsp_headers, code, response = get_collection_edr_query(
253253
api_, req, 'usgs-prism', None, 'cube')
254254
assert code == HTTPStatus.OK
255+
256+
257+
def test_get_collection_edr_query_crs(config, api_):
258+
# Invalid CRS query parameter (not a URI)
259+
req = mock_api_request({'coords': 'POINT(11 11)', 'crs': '4326'})
260+
rsp_headers, code, response = get_collection_edr_query(
261+
api_, req, 'icoads-sst', None, 'position')
262+
assert code == HTTPStatus.BAD_REQUEST
263+
264+
# Valid CRS parameter (default CRS)
265+
req = mock_api_request({
266+
'coords': 'POINT(11 11)',
267+
'crs': 'http://www.opengis.net/def/crs/OGC/1.3/CRS84'
268+
})
269+
rsp_headers, code, response = get_collection_edr_query(
270+
api_, req, 'icoads-sst', None, 'position')
271+
assert code == HTTPStatus.OK
272+
assert 'Content-Crs' in rsp_headers
273+
expected_crs = '<http://www.opengis.net/def/crs/OGC/1.3/CRS84>'
274+
assert rsp_headers['Content-Crs'] == expected_crs

0 commit comments

Comments
 (0)