stac-fastapi.api 4.0.0__tar.gz → 5.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (24) hide show
  1. {stac_fastapi_api-4.0.0 → stac_fastapi_api-5.0.0}/PKG-INFO +2 -2
  2. {stac_fastapi_api-4.0.0 → stac_fastapi_api-5.0.0}/setup.py +1 -1
  3. {stac_fastapi_api-4.0.0 → stac_fastapi_api-5.0.0}/stac_fastapi/api/app.py +17 -34
  4. {stac_fastapi_api-4.0.0 → stac_fastapi_api-5.0.0}/stac_fastapi/api/middleware.py +7 -6
  5. {stac_fastapi_api-4.0.0 → stac_fastapi_api-5.0.0}/stac_fastapi/api/version.py +1 -1
  6. {stac_fastapi_api-4.0.0 → stac_fastapi_api-5.0.0}/stac_fastapi.api.egg-info/PKG-INFO +2 -2
  7. {stac_fastapi_api-4.0.0 → stac_fastapi_api-5.0.0}/stac_fastapi.api.egg-info/requires.txt +1 -1
  8. {stac_fastapi_api-4.0.0 → stac_fastapi_api-5.0.0}/tests/test_app_prefix.py +27 -0
  9. {stac_fastapi_api-4.0.0 → stac_fastapi_api-5.0.0}/tests/test_middleware.py +14 -0
  10. {stac_fastapi_api-4.0.0 → stac_fastapi_api-5.0.0}/README.md +0 -0
  11. {stac_fastapi_api-4.0.0 → stac_fastapi_api-5.0.0}/setup.cfg +0 -0
  12. {stac_fastapi_api-4.0.0 → stac_fastapi_api-5.0.0}/stac_fastapi/api/__init__.py +0 -0
  13. {stac_fastapi_api-4.0.0 → stac_fastapi_api-5.0.0}/stac_fastapi/api/config.py +0 -0
  14. {stac_fastapi_api-4.0.0 → stac_fastapi_api-5.0.0}/stac_fastapi/api/errors.py +0 -0
  15. {stac_fastapi_api-4.0.0 → stac_fastapi_api-5.0.0}/stac_fastapi/api/models.py +0 -0
  16. {stac_fastapi_api-4.0.0 → stac_fastapi_api-5.0.0}/stac_fastapi/api/openapi.py +0 -0
  17. {stac_fastapi_api-4.0.0 → stac_fastapi_api-5.0.0}/stac_fastapi/api/routes.py +0 -0
  18. {stac_fastapi_api-4.0.0 → stac_fastapi_api-5.0.0}/stac_fastapi.api.egg-info/SOURCES.txt +0 -0
  19. {stac_fastapi_api-4.0.0 → stac_fastapi_api-5.0.0}/stac_fastapi.api.egg-info/dependency_links.txt +0 -0
  20. {stac_fastapi_api-4.0.0 → stac_fastapi_api-5.0.0}/stac_fastapi.api.egg-info/not-zip-safe +0 -0
  21. {stac_fastapi_api-4.0.0 → stac_fastapi_api-5.0.0}/stac_fastapi.api.egg-info/top_level.txt +0 -0
  22. {stac_fastapi_api-4.0.0 → stac_fastapi_api-5.0.0}/tests/test_api.py +0 -0
  23. {stac_fastapi_api-4.0.0 → stac_fastapi_api-5.0.0}/tests/test_app.py +0 -0
  24. {stac_fastapi_api-4.0.0 → stac_fastapi_api-5.0.0}/tests/test_models.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: stac-fastapi.api
3
- Version: 4.0.0
3
+ Version: 5.0.0
4
4
  Summary: An implementation of STAC API based on the FastAPI framework.
5
5
  Home-page: https://github.com/stac-utils/stac-fastapi
6
6
  Author: Arturo Engineering
@@ -19,7 +19,7 @@ Classifier: License :: OSI Approved :: MIT License
19
19
  Requires-Python: >=3.9
20
20
  Description-Content-Type: text/markdown
21
21
  Requires-Dist: brotli_asgi
22
- Requires-Dist: stac-fastapi.types~=4.0
22
+ Requires-Dist: stac-fastapi.types~=5.0
23
23
  Provides-Extra: dev
24
24
  Requires-Dist: httpx; extra == "dev"
25
25
  Requires-Dist: pytest; extra == "dev"
@@ -7,7 +7,7 @@ with open("README.md") as f:
7
7
 
