Skip to content

Commit

Permalink
feat[server]: rework stac-server and add cql2 support (#966)
Browse files Browse the repository at this point in the history
  • Loading branch information
alambare-csgroup committed Feb 29, 2024
1 parent d4d6bdf commit 5901a6e
Show file tree
Hide file tree
Showing 29 changed files with 3,551 additions and 2,169 deletions.
3 changes: 3 additions & 0 deletions NOTICE
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ https://github.com/tiangolo/fastapi
https://github.com/urllib3/urllib3
https://github.com/annotated-types/annotated-types
https://github.com/pypa/setuptools
https://github.com/pydantic/pydantic
https://github.com/pydantic/pydantic-core
https://github.com/geopython/pygeofilter


================================================================
Expand Down
5 changes: 2 additions & 3 deletions eodag/api/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -539,8 +539,8 @@ def list_product_types(
if product_type_id == GENERIC_PRODUCT_TYPE:
continue
config = self.product_types_config[product_type_id]
config["_id"] = product_type_id
if "alias" in config:
config["_id"] = product_type_id
product_type_id = config["alias"]
product_type = dict(ID=product_type_id, **config)
if product_type_id not in product_types:
Expand Down Expand Up @@ -1618,8 +1618,7 @@ def _prepare_search(
for p in self.list_product_types(
search_plugin.provider, fetch_providers=False
)
if p["ID"] == product_type
or ("_id" in p and p["_id"] == product_type)
if p["_id"] == product_type
][0],
**{"productType": product_type},
)
Expand Down
3 changes: 2 additions & 1 deletion eodag/plugins/apis/cds.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
DEFAULT_ITEMS_PER_PAGE,
DEFAULT_PAGE,
Annotated,
StreamResponse,
datetime_range,
deepcopy,
get_geometry_from_various,
Expand Down Expand Up @@ -403,7 +404,7 @@ def _stream_download_dict(
wait: int = DEFAULT_DOWNLOAD_WAIT,
timeout: int = DEFAULT_DOWNLOAD_TIMEOUT,
**kwargs: Union[str, bool, Dict[str, Any]],
) -> Dict[str, Any]:
) -> StreamResponse:
"""Returns dictionnary of :class:`~fastapi.responses.StreamingResponse` keyword-arguments.
It contains a generator to streamed download chunks and the response headers."""

