Skip to content

Commit c02b97d

Browse files
committed
update from main
2 parents ad080fb + d379c89 commit c02b97d

File tree

9 files changed

+170
-15
lines changed

9 files changed

+170
-15
lines changed

CHANGES.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,12 @@
66

77
- move Postgres settings into separate `PostgresSettings` class and defer loading until connecting to database ([#209](https://github.com/stac-utils/stac-fastapi-pgstac/pull/209))
88

9+
## [4.0.3] - 2025-03-10
10+
11+
### Fixed
12+
13+
- fix links when app is mounted behind proxy or has router-prefix ([#195](https://github.com/stac-utils/stac-fastapi-pgstac/pull/195))
14+
915
## [4.0.2] - 2025-02-18
1016

1117
### Fixed
@@ -387,7 +393,8 @@ As a part of this release, this repository was extracted from the main
387393

388394
- First PyPi release!
389395

390-
[Unreleased]: <https://github.com/stac-utils/stac-fastapi-pgstac/compare/4.0.2..main>
396+
[Unreleased]: <https://github.com/stac-utils/stac-fastapi-pgstac/compare/4.0.3..main>
397+
[4.0.3]: <https://github.com/stac-utils/stac-fastapi-pgstac/compare/4.0.2..4.0.3>
391398
[4.0.2]: <https://github.com/stac-utils/stac-fastapi-pgstac/compare/4.0.1..4.0.2>
392399
[4.0.1]: <https://github.com/stac-utils/stac-fastapi-pgstac/compare/4.0.0..4.0.1>
393400
[4.0.0]: <https://github.com/stac-utils/stac-fastapi-pgstac/compare/3.0.1..4.0.0>

RELEASING.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,12 @@ This is a checklist for releasing a new version of **stac-fastapi**.
66
We currently do not have published versioning guidelines, but there is some text on the subject here: <https://github.com/radiantearth/stac-spec/discussions/1184>.
77
2. Create a release branch named `release/vX.Y.Z`, where `X.Y.Z` is the new version.
88
3. Search and replace all instances of the current version number with the new version.
9+
10+
Note: You can use [`bump-my-version`](https://github.com/callowayproject/bump-my-version) CLI
11+
```
12+
bump-my-version bump --new-version 3.1.0
13+
```
14+
915
4. Update [CHANGES.md](./CHANGES.md) for the new version.
1016
Add the appropriate header, and update the links at the bottom of the file.
1117
5. Audit CHANGES.md for completeness and accuracy.

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
4.0.2
1+
4.0.3

pyproject.toml

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,41 @@ ignore = [
2626
"E501", # do not perform function calls in argument defaults
2727
"B028", # No explicit `stacklevel` keyword argument found
2828
]
29+
30+
31+
[tool.bumpversion]
32+
current_version = "4.0.3"
33+
parse = """(?x)
34+
(?P<major>\\d+)\\.
35+
(?P<minor>\\d+)\\.
36+
(?P<patch>\\d+)
37+
(?:
38+
(?P<pre_l>a|b|rc) # pre-release label
39+
(?P<pre_n>\\d+) # pre-release version number
40+
)? # pre-release section is optional
41+
(?:
42+
\\.post
43+
(?P<post_n>\\d+) # post-release version number
44+
)? # post-release section is optional
45+
"""
46+
serialize = [
47+
"{major}.{minor}.{patch}.post{post_n}",
48+
"{major}.{minor}.{patch}{pre_l}{pre_n}",
49+
"{major}.{minor}.{patch}",
50+
]
51+
52+
search = "{current_version}"
53+
replace = "{new_version}"
54+
regex = false
55+
tag = false
56+
commit = true
57+
58+
[[tool.bumpversion.files]]
59+
filename = "VERSION"
60+
search = "{current_version}"
61+
replace = "{new_version}"
62+
63+
[[tool.bumpversion.files]]
64+
filename = "stac_fastapi/pgstac/version.py"
65+
search = '__version__ = "{current_version}"'
66+
replace = '__version__ = "{new_version}"'

setup.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@
1010
"orjson",
1111
"pydantic",
1212
"stac_pydantic==3.1.*",
13-
"stac-fastapi.api~=5.0",
14-
"stac-fastapi.extensions~=5.0",
15-
"stac-fastapi.types~=5.0",
13+
"stac-fastapi.api>=5.0,<5.1",
14+
"stac-fastapi.extensions>=5.0,<5.1",
15+
"stac-fastapi.types>=5.0,<5.1",
1616
"asyncpg",
1717
"buildpg",
1818
"brotli_asgi",

stac_fastapi/pgstac/models/links.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,11 @@ def base_url(self):
5151
@property
5252
def url(self):
5353
"""Get the current request url."""
54-
return str(self.request.url)
54+
url = urljoin(str(self.request.base_url), self.request.url.path.lstrip("/"))
55+
if qs := self.request.url.query:
56+
url += f"?{qs}"
57+
58+
return url
5559

5660
def resolve(self, url):
5761
"""Resolve url to the current request url."""
@@ -143,7 +147,7 @@ def link_next(self) -> Optional[Dict[str, Any]]:
143147
"rel": Relations.next.value,
144148
"type": MimeTypes.geojson.value,
145149
"method": method,
146-
"href": f"{self.request.url}",
150+
"href": self.url,
147151
"body": {**self.request.postbody, "token": f"next:{self.next}"},
148152
}
149153

@@ -167,7 +171,7 @@ def link_prev(self) -> Optional[Dict[str, Any]]:
167171
"rel": Relations.previous.value,
168172
"type": MimeTypes.geojson.value,
169173
"method": method,
170-
"href": f"{self.request.url}",
174+
"href": self.url,
171175
"body": {**self.request.postbody, "token": f"prev:{self.prev}"},
172176
}
173177
return None

stac_fastapi/pgstac/version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
"""library version."""
22

3-
__version__ = "4.0.2"
3+
__version__ = "4.0.3"

tests/api/test_links.py

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
import pytest
2+
from fastapi import APIRouter, FastAPI
3+
from starlette.requests import Request
4+
from starlette.testclient import TestClient
5+
6+
from stac_fastapi.pgstac.models import links as app_links
7+
8+
9+
@pytest.mark.parametrize("root_path", ["", "/api/v1"])
10+
@pytest.mark.parametrize("prefix", ["", "/stac"])
11+
def tests_app_links(prefix, root_path): # noqa: C901
12+
endpoint_prefix = root_path + prefix
13+
url_prefix = "http://stac.io" + endpoint_prefix
14+
15+
app = FastAPI(root_path=root_path)
16+
router = APIRouter(prefix=prefix)
17+
app.state.router_prefix = router.prefix
18+
19+
@router.get("/search")
20+
@router.post("/search")
21+
async def search(request: Request):
22+
links = app_links.PagingLinks(request, next="yo:2", prev="yo:1")
23+
return {
24+
"url": links.url,
25+
"base_url": links.base_url,
26+
"links": await links.get_links(),
27+
}
28+
29+
@router.get("/collections")
30+
async def collections(request: Request):
31+
pgstac_next = {
32+
"rel": "next",
33+
"body": {"offset": 1},
34+
"href": "./collections",
35+
"type": "application/json",
36+
"merge": True,
37+
"method": "GET",
38+
}
39+
pgstac_prev = {
40+
"rel": "prev",
41+
"body": {"offset": 0},
42+
"href": "./collections",
43+
"type": "application/json",
44+
"merge": True,
45+
"method": "GET",
46+
}
47+
links = app_links.CollectionSearchPagingLinks(
48+
request, next=pgstac_next, prev=pgstac_prev
49+
)
50+
return {
51+
"url": links.url,
52+
"base_url": links.base_url,
53+
"links": await links.get_links(),
54+
}
55+
56+
app.include_router(router)
57+
58+
with TestClient(
59+
app,
60+
base_url="http://stac.io",
61+
root_path=root_path,
62+
) as client:
63+
response = client.get(f"{prefix}/search")
64+
assert response.status_code == 200
65+
assert response.json()["url"] == url_prefix + "/search"
66+
assert response.json()["base_url"].rstrip("/") == url_prefix
67+
links = response.json()["links"]
68+
for link in links:
69+
if link["rel"] in ["previous", "next"]:
70+
assert link["method"] == "GET"
71+
assert link["href"].startswith(url_prefix)
72+
assert {"next", "previous", "root", "self"} == {link["rel"] for link in links}
73+
74+
response = client.get(f"{prefix}/search", params={"limit": 1})
75+
assert response.status_code == 200
76+
assert response.json()["url"] == url_prefix + "/search?limit=1"
77+
assert response.json()["base_url"].rstrip("/") == url_prefix
78+
links = response.json()["links"]
79+
for link in links:
80+
if link["rel"] in ["previous", "next"]:
81+
assert link["method"] == "GET"
82+
assert "limit=1" in link["href"]
83+
assert link["href"].startswith(url_prefix)
84+
assert {"next", "previous", "root", "self"} == {link["rel"] for link in links}
85+
86+
response = client.post(f"{prefix}/search", json={})
87+
assert response.status_code == 200
88+
assert response.json()["url"] == url_prefix + "/search"
89+
assert response.json()["base_url"].rstrip("/") == url_prefix
90+
links = response.json()["links"]
91+
for link in links:
92+
if link["rel"] in ["previous", "next"]:
93+
assert link["method"] == "POST"
94+
assert link["href"].startswith(url_prefix)
95+
assert {"next", "previous", "root", "self"} == {link["rel"] for link in links}
96+
97+
response = client.get(f"{prefix}/collections")
98+
assert response.status_code == 200
99+
assert response.json()["url"] == url_prefix + "/collections"
100+
assert response.json()["base_url"].rstrip("/") == url_prefix
101+
links = response.json()["links"]
102+
for link in links:
103+
if link["rel"] in ["previous", "next"]:
104+
assert link["method"] == "GET"
105+
assert link["href"].startswith(url_prefix)
106+
assert {"next", "previous", "root", "self"} == {link["rel"] for link in links}

tests/conftest.py

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import asyncio
21
import json
32
import logging
43
import os
@@ -62,11 +61,6 @@
6261
)
6362

6463

65-
@pytest.fixture(scope="session")
66-
def event_loop():
67-
return asyncio.get_event_loop()
68-
69-
7064
@pytest.fixture(scope="session")
7165
def database(postgresql_proc):
7266
with DatabaseJanitor(

0 commit comments

Comments
 (0)