stac-fastapi.api 6.1.4__tar.gz → 6.2.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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: stac-fastapi-api
3
- Version: 6.1.4
3
+ Version: 6.2.0
4
4
  Summary: An implementation of STAC API based on the FastAPI framework.
5
5
  Project-URL: Homepage, https://github.com/stac-utils/stac-fastapi
6
6
  Author-email: ArturoAI <engineering@arturo.ai>
@@ -11,12 +11,10 @@ Classifier: Intended Audience :: Developers
11
11
  Classifier: Intended Audience :: Information Technology
12
12
  Classifier: Intended Audience :: Science/Research
13
13
  Classifier: License :: OSI Approved :: MIT License
14
- Classifier: Programming Language :: Python :: 3.9
15
- Classifier: Programming Language :: Python :: 3.10
16
14
  Classifier: Programming Language :: Python :: 3.11
17
15
  Classifier: Programming Language :: Python :: 3.12
18
16
  Classifier: Programming Language :: Python :: 3.13
19
17
  Classifier: Programming Language :: Python :: 3.14
20
- Requires-Python: >=3.9
18
+ Requires-Python: >=3.11
21
19
  Requires-Dist: brotli-asgi
22
- Requires-Dist: stac-fastapi-types~=6.1
20
+ Requires-Dist: stac-fastapi-types~=6.2
@@ -2,7 +2,7 @@
2
2
  name = "stac-fastapi-api"
3
3
  description = "An implementation of STAC API based on the FastAPI framework."
4
4
  readme = "README.md"
5
- requires-python = ">=3.9"
5
+ requires-python = ">=3.11"
6
6
  license = "MIT"
7
7
  authors = [
8
8
  { name = "ArturoAI", email = "engineering@arturo.ai" },
@@ -23,8 +23,6 @@ classifiers = [
23
23
  "Intended Audience :: Developers",
24
24
  "Intended Audience :: Information Technology",
25
25
  "Intended Audience :: Science/Research",
26
- "Programming Language :: Python :: 3.9",
27
- "Programming Language :: Python :: 3.10",
28
26
  "Programming Language :: Python :: 3.11",
29
27
  "Programming Language :: Python :: 3.12",
30
28
  "Programming Language :: Python :: 3.13",
@@ -34,7 +32,7 @@ classifiers = [
34
32
  dynamic = ["version"]
35
33
  dependencies = [
36
34
  "brotli_asgi",
37
- "stac-fastapi.types~=6.1",
35
+ "stac-fastapi.types~=6.2",
38
36
  ]
39
37
 
40
38
  [dependency-groups]
@@ -82,20 +82,33 @@ class ProxyHeaderMiddleware:
82
82
 
83
83
  await self.app(scope, receive, send)
84
84
 
85
- def _get_forwarded_url_parts(self, scope: Scope) -> Tuple[str, str, str]:
85
+ def _get_forwarded_url_parts(self, scope: Scope) -> Tuple[str, str, int]:
86
86
  proto = scope.get("scheme", "http")
87
- header_host = self._get_header_value_by_name(scope, "host")
88
- if header_host is None:
89
- domain, port = scope["server"]
90
- else:
87
+ # Assume default port based on protocol, can be overridden later
88
+ port = 443 if proto == "https" else 80
89
+
90
+ if header_host := self._get_header_value_by_name(scope, "host"):
91
91
  header_host_parts = header_host.split(":")
92
+ domain = header_host_parts[0]
92
93
  if len(header_host_parts) == 2:
93
- domain, port = header_host_parts
94
- else:
95
- domain = header_host_parts[0]
96
- port = None
97
-
98
- port_str = None # make sure it is defined in all paths since we access it later
94
+ with contextlib.suppress(ValueError):
95
+ port = int(header_host_parts[1])
96
+ else:
97
+ # Not sure when we would not have a host header, but fallback to server info
98
+ domain, port = scope["server"]
99
+ port = int(port)
100
+
101
+ forwarded_port: Optional[str] = None
102
+ forwarding_occurred = any(
103
+ key
104
+ in [
105
+ b"forwarded",
106
+ b"x-forwarded-proto",
107
+ b"x-forwarded-host",
108
+ b"x-forwarded-port",
109
+ ]
110
+ for key, _ in scope["headers"]
111
+ )
99
112
 
100
113
  if forwarded := self._get_header_value_by_name(scope, "forwarded"):
101
114
  for proxy in forwarded.split(","):
@@ -103,15 +116,21 @@ class ProxyHeaderMiddleware:
103
116
  proto = proto_expr.group("proto")
104
117
  if host_expr := _HOST_HEADER_REGEX.search(proxy):
105
118
  domain = host_expr.group("host")
106
- port_str = host_expr.group("port") # None if not present in the match
119
+ forwarded_port = host_expr.group("port") # None if not present
107
120
 
108
121
  else:
109
- domain = self._get_header_value_by_name(scope, "x-forwarded-host", domain)
110
- proto = self._get_header_value_by_name(scope, "x-forwarded-proto", proto)
111
- port_str = self._get_header_value_by_name(scope, "x-forwarded-port", port)
112
-
113
- with contextlib.suppress(ValueError): # ignore ports that are not valid integers
114
- port = int(port_str) if port_str is not None else port
122
+ domain = self._get_header_value_by_name(scope, "x-forwarded-host") or domain
123
+ proto = self._get_header_value_by_name(scope, "x-forwarded-proto") or proto
124
+ forwarded_port = self._get_header_value_by_name(scope, "x-forwarded-port")
125
+
126
+ if forwarding_occurred and not forwarded_port:
127
+ # If forwarding occurred but no port was specified, use protocol default
128
+ forwarded_port = "443" if proto == "https" else "80"
129
+
130
+ if forwarded_port:
131
+ # ignore ports that are not valid integers
132
+ with contextlib.suppress(ValueError):
133
+ port = int(forwarded_port)
115
134
 
116
135
  return (proto, domain, port)
117
136
 
@@ -1,3 +1,3 @@
1
1
  """Library version."""
2
2
 
3
- __version__ = "6.1.4"
3
+ __version__ = "6.2.0"