Skip to content

Commit 6cbea93

Browse files
committed
add item collections routes etc
1 parent 2e14974 commit 6cbea93

File tree

4 files changed

+144
-11
lines changed

4 files changed

+144
-11
lines changed

stac_fastapi/core/stac_fastapi/core/core.py

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
from stac_fastapi.core.base_database_logic import BaseDatabaseLogic
2424
from stac_fastapi.core.base_settings import ApiBaseSettings
2525
from stac_fastapi.core.datetime_utils import format_datetime_range
26-
from stac_fastapi.core.models import Catalog
2726
from stac_fastapi.core.models.links import PagingLinks
2827
from stac_fastapi.core.redis_utils import redis_pagination_links
2928
from stac_fastapi.core.serializers import (
@@ -94,6 +93,17 @@ class CoreClient(AsyncBaseCoreClient):
9493
title: str = attr.ib(default="stac-fastapi")
9594
description: str = attr.ib(default="stac-fastapi")
9695

96+
def extension_is_enabled(self, extension_name: str) -> bool:
97+
"""Check if an extension is enabled by checking self.extensions.
98+
99+
Args:
100+
extension_name: Name of the extension class to check for.
101+
102+
Returns:
103+
True if the extension is in self.extensions, False otherwise.
104+
"""
105+
return any(ext.__class__.__name__ == extension_name for ext in self.extensions)
106+
97107
def _landing_page(
98108
self,
99109
base_url: str,
@@ -148,24 +158,16 @@ def _landing_page(
148158
)
149159
return landing_page
150160

151-
async def landing_page(self, **kwargs) -> Union[stac_types.LandingPage, Catalog]:
161+
async def landing_page(self, **kwargs) -> stac_types.LandingPage:
152162
"""Landing page.
153163
154164
Called with `GET /`.
155165
156166
Returns:
157-
API landing page, serving as an entry point to the API, or root catalog if CatalogsExtension is enabled.
167+
API landing page, serving as an entry point to the API.
158168
"""
159169
request: Request = kwargs["request"]
160170

161-
# If CatalogsExtension is enabled, return root catalog instead of landing page
162-
if self.extension_is_enabled("CatalogsExtension"):
163-
# Find the CatalogsExtension and call its catalogs method
164-
for extension in self.extensions:
165-
if extension.__class__.__name__ == "CatalogsExtension":
166-
return await extension.catalogs(request)
167-
168-
# Normal landing page logic
169171
base_url = get_base_url(request)
170172
landing_page = self._landing_page(
171173
base_url=base_url,
@@ -223,6 +225,16 @@ async def landing_page(self, **kwargs) -> Union[stac_types.LandingPage, Catalog]
223225
]
224226
)
225227

228+
if self.extension_is_enabled("CatalogsExtension"):
229+
landing_page["links"].append(
230+
{
231+
"rel": "catalogs",
232+
"type": "application/json",
233+
"title": "Catalogs",
234+
"href": urljoin(base_url, "catalogs"),
235+
}
236+
)
237+
226238
# Add OpenAPI URL
227239
landing_page["links"].append(
228240
{

stac_fastapi/core/stac_fastapi/core/extensions/catalogs.py

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,42 @@ def register(self, app: FastAPI, settings=None) -> None:
8484
tags=["Catalogs"],
8585
)
8686

87+
# Add endpoint for getting a specific collection in a catalog
88+
self.router.add_api_route(
89+
path="/catalogs/{catalog_id}/collections/{collection_id}",
90+
endpoint=self.get_catalog_collection,
91+
methods=["GET"],
92+
response_model=stac_types.Collection,
93+
response_class=self.response_class,
94+
summary="Get Catalog Collection",
95+
description="Get a specific collection from a catalog.",
96+
tags=["Catalogs"],
97+
)
98+
99+
# Add endpoint for getting items in a collection within a catalog
100+
self.router.add_api_route(
101+
path="/catalogs/{catalog_id}/collections/{collection_id}/items",
102+
endpoint=self.get_catalog_collection_items,
103+
methods=["GET"],
104+
response_model=stac_types.ItemCollection,
105+
response_class=self.response_class,
106+
summary="Get Catalog Collection Items",
107+
description="Get items from a collection in a catalog.",
108+
tags=["Catalogs"],
109+
)
110+
111+
# Add endpoint for getting a specific item in a collection within a catalog
112+
self.router.add_api_route(
113+
path="/catalogs/{catalog_id}/collections/{collection_id}/items/{item_id}",
114+
endpoint=self.get_catalog_collection_item,
115+
methods=["GET"],
116+
response_model=stac_types.Item,
117+
response_class=self.response_class,
118+
summary="Get Catalog Collection Item",
119+
description="Get a specific item from a collection in a catalog.",
120+
tags=["Catalogs"],
121+
)
122+
87123
app.include_router(self.router, tags=["Catalogs"])
88124

89125
async def catalogs(self, request: Request) -> Catalog:
@@ -253,3 +289,82 @@ async def get_catalog_collections(
253289
raise HTTPException(
254290
status_code=404, detail=f"Catalog {catalog_id} not found"
255291
)
292+
293+
async def get_catalog_collection(
294+
self, catalog_id: str, collection_id: str, request: Request
295+
) -> stac_types.Collection:
296+
"""Get a specific collection from a catalog.
297+
298+
Args:
299+
catalog_id: The ID of the catalog.
300+
collection_id: The ID of the collection.
301+
request: Request object.
302+
303+
Returns:
304+
The requested collection.
305+
"""
306+
# Verify the catalog exists
307+
try:
308+
await self.client.database.find_catalog(catalog_id)
309+
except Exception:
310+
raise HTTPException(
311+
status_code=404, detail=f"Catalog {catalog_id} not found"
312+
)
313+
314+
# Delegate to the core client's get_collection method
315+
return await self.client.get_collection(
316+
collection_id=collection_id, request=request
317+
)
318+
319+
async def get_catalog_collection_items(
320+
self, catalog_id: str, collection_id: str, request: Request
321+
) -> stac_types.ItemCollection:
322+
"""Get items from a collection in a catalog.
323+
324+
Args:
325+
catalog_id: The ID of the catalog.
326+
collection_id: The ID of the collection.
327+
request: Request object.
328+
329+
Returns:
330+
ItemCollection containing items from the collection.
331+
"""
332+
# Verify the catalog exists
333+
try:
334+
await self.client.database.find_catalog(catalog_id)
335+
except Exception:
336+
raise HTTPException(
337+
status_code=404, detail=f"Catalog {catalog_id} not found"
338+
)
339+
340+
# Delegate to the core client's item_collection method
341+
return await self.client.item_collection(
342+
collection_id=collection_id, request=request
343+
)
344+
345+
async def get_catalog_collection_item(
346+
self, catalog_id: str, collection_id: str, item_id: str, request: Request
347+
) -> stac_types.Item:
348+
"""Get a specific item from a collection in a catalog.
349+
350+
Args:
351+
catalog_id: The ID of the catalog.
352+
collection_id: The ID of the collection.
353+
item_id: The ID of the item.
354+
request: Request object.
355+
356+
Returns:
357+
The requested item.
358+
"""
359+
# Verify the catalog exists
360+
try:
361+
await self.client.database.find_catalog(catalog_id)
362+
except Exception:
363+
raise HTTPException(
364+
status_code=404, detail=f"Catalog {catalog_id} not found"
365+
)
366+
367+
# Delegate to the core client's get_item method
368+
return await self.client.get_item(
369+
item_id=item_id, collection_id=collection_id, request=request
370+
)

stac_fastapi/elasticsearch/stac_fastapi/elasticsearch/app.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,9 @@
214214
landing_page_id=os.getenv("STAC_FASTAPI_LANDING_PAGE_ID", "stac-fastapi"),
215215
),
216216
settings=settings,
217+
conformance_classes=[
218+
"https://api.stacspec.org/v1.0.0-beta.1/catalogs",
219+
],
217220
)
218221
extensions.append(catalogs_extension)
219222

stac_fastapi/opensearch/stac_fastapi/opensearch/app.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,9 @@
213213
landing_page_id=os.getenv("STAC_FASTAPI_LANDING_PAGE_ID", "stac-fastapi"),
214214
),
215215
settings=settings,
216+
conformance_classes=[
217+
"https://api.stacspec.org/v1.0.0-beta.1/catalogs",
218+
],
216219
)
217220
extensions.append(catalogs_extension)
218221

0 commit comments

Comments
 (0)