Skip to content

Commit 49de0ce

Browse files
Patch/fix doc urls in landing (#673)
* fix Documentation URL in landing page * update changelog
1 parent f542278 commit 49de0ce

File tree

4 files changed

+192
-6
lines changed

4 files changed

+192
-6
lines changed

CHANGES.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@
22

33
## [Unreleased]
44

5+
## [2.5.5] - 2024-04-24
6+
7+
### Fixed
8+
9+
* Fix `service-doc` and `service-desc` url in landing page when using router prefix
10+
511
## [2.5.4] - 2024-04-24
612

713
### Fixed

stac_fastapi/api/tests/conftest.py

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
from datetime import datetime
2+
from typing import List, Optional, Union
3+
4+
import pytest
5+
from stac_pydantic import Collection, Item
6+
from stac_pydantic.api.utils import link_factory
7+
8+
from stac_fastapi.types import core, stac
9+
from stac_fastapi.types.core import NumType
10+
from stac_fastapi.types.search import BaseSearchPostRequest
11+
12+
collection_links = link_factory.CollectionLinks("/", "test").create_links()
13+
item_links = link_factory.ItemLinks("/", "test", "test").create_links()
14+
15+
16+
@pytest.fixture
17+
def _collection():
18+
return Collection(
19+
id="test_collection",
20+
title="Test Collection",
21+
description="A test collection",
22+
keywords=["test"],
23+
license="proprietary",
24+
extent={
25+
"spatial": {"bbox": [[-180, -90, 180, 90]]},
26+
"temporal": {"interval": [["2000-01-01T00:00:00Z", None]]},
27+
},
28+
links=collection_links,
29+
)
30+
31+
32+
@pytest.fixture
33+
def collection(_collection: Collection):
34+
return _collection.json()
35+
36+
37+
@pytest.fixture
38+
def collection_dict(_collection: Collection):
39+
return _collection.dict()
40+
41+
42+
@pytest.fixture
43+
def _item():
44+
return Item(
45+
id="test_item",
46+
type="Feature",
47+
geometry={"type": "Point", "coordinates": [0, 0]},
48+
bbox=[-180, -90, 180, 90],
49+
properties={"datetime": "2000-01-01T00:00:00Z"},
50+
links=item_links,
51+
assets={},
52+
)
53+
54+
55+
@pytest.fixture
56+
def item(_item: Item):
57+
return _item.json()
58+
59+
60+
@pytest.fixture
61+
def item_dict(_item: Item):
62+
return _item.dict()
63+
64+
65+
@pytest.fixture
66+
def TestCoreClient(collection_dict, item_dict):
67+
class CoreClient(core.BaseCoreClient):
68+
def post_search(
69+
self, search_request: BaseSearchPostRequest, **kwargs
70+
) -> stac.ItemCollection:
71+
return stac.ItemCollection(
72+
type="FeatureCollection", features=[stac.Item(**item_dict)]
73+
)
74+
75+
def get_search(
76+
self,
77+
collections: Optional[List[str]] = None,
78+
ids: Optional[List[str]] = None,
79+
bbox: Optional[List[NumType]] = None,
80+
intersects: Optional[str] = None,
81+
datetime: Optional[Union[str, datetime]] = None,
82+
limit: Optional[int] = 10,
83+
**kwargs,
84+
) -> stac.ItemCollection:
85+
return stac.ItemCollection(
86+
type="FeatureCollection", features=[stac.Item(**item_dict)]
87+
)
88+
89+
def get_item(self, item_id: str, collection_id: str, **kwargs) -> stac.Item:
90+
return stac.Item(**item_dict)
91+
92+
def all_collections(self, **kwargs) -> stac.Collections:
93+
return stac.Collections(
94+
collections=[stac.Collection(**collection_dict)],
95+
links=[
96+
{"href": "test", "rel": "root"},
97+
{"href": "test", "rel": "self"},
98+
{"href": "test", "rel": "parent"},
99+
],
100+
)
101+
102+
def get_collection(self, collection_id: str, **kwargs) -> stac.Collection:
103+
return stac.Collection(**collection_dict)
104+
105+
def item_collection(
106+
self,
107+
collection_id: str,
108+
bbox: Optional[List[Union[float, int]]] = None,
109+
datetime: Optional[Union[str, datetime]] = None,
110+
limit: int = 10,
111+
token: str = None,
112+
**kwargs,
113+
) -> stac.ItemCollection:
114+
return stac.ItemCollection(
115+
type="FeatureCollection", features=[stac.Item(**item_dict)]
116+
)
117+
118+
return CoreClient
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import urllib
2+
from typing import Optional
3+
4+
import pytest
5+
from fastapi import APIRouter
6+
from starlette.testclient import TestClient
7+
8+
from stac_fastapi.api.app import StacApi
9+
from stac_fastapi.types.config import ApiSettings
10+
11+
12+
def get_link(landing_page, rel_type, method: Optional[str] = None):
13+
return next(
14+
filter(
15+
lambda link: link["rel"] == rel_type
16+
and (not method or link.get("method") == method),
17+
landing_page["links"],
18+
),
19+
None,
20+
)
21+
22+
23+
@pytest.mark.parametrize("prefix", ["", "/a_prefix"])
24+
def test_api_prefix(TestCoreClient, prefix):
25+
api_settings = ApiSettings(
26+
openapi_url=f"{prefix}/api",
27+
docs_url=f"{prefix}/api.html",
28+
)
29+
30+
api = StacApi(
31+
settings=api_settings,
32+
client=TestCoreClient(),
33+
router=APIRouter(prefix=prefix),
34+
)
35+
36+
with TestClient(api.app, base_url="http://stac.io") as client:
37+
landing = client.get(f"{prefix}/")
38+
assert landing.status_code == 200, landing.json()
39+
40+
service_doc = client.get(f"{prefix}/api.html")
41+
assert service_doc.status_code == 200, service_doc.text
42+
43+
service_desc = client.get(f"{prefix}/api")
44+
assert service_desc.status_code == 200, service_desc.json()
45+
46+
conformance = client.get(f"{prefix}/conformance")
47+
assert conformance.status_code == 200, conformance.json()
48+
49+
link_tests = [
50+
("root", "application/json", "/"),
51+
("conformance", "application/json", "/conformance"),
52+
("service-doc", "text/html", "/api.html"),
53+
("service-desc", "application/vnd.oai.openapi+json;version=3.0", "/api"),
54+
]
55+
56+
for rel_type, expected_media_type, expected_path in link_tests:
57+
link = get_link(landing.json(), rel_type)
58+
59+
assert link is not None, f"Missing {rel_type} link in landing page"
60+
assert link.get("type") == expected_media_type
61+
62+
link_path = urllib.parse.urlsplit(link.get("href")).path
63+
assert link_path == prefix + expected_path
64+
65+
resp = client.get(prefix + expected_path)
66+
assert resp.status_code == 200

stac_fastapi/types/stac_fastapi/types/core.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -404,9 +404,7 @@ def landing_page(self, **kwargs) -> stac_types.LandingPage:
404404
"rel": "service-desc",
405405
"type": "application/vnd.oai.openapi+json;version=3.0",
406406
"title": "OpenAPI service description",
407-
"href": urljoin(
408-
str(request.base_url), request.app.openapi_url.lstrip("/")
409-
),
407+
"href": str(request.url_for("openapi")),
410408
}
411409
)
412410

@@ -416,9 +414,7 @@ def landing_page(self, **kwargs) -> stac_types.LandingPage:
416414
"rel": "service-doc",
417415
"type": "text/html",
418416
"title": "OpenAPI service documentation",
419-
"href": urljoin(
420-
str(request.base_url), request.app.docs_url.lstrip("/")
421-
),
417+
"href": str(request.url_for("swagger_ui_html")),
422418
}
423419
)
424420

0 commit comments

Comments
 (0)