1+ import json
2+ from collections import defaultdict
13from contextlib import asynccontextmanager
2- from pathlib import Path
34from typing import Any , AsyncIterator , TypedDict
45
5- import tomllib
6- from fastapi import FastAPI
6+ import pystac . utils
7+ from fastapi import FastAPI , HTTPException
78from rustac import DuckdbClient
89
910import stac_fastapi .api .models
1213
1314from .client import Client
1415from .search import SearchGetRequest , SearchPostRequest
15- from .settings import Settings , StacFastapiGeoparquetSettings
16+ from .settings import Settings
17+
18+ GEOPARQUET_MEDIA_TYPE = "application/vnd.apache.parquet"
1619
1720GetSearchRequestModel = stac_fastapi .api .models .create_request_model (
1821 model_name = "SearchGetRequest" ,
@@ -40,7 +43,7 @@ class State(TypedDict):
4043 collections : dict [str , dict [str , Any ]]
4144 """A mapping of collection id to collection."""
4245
43- hrefs : dict [str , str ]
46+ hrefs : dict [str , list [ str ] ]
4447 """A mapping of collection id to geoparquet href."""
4548
4649
@@ -57,41 +60,36 @@ def create(
5760 stac_fastapi_description = "A stac-fastapi server backend by stac-geoparquet" ,
5861 )
5962
60- if settings .stac_fastapi_geoparquet_href .endswith (".toml" ):
61- with open (settings .stac_fastapi_geoparquet_href , "rb" ) as f :
62- data = tomllib .load (f )
63- stac_fastapi_geoparquet_settings = StacFastapiGeoparquetSettings .model_validate (
64- data
65- )
66- config_directory = Path (settings .stac_fastapi_geoparquet_href ).parent
67- hrefs = []
68- for href in stac_fastapi_geoparquet_settings .hrefs :
69- if Path (href ).is_absolute ():
70- hrefs .append (href )
71- else :
72- hrefs .append (str (config_directory .joinpath (href ).resolve ()))
73- else :
74- hrefs = [settings .stac_fastapi_geoparquet_href ]
63+ with open (settings .stac_fastapi_collections_href , "rb" ) as f :
64+ collections = json .load (f )
7565
7666 @asynccontextmanager
7767 async def lifespan (app : FastAPI ) -> AsyncIterator [State ]:
7868 client = app .extra ["duckdb_client" ]
79- collections = dict ()
80- href_dict = dict ()
81- for href in hrefs :
82- for collection in client .get_collections (href ):
83- if collection ["id" ] in collections :
84- raise ValueError (
85- "cannot have two items in the same collection in different "
86- "geoparquet files"
69+ settings : Settings = app .extra ["settings" ]
70+ collections = app .extra ["collections" ]
71+ collection_dict = dict ()
72+ hrefs = defaultdict (list )
73+ for collection in collections :
74+ if collection ["id" ] in collection_dict :
75+ raise HTTPException (
76+ 500 , f"two collections with the same id: { collection .id } "
77+ )
78+ else :
79+ collection_dict [collection ["id" ]] = collection
80+ for key , asset in collection ["assets" ].items ():
81+ if asset ["type" ] == GEOPARQUET_MEDIA_TYPE :
82+ hrefs [collection ["id" ]].append (
83+ pystac .utils .make_absolute_href (
84+ asset ["href" ],
85+ settings .stac_fastapi_collections_href ,
86+ start_is_dir = False ,
87+ )
8788 )
88- else :
89- collections [collection ["id" ]] = collection
90- href_dict [collection ["id" ]] = href
9189 yield {
9290 "client" : client ,
93- "collections" : collections ,
94- "hrefs" : href_dict ,
91+ "collections" : collection_dict ,
92+ "hrefs" : hrefs ,
9593 }
9694
9795 api = StacApi (
@@ -102,6 +100,8 @@ async def lifespan(app: FastAPI) -> AsyncIterator[State]:
102100 openapi_url = settings .openapi_url ,
103101 docs_url = settings .docs_url ,
104102 redoc_url = settings .docs_url ,
103+ settings = settings ,
104+ collections = collections ,
105105 duckdb_client = duckdb_client ,
106106 ),
107107 search_get_request_model = GetSearchRequestModel ,
0 commit comments