Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 16 additions & 6 deletions pygeoapi/api/stac.py
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ def landing_page(api: API,
'rel': 'search',
'type': FORMAT_TYPES[F_JSON],
'title': l10n.translate('STAC API search', request.locale),
'href': f"{api.base_url}/stac-api//search?f={F_JSON}"
'href': f"{api.base_url}/stac-api/search?f={F_JSON}"
}]

return headers, status, to_json(content, api.pretty_print)
Expand Down Expand Up @@ -379,9 +379,17 @@ def search(api: API, request: Union[APIRequest, Any]) -> Tuple[dict, int, str]:
geom = from_geojson(json.dumps(feature['geometry']))
feature['bbox'] = geom.bounds

for la in ['links', 'assets']:
if feature.get(la) is None:
feature[la] = []
if feature.get('links') is None:
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the content model that this update is based on? Is properties.content.links and properties.content.assets part of STAC proper?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. As can be seen in the STAC Spec:

image

links is a list, and assets is a dict.

feature['links'] = feature\
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. I am seeing:

                        .get('properties', {})\
                        .get('content', {})\
                        .get('links', [])

A STAC Item indeed has links and assets, but they are at the root of the STAC item, not in an object called properties.content.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed. This is quirk of the pgSTAC back-end. Please see #2355 for a more detailed explanation. I can also add a comment here pointing to that to keep the context near the code.

Also open to alternative approaches to address this discrepancy.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this case, I would suggest removing this given it is backend specific. You can work around this by adding your own feature provider plugin which reads PgSTAC and returns items such that the STAC code in pygeoapi is reading content on the absence of a backend specific data model.

.get('properties', {})\
.get('content', {})\
.get('links', [])

if feature.get('assets') is None:
feature['assets'] = feature\
.get('properties', {})\
.get('content', {})\
.get('assets', {})

stac_api_response['numberReturned'] = len(stac_api_response['features'])

Expand Down Expand Up @@ -488,18 +496,20 @@ def get_temporal(feature: dict) -> dict:
if datetime_ is None and None not in [start_datetime, end_datetime]:
LOGGER.debug('Temporal range partially exists')
elif datetime_ is not None:
value['datetime'] = datetime_
LOGGER.debug('Temporal instant exists')

LOGGER.debug('Attempting to derive temporal from GeoJSON feature')
LOGGER.debug(feature)
if feature.get('time') is not None:
if value.get('datetime') is None and feature.get('time') is not None:
if feature['time'].get('timestamp') is not None:
value['datetime'] = feature['time']['timestamp']
if feature['time'].get('interval') is not None:
value['start_datetime'] = feature['time']['interval'][0]
value['end_datetime'] = feature['time']['interval'][1]

if feature['properties'].get('created') is not None:
if value.get('datetime') is None \
and feature['properties'].get('created') is not None:
value['datetime'] = feature['properties']['created']

if not value:
Expand Down
Loading