Expand Down
7 changes: 4 additions & 3 deletions eodag/plugins/download/aws.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
HTTP_REQ_TIMEOUT,
USER_AGENT,
ProgressCallback,
StreamResponse,
flatten_top_directories,
get_bucket_name_and_prefix,
path_to_uri,
Expand Down Expand Up @@ -631,7 +632,7 @@ def _stream_download_dict(
wait: int = DEFAULT_DOWNLOAD_WAIT,
timeout: int = DEFAULT_DOWNLOAD_TIMEOUT,
**kwargs: Union[str, bool, Dict[str, Any]],
) -> Dict[str, Any]:
) -> StreamResponse:
r"""
Returns dictionnary of :class:`~fastapi.responses.StreamingResponse` keyword-arguments.
It contains a generator to streamed download chunks and the response headers.
Expand Down Expand Up @@ -725,11 +726,11 @@ def _stream_download_dict(
if assets_values[0].get("type", None):
headers["content-type"] = assets_values[0]["type"]

return dict(
return StreamResponse(
content=chain(iter([first_chunks_tuple]), chunks_tuples),
headers=headers,
)
return dict(
return StreamResponse(
content=stream_zip(chunks_tuples),
media_type="application/zip",
headers={
Expand Down
3 changes: 2 additions & 1 deletion eodag/plugins/download/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
DEFAULT_DOWNLOAD_TIMEOUT,
DEFAULT_DOWNLOAD_WAIT,
ProgressCallback,
StreamResponse,
sanitize,
uri_to_path,
)
Expand Down Expand Up @@ -150,7 +151,7 @@ def _stream_download_dict(
wait: int = DEFAULT_DOWNLOAD_WAIT,
timeout: int = DEFAULT_DOWNLOAD_TIMEOUT,
**kwargs: Union[str, bool, Dict[str, Any]],
) -> Dict[str, Any]:
) -> StreamResponse:
r"""
Base _stream_download_dict method. Not available, it must be defined for each plugin.
Expand Down
9 changes: 5 additions & 4 deletions eodag/plugins/download/http.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
HTTP_REQ_TIMEOUT,
USER_AGENT,
ProgressCallback,
StreamResponse,
flatten_top_directories,
parse_header,
path_to_uri,
Expand Down Expand Up @@ -535,7 +536,7 @@ def _stream_download_dict(
wait: int = DEFAULT_DOWNLOAD_WAIT,
timeout: int = DEFAULT_DOWNLOAD_TIMEOUT,
**kwargs: Union[str, bool, Dict[str, Any]],
) -> Dict[str, Any]:
) -> StreamResponse:
r"""
Returns dictionnary of :class:`~fastapi.responses.StreamingResponse` keyword-arguments.
It contains a generator to streamed download chunks and the response headers.
Expand Down Expand Up @@ -584,7 +585,7 @@ def _stream_download_dict(
"type"
]

return dict(
return StreamResponse(
content=chain(iter([first_chunks_tuple]), chunks_tuples),
headers=assets_values[0].headers,
)
Expand All @@ -595,7 +596,7 @@ def _stream_download_dict(
if "title" in product.properties
else sanitize(product.properties.get("id", "download"))
)
return dict(
return StreamResponse(
content=stream_zip(chunks_tuples),
media_type="application/zip",
headers={
Expand All @@ -612,7 +613,7 @@ def _stream_download_dict(
# start reading chunks to set product.headers
first_chunk = next(chunks)

return dict(
return StreamResponse(
content=chain(iter([first_chunk]), chunks),
headers=product.headers,
)
Expand Down
10 changes: 5 additions & 5 deletions eodag/plugins/search/creodias_s3.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
from eodag.config import PluginConfig
from eodag.plugins.authentication.aws_auth import AwsAuth
from eodag.plugins.search.qssearch import QueryStringSearch
from eodag.utils import guess_file_type
from eodag.utils.exceptions import AuthenticationError, MisconfiguredError, RequestError

DATA_EXTENSIONS = ["jp2", "tiff", "nc", "grib"]
Expand Down Expand Up @@ -75,7 +76,7 @@ def _update_assets(product: EOProduct, config: PluginConfig, auth: AwsAuth):
endpoint_url=config.base_uri,
**auth_dict,
)
logger.debug(f"Listing assets in {prefix}")
logger.debug("Listing assets in %s", prefix)
product.assets = AssetsDict(product)
for asset in auth.s3_client.list_objects(
Bucket=config.s3_bucket, Prefix=prefix, MaxKeys=300
Expand All @@ -96,6 +97,8 @@ def _update_assets(product: EOProduct, config: PluginConfig, auth: AwsAuth):
"roles": [role],
"href": f"s3://{config.s3_bucket}/{asset['Key']}",
}
if mime_type := guess_file_type(asset["Key"]):
product.assets[asset_basename]["type"] = mime_type
# update driver
product.driver = product.get_driver()

Expand All @@ -104,10 +107,7 @@ def _update_assets(product: EOProduct, config: PluginConfig, auth: AwsAuth):
raise AuthenticationError(
f"Authentication failed on {config.base_uri} s3"
) from e
else:
raise RequestError(
"assets for product %s could not be found", prefix
) from e
raise RequestError(f"assets for product {prefix} could not be found") from e


class CreodiasS3Search(QueryStringSearch):
Expand Down
52 changes: 22 additions & 30 deletions eodag/resources/stac.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
# limitations under the License.

stac_version: 1.0.0
stac_api_version: 1.0.0-rc.3
stac_api_version: 1.0.0

# Capabilities ----------------------------------------------------------------

Expand Down Expand Up @@ -53,13 +53,26 @@ landing_page:
# http://docs.opengeospatial.org/is/17-069r3/17-069r3.html#_declaration_of_conformance_classes
conformance:
conformsTo:
- https://api.stacspec.org/v1.0.0-rc.3/core
- https://api.stacspec.org/v1.0.0-rc.3/item-search
- https://api.stacspec.org/v1.0.0-rc.3/ogcapi-features
- https://api.stacspec.org/v1.0.0-rc.3/collections
- https://api.stacspec.org/v1.0.0/core
- https://api.stacspec.org/v1.0.0/item-search
- https://api.stacspec.org/v1.0.0/item-search#query
- https://api.stacspec.org/v1.0.0/item-search#filter
- https://api.stacspec.org/v1.0.0/item-search#sort
- https://api.stacspec.org/v1.0.0/ogcapi-features
- https://api.stacspec.org/v1.0.0/ogcapi-features#query
- https://api.stacspec.org/v1.0.0/ogcapi-features#sort
- https://api.stacspec.org/v1.0.0/collections
- http://www.opengis.net/spec/ogcapi-features-1/1.0/conf/core
- http://www.opengis.net/spec/ogcapi-features-1/1.0/conf/oas30
- http://www.opengis.net/spec/ogcapi-features-1/1.0/conf/geojson
- http://www.opengis.net/spec/ogcapi-features-3/1.0/conf/filter
- http://www.opengis.net/spec/ogcapi-features-3/1.0/conf/features-filter
- http://www.opengis.net/spec/cql2/1.0/conf/cql2-text
- http://www.opengis.net/spec/cql2/1.0/conf/cql2-json
- http://www.opengis.net/spec/cql2/1.0/conf/basic-cql2
- http://www.opengis.net/spec/cql2/1.0/conf/basic-spatial-operators
- http://www.opengis.net/spec/cql2/1.0/conf/temporal-operators
- http://www.opengis.net/spec/cql2/1.0/conf/advanced-comparison-operators

# https://stacspec.org/STAC-api.html#operation/getCollections
collections:
Expand Down Expand Up @@ -147,20 +160,12 @@ items:
- rel: parent
title: "{catalog[id]}"
href: "{catalog[url]}"
# implement next/prev page links
# https://github.com/radiantearth/stac-spec/blob/master/api-spec/api-spec.md#paging-extension
- rel: next
href: '$.search_results.next'
title: Next page
type: application/geo+json
method: '$.search_results.method'
body: '$.search_results.body'
# time and date when the response was generated
timeStamp: '$.search_results.timeStamp'
timeStamp: '$.timeStamp'
# count request result
numberMatched: '$.search_results.numberMatched'
numberMatched: '$.numberMatched'
# len(features)
numberReturned: '$.search_results.numberReturned'
numberReturned: '$.numberReturned'

# https://stacspec.org/STAC-api.html#operation/getFeature
item:
Expand Down Expand Up @@ -216,20 +221,7 @@ item:
- rel: collection
title: "{item[collection]}"
href: "{catalog[url]}"
assets:
downloadLink:
title: 'Download link'
href: "{catalog[url]}/items/{item[id]}/download"
# https://github.com/radiantearth/stac-spec/blob/master/item-spec/item-spec.md#media-types
type: 'application/zip'
_dc_qs: '$.product.properties._dc_qs'
thumbnail:
title: 'Thumbnail'
href: '$.product.properties.quicklook'
type: 'image/jpeg'
role: thumbnail
# https://github.com/radiantearth/stac-spec/blob/master/item-spec/item-spec.md#media-types
origin_assets: '$.product.assets'

# product properties not needed in items
metadata_ignore:
- title
Expand Down

0 comments on commit 5901a6e

Please sign in to comment.