8
8
  install_requires = [
9
9
  "brotli_asgi",
10
- "stac-fastapi.types~=4.0",
10
+ "stac-fastapi.types~=5.0",
11
11
  ]
12
12
 
13
13
  extra_reqs = {
@@ -1,12 +1,11 @@
1
1
  """Fastapi app creation."""
2
2
 
3
3
 
4
- from typing import Any, Dict, List, Optional, Tuple, Type, Union
4
+ from typing import Dict, List, Optional, Tuple, Type, Union
5
5
 
6
6
  import attr
7
7
  from brotli_asgi import BrotliMiddleware
8
8
  from fastapi import APIRouter, FastAPI
9
- from fastapi.openapi.utils import get_openapi
10
9
  from fastapi.params import Depends
11
10
  from stac_pydantic import api
12
11
  from stac_pydantic.api.collections import Collections
@@ -71,19 +70,6 @@ class StacApi:
71
70
  exceptions: Dict[Type[Exception], int] = attr.ib(
72
71
  default=attr.Factory(lambda: DEFAULT_STATUS_CODES)
73
72
  )
74
- app: FastAPI = attr.ib(
75
- default=attr.Factory(
76
- lambda self: FastAPI(
77
- openapi_url=self.settings.openapi_url,
78
- docs_url=self.settings.docs_url,
79
- redoc_url=None,
80
- root_path=self.settings.root_path,
81
- ),
82
- takes_self=True,
83
- ),
84
- converter=update_openapi,
85
- )
86
- router: APIRouter = attr.ib(default=attr.Factory(APIRouter))
87
73
  title: str = attr.ib(
88
74
  default=attr.Factory(
89
75
  lambda self: self.settings.stac_fastapi_title, takes_self=True
@@ -100,6 +86,22 @@ class StacApi:
100
86
  lambda self: self.settings.stac_fastapi_description, takes_self=True
101
87
  )
102
88
  )
89
+ app: FastAPI = attr.ib(
90
+ default=attr.Factory(
91
+ lambda self: FastAPI(
92
+ openapi_url=self.settings.openapi_url,
93
+ docs_url=self.settings.docs_url,
94
+ redoc_url=None,
95
+ root_path=self.settings.root_path,
96
+ title=self.title,
97
+ version=self.api_version,
98
+ description=self.description,
99
+ ),
100
+ takes_self=True,
101
+ ),
102
+ converter=update_openapi,
103
+ )
104
+ router: APIRouter = attr.ib(default=attr.Factory(APIRouter))
103
105
  search_get_request_model: Type[BaseSearchGetRequest] = attr.ib(
104
106
  default=BaseSearchGetRequest
105
107
  )
@@ -388,22 +390,6 @@ class StacApi:
388
390
  self.register_get_collection()
389
391
  self.register_get_item_collection()
390
392
 
391
- def customize_openapi(self) -> Optional[Dict[str, Any]]:
392
- """Customize openapi schema."""
393
- if self.app.openapi_schema:
394
- return self.app.openapi_schema
395
-
396
- openapi_schema = get_openapi(
397
- title=self.title,
398
- version=self.api_version,
399
- description=self.description,
400
- routes=self.app.routes,
401
- servers=self.app.servers,
402
- )
403
-
404
- self.app.openapi_schema = openapi_schema
405
- return self.app.openapi_schema
406
-
407
393
  def add_health_check(self):
408
394
  """Add a health check."""
409
395
  mgmt_router = APIRouter(prefix=self.app.state.router_prefix)
@@ -467,9 +453,6 @@ class StacApi:
467
453
  # register exception handlers
468
454
  add_exception_handlers(self.app, status_codes=self.exceptions)
469
455
 
470
- # customize openapi
471
- self.app.openapi = self.customize_openapi
472
-
473
456
  # add middlewares
474
457
  if self.middlewares and self.app.middleware_stack is not None:
475
458
  raise RuntimeError("Cannot add middleware after an application has started")
@@ -4,7 +4,7 @@ import contextlib
4
4
  import re
5
5
  import typing
6
6
  from http.client import HTTP_PORT, HTTPS_PORT
7
- from typing import List, Tuple
7
+ from typing import List, Optional, Tuple
8
8
 
9
9
  from starlette.middleware.cors import CORSMiddleware as _CORSMiddleware
10
10
  from starlette.types import ASGIApp, Receive, Scope, Send
@@ -95,12 +95,13 @@ class ProxyHeaderMiddleware:
95
95
  domain = header_host_parts[0]
96
96
  port = None
97
97
 
98
+ port_str = None # make sure it is defined in all paths since we access it later
99
+
98
100
  if forwarded := self._get_header_value_by_name(scope, "forwarded"):
99
101
  for proxy in forwarded.split(","):
100
- if (proto_expr := _PROTO_HEADER_REGEX.search(proxy)) and (
101
- host_expr := _HOST_HEADER_REGEX.search(proxy)
102
- ):
102
+ if proto_expr := _PROTO_HEADER_REGEX.search(proxy):
103
103
  proto = proto_expr.group("proto")
104
+ if host_expr := _HOST_HEADER_REGEX.search(proxy):
104
105
  domain = host_expr.group("host")
105
106
  port_str = host_expr.group("port") # None if not present in the match
106
107
 
@@ -115,8 +116,8 @@ class ProxyHeaderMiddleware:
115
116
  return (proto, domain, port)
116
117
 
117
118
  def _get_header_value_by_name(
118
- self, scope: Scope, header_name: str, default_value: str = None
119
- ) -> str:
119
+ self, scope: Scope, header_name: str, default_value: Optional[str] = None
120
+ ) -> Optional[str]:
120
121
  headers = scope["headers"]
