Skip to content

Commit

Permalink
Patch/fix doc urls in landing (#673)
Browse files Browse the repository at this point in the history
* fix Documentation URL in landing page

* update changelog
  • Loading branch information
vincentsarago authored Apr 25, 2024
1 parent f542278 commit 49de0ce
Show file tree
Hide file tree
Showing 4 changed files with 192 additions and 6 deletions.
6 changes: 6 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@

## [Unreleased]

## [2.5.5] - 2024-04-24

### Fixed

* Fix `service-doc` and `service-desc` url in landing page when using router prefix

## [2.5.4] - 2024-04-24

### Fixed
Expand Down
118 changes: 118 additions & 0 deletions stac_fastapi/api/tests/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
from datetime import datetime
from typing import List, Optional, Union

import pytest
from stac_pydantic import Collection, Item
from stac_pydantic.api.utils import link_factory

from stac_fastapi.types import core, stac
from stac_fastapi.types.core import NumType
from stac_fastapi.types.search import BaseSearchPostRequest

collection_links = link_factory.CollectionLinks("/", "test").create_links()
item_links = link_factory.ItemLinks("/", "test", "test").create_links()


@pytest.fixture
def _collection():
return Collection(
id="test_collection",
title="Test Collection",
description="A test collection",
keywords=["test"],
license="proprietary",
extent={
"spatial": {"bbox": [[-180, -90, 180, 90]]},
"temporal": {"interval": [["2000-01-01T00:00:00Z", None]]},
},
links=collection_links,
)


@pytest.fixture
def collection(_collection: Collection):
return _collection.json()


@pytest.fixture
def collection_dict(_collection: Collection):
return _collection.dict()


@pytest.fixture
def _item():
return Item(
id="test_item",
type="Feature",
geometry={"type": "Point", "coordinates": [0, 0]},
bbox=[-180, -90, 180, 90],
properties={"datetime": "2000-01-01T00:00:00Z"},
links=item_links,
assets={},
)


@pytest.fixture
def item(_item: Item):
return _item.json()


@pytest.fixture
def item_dict(_item: Item):
return _item.dict()


@pytest.fixture
def TestCoreClient(collection_dict, item_dict):
class CoreClient(core.BaseCoreClient):
def post_search(
self, search_request: BaseSearchPostRequest, **kwargs
) -> stac.ItemCollection:
return stac.ItemCollection(
type="FeatureCollection", features=[stac.Item(**item_dict)]
)

def get_search(
self,
collections: Optional[List[str]] = None,
ids: Optional[List[str]] = None,
bbox: Optional[List[NumType]] = None,
intersects: Optional[str] = None,
datetime: Optional[Union[str, datetime]] = None,
limit: Optional[int] = 10,
**kwargs,
) -> stac.ItemCollection:
return stac.ItemCollection(
type="FeatureCollection", features=[stac.Item(**item_dict)]
)

def get_item(self, item_id: str, collection_id: str, **kwargs) -> stac.Item:
return stac.Item(**item_dict)

def all_collections(self, **kwargs) -> stac.Collections:
return stac.Collections(
collections=[stac.Collection(**collection_dict)],
links=[
{"href": "test", "rel": "root"},
{"href": "test", "rel": "self"},
{"href": "test", "rel": "parent"},
],
)

def get_collection(self, collection_id: str, **kwargs) -> stac.Collection:
return stac.Collection(**collection_dict)

def item_collection(
self,
collection_id: str,
bbox: Optional[List[Union[float, int]]] = None,
datetime: Optional[Union[str, datetime]] = None,
limit: int = 10,
token: str = None,
**kwargs,
) -> stac.ItemCollection:
return stac.ItemCollection(
type="FeatureCollection", features=[stac.Item(**item_dict)]
)

return CoreClient
66 changes: 66 additions & 0 deletions stac_fastapi/api/tests/test_app_prefix.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import urllib
from typing import Optional

import pytest
from fastapi import APIRouter
from starlette.testclient import TestClient

from stac_fastapi.api.app import StacApi
from stac_fastapi.types.config import ApiSettings


def get_link(landing_page, rel_type, method: Optional[str] = None):
return next(
filter(
lambda link: link["rel"] == rel_type
and (not method or link.get("method") == method),
landing_page["links"],
),
None,
)


@pytest.mark.parametrize("prefix", ["", "/a_prefix"])
def test_api_prefix(TestCoreClient, prefix):
api_settings = ApiSettings(
openapi_url=f"{prefix}/api",
docs_url=f"{prefix}/api.html",
)

api = StacApi(
settings=api_settings,
client=TestCoreClient(),
router=APIRouter(prefix=prefix),
)

with TestClient(api.app, base_url="http://stac.io") as client:
landing = client.get(f"{prefix}/")
assert landing.status_code == 200, landing.json()

service_doc = client.get(f"{prefix}/api.html")
assert service_doc.status_code == 200, service_doc.text

service_desc = client.get(f"{prefix}/api")
assert service_desc.status_code == 200, service_desc.json()

conformance = client.get(f"{prefix}/conformance")
assert conformance.status_code == 200, conformance.json()

link_tests = [
("root", "application/json", "/"),
("conformance", "application/json", "/conformance"),
("service-doc", "text/html", "/api.html"),
("service-desc", "application/vnd.oai.openapi+json;version=3.0", "/api"),
]

for rel_type, expected_media_type, expected_path in link_tests:
link = get_link(landing.json(), rel_type)

assert link is not None, f"Missing {rel_type} link in landing page"
assert link.get("type") == expected_media_type

link_path = urllib.parse.urlsplit(link.get("href")).path
assert link_path == prefix + expected_path

resp = client.get(prefix + expected_path)
assert resp.status_code == 200
8 changes: 2 additions & 6 deletions stac_fastapi/types/stac_fastapi/types/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -404,9 +404,7 @@ def landing_page(self, **kwargs) -> stac_types.LandingPage:
"rel": "service-desc",
"type": "application/vnd.oai.openapi+json;version=3.0",
"title": "OpenAPI service description",
"href": urljoin(
str(request.base_url), request.app.openapi_url.lstrip("/")
),
"href": str(request.url_for("openapi")),
}
)

Expand All @@ -416,9 +414,7 @@ def landing_page(self, **kwargs) -> stac_types.LandingPage:
"rel": "service-doc",
"type": "text/html",
"title": "OpenAPI service documentation",
"href": urljoin(
str(request.base_url), request.app.docs_url.lstrip("/")
),
"href": str(request.url_for("swagger_ui_html")),
}
)

Expand Down

0 comments on commit 49de0ce

Please sign in to comment.