Skip to content

Commit 47eac1f

Browse files
feature: add root_path settings to the default fastapi application (#769)
1 parent 3a9aae6 commit 47eac1f

File tree

4 files changed

+67
-0
lines changed

4 files changed

+67
-0
lines changed

CHANGES.md

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
* Add `numberMatched` and `numberReturned` properties in `types.stac.ItemCollection` model
1212
* Add `numberMatched` and `numberReturned` properties in `types.stac.Collections` model
13+
* Add `root_path` to `stac_fastapi.types.config.ApiSettings` and use it in the default FastAPI application
1314
* Add `python3.13` support
1415

1516
## Changed

stac_fastapi/api/stac_fastapi/api/app.py

+1
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ class StacApi:
7777
openapi_url=self.settings.openapi_url,
7878
docs_url=self.settings.docs_url,
7979
redoc_url=None,
80+
root_path=self.settings.root_path,
8081
),
8182
takes_self=True,
8283
),

stac_fastapi/api/tests/test_app_prefix.py

+64
Original file line numberDiff line numberDiff line change
@@ -144,3 +144,67 @@ def test_async_api_prefix(AsyncTestCoreClient, prefix):
144144

145145
resp = client.get(prefix + expected_path)
146146
assert resp.status_code == 200
147+
148+
149+
@pytest.mark.parametrize("prefix", ["", "/a_prefix"])
150+
def test_api_prefix_with_root_path(TestCoreClient, prefix):
151+
api_settings = ApiSettings(
152+
openapi_url=f"{prefix}/api", docs_url=f"{prefix}/api.html", root_path="/api/v1"
153+
)
154+
155+
api = StacApi(
156+
settings=api_settings,
157+
client=TestCoreClient(),
158+
router=APIRouter(prefix=prefix),
159+
)
160+
161+
prefix = "/api/v1" + prefix
162+
with TestClient(api.app, base_url="http://stac.io", root_path="/api/v1") as client:
163+
landing = client.get(f"{prefix}/")
164+
assert landing.status_code == 200, landing.json()
165+
print(landing.text)
166+
service_doc = client.get(f"{prefix}/api.html")
167+
assert service_doc.status_code == 200, service_doc.text
168+
169+
service_desc = client.get(f"{prefix}/api")
170+
assert service_desc.status_code == 200, service_desc.json()
171+
172+
conformance = client.get(f"{prefix}/conformance")
173+
assert conformance.status_code == 200, conformance.json()
174+
175+
# NOTE: The collections/collection/items/item links do not have the prefix
176+
# because they are created in the fixtures
177+
collections = client.get(f"{prefix}/collections")
178+
assert collections.status_code == 200, collections.json()
179+
collection_id = collections.json()["collections"][0]["id"]
180+
181+
collection = client.get(f"{prefix}/collections/{collection_id}")
182+
assert collection.status_code == 200, collection.json()
183+
184+
items = client.get(f"{prefix}/collections/{collection_id}/items")
185+
assert items.status_code == 200, items.json()
186+
187+
item_id = items.json()["features"][0]["id"]
188+
item = client.get(f"{prefix}/collections/{collection_id}/items/{item_id}")
189+
assert item.status_code == 200, item.json()
190+
191+
link_tests = [
192+
("root", "application/json", "/"),
193+
("conformance", "application/json", "/conformance"),
194+
("data", "application/json", "/collections"),
195+
("search", "application/geo+json", "/search"),
196+
("service-doc", "text/html", "/api.html"),
197+
("service-desc", "application/vnd.oai.openapi+json;version=3.0", "/api"),
198+
]
199+
200+
for rel_type, expected_media_type, expected_path in link_tests:
201+
link = get_link(landing.json(), rel_type)
202+
203+
assert link is not None, f"Missing {rel_type} link in landing page"
204+
assert link.get("type") == expected_media_type
205+
206+
link_path = urllib.parse.urlsplit(link.get("href")).path
207+
assert link_path == prefix + expected_path
208+
209+
resp = client.get(prefix + expected_path)
210+
assert resp.status_code == 200

stac_fastapi/types/stac_fastapi/types/config.py

+1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ class ApiSettings(BaseSettings):
3131

3232
openapi_url: str = "/api"
3333
docs_url: str = "/api.html"
34+
root_path: str = ""
3435

3536
model_config = SettingsConfigDict(env_file=".env", extra="allow")
3637

0 commit comments

Comments
 (0)