121
122
  candidates = [
122
123
  value.decode() for key, value in headers if key.decode() == header_name
@@ -1,3 +1,3 @@
1
1
  """Library version."""
2
2
 
3
- __version__ = "4.0.0"
3
+ __version__ = "5.0.0"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: stac-fastapi.api
3
- Version: 4.0.0
3
+ Version: 5.0.0
4
4
  Summary: An implementation of STAC API based on the FastAPI framework.
5
5
  Home-page: https://github.com/stac-utils/stac-fastapi
6
6
  Author: Arturo Engineering
@@ -19,7 +19,7 @@ Classifier: License :: OSI Approved :: MIT License
19
19
  Requires-Python: >=3.9
20
20
  Description-Content-Type: text/markdown
21
21
  Requires-Dist: brotli_asgi
22
- Requires-Dist: stac-fastapi.types~=4.0
22
+ Requires-Dist: stac-fastapi.types~=5.0
23
23
  Provides-Extra: dev
24
24
  Requires-Dist: httpx; extra == "dev"
25
25
  Requires-Dist: pytest; extra == "dev"
@@ -1,5 +1,5 @@
1
1
  brotli_asgi
2
- stac-fastapi.types~=4.0
2
+ stac-fastapi.types~=5.0
3
3
 
4
4
  [benchmark]
5
5
  pytest-benchmark
@@ -208,3 +208,30 @@ def test_api_prefix_with_root_path(TestCoreClient, prefix):
208
208
 
209
209
  resp = client.get(prefix + expected_path)
210
210
  assert resp.status_code == 200
211
+
212
+
213
+ def test_api_fastapi_option(TestCoreClient):
214
+ api_settings = ApiSettings(
215
+ stac_fastapi_title="stac-fastapi-tests",
216
+ stac_fastapi_description="test for stac-fastapi",
217
+ stac_fastapi_version="0.1.0dev",
218
+ )
219
+
220
+ api = StacApi(
221
+ settings=api_settings,
222
+ client=TestCoreClient(),
223
+ )
224
+
225
+ with TestClient(api.app, base_url="http://stac.io") as client:
226
+ landing = client.get("/")
227
+ assert landing.status_code == 200
228
+ body = landing.json()
229
+ assert body["title"] == "stac-fastapi-tests"
230
+ assert body["description"] == "test for stac-fastapi"
231
+
232
+ service_desc = client.get("/api")
233
+ assert service_desc.status_code == 200
234
+ body = service_desc.json()["info"]
235
+ assert body["title"] == "stac-fastapi-tests"
236
+ assert body["description"] == "test for stac-fastapi"
237
+ assert body["version"] == "0.1.0dev"
@@ -183,6 +183,20 @@ def test_replace_header_value_by_name(
183
183
  },
184
184
  ("https", "test", 1234),
185
185
  ),
186
+ (
187
+ {
188
+ "scheme": "http",
189
+ "server": ["testserver", 80],
190
+ "headers": [
191
+ (
192
+ b"forwarded",
193
+ # proto is set, but no host
194
+ b'for="85.193.181.55";proto=https,for="85.193.181.55";proto=https',
195
+ )
196
+ ],
197
+ },
198
+ ("https", "testserver", 80),
199
+ ),
186
200
  ],
187
201
  )
188
202
  def test_get_forwarded_url_parts(