From 23886a4b9c886747f23efcf22c272ce0e099620f Mon Sep 17 00:00:00 2001 From: Pete Gadomski Date: Mon, 17 Nov 2025 06:56:52 -0700 Subject: [PATCH 1/4] fix: use NoDecode for cors origins Otherwise, the env var syntax needs to be an encoded json string, which is awkward. --- stac_fastapi/pgstac/config.py | 6 ++++-- tests/test_config.py | 14 +++++++++++++- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/stac_fastapi/pgstac/config.py b/stac_fastapi/pgstac/config.py index 9af6513c..35b16ec9 100644 --- a/stac_fastapi/pgstac/config.py +++ b/stac_fastapi/pgstac/config.py @@ -5,7 +5,7 @@ from urllib.parse import quote_plus as quote from pydantic import BaseModel, BeforeValidator, Field, model_validator -from pydantic_settings import BaseSettings, SettingsConfigDict +from pydantic_settings import BaseSettings, NoDecode, SettingsConfigDict from stac_fastapi.types.config import ApiSettings from typing_extensions import Self @@ -201,7 +201,9 @@ class Settings(ApiSettings): Implies that the `Transactions` extension is enabled. """ - cors_origins: Annotated[Sequence[str], BeforeValidator(str_to_list)] = ("*",) + cors_origins: Annotated[Sequence[str], BeforeValidator(str_to_list), NoDecode] = ( + "*", + ) cors_origin_regex: Optional[str] = None cors_methods: Annotated[Sequence[str], BeforeValidator(str_to_list)] = ( "GET", diff --git a/tests/test_config.py b/tests/test_config.py index e05eb5ef..9df71e7f 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -4,8 +4,9 @@ import pytest from pydantic import ValidationError +from pytest import MonkeyPatch -from stac_fastapi.pgstac.config import PostgresSettings +from stac_fastapi.pgstac.config import PostgresSettings, Settings async def test_pg_settings_with_env(monkeypatch): @@ -74,3 +75,14 @@ async def test_pg_settings_attributes(monkeypatch): postgres_dbname="pgstac", _env_file=None, ) + + +def test_cors_origins(monkeypatch: MonkeyPatch) -> None: + monkeypatch.setenv( + "CORS_ORIGINS", "http://stac-fastapi-pgstac.test,http://stac-fastapi.test" + ) + settings = Settings() + assert settings.cors_origins == [ + "http://stac-fastapi-pgstac.test", + "http://stac-fastapi.test", + ] From b30e73dadfaf20524e7390e9d0cc86fd69188b77 Mon Sep 17 00:00:00 2001 From: Pete Gadomski Date: Mon, 17 Nov 2025 07:00:57 -0700 Subject: [PATCH 2/4] chore: update changelog --- CHANGES.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index d81b0e71..27b8f790 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -12,6 +12,10 @@ - `EXCLUDE_HYDRATE_MARKERS=TRUE/FALSE` (defaults to `TRUE`) to exclude `𒍟※` markers returned by PgSTAC - python `3.13` and `3.14` support +### Fixed + +- Parsing of `CORS_ORIGINS` from environment variables ([#313](https://github.com/stac-utils/stac-fastapi-pgstac/pull/313)) + ## [6.0.2] - 2025-10-03 - add `CORS_ORIGIN_REGEX` settings ([#298](https://github.com/stac-utils/stac-fastapi-pgstac/pull/298)) From 192f0de081116074cf983d90c171db41c877d99e Mon Sep 17 00:00:00 2001 From: Pete Gadomski Date: Thu, 20 Nov 2025 05:10:33 -0700 Subject: [PATCH 3/4] feat: add json parsing, more values --- stac_fastapi/pgstac/config.py | 13 ++++++--- tests/test_config.py | 50 +++++++++++++++++++++++++++++++++-- 2 files changed, 57 insertions(+), 6 deletions(-) diff --git a/stac_fastapi/pgstac/config.py b/stac_fastapi/pgstac/config.py index 35b16ec9..e0daecc6 100644 --- a/stac_fastapi/pgstac/config.py +++ b/stac_fastapi/pgstac/config.py @@ -1,5 +1,6 @@ """Postgres API configuration.""" +import json import warnings from typing import Annotated, Any, List, Optional, Sequence, Type from urllib.parse import quote_plus as quote @@ -158,8 +159,12 @@ def connection_string(self): def str_to_list(value: Any) -> Any: if isinstance(value, str): - return [v.strip() for v in value.split(",")] - return value + if value.startswith("["): + return json.loads(value) + else: + return [v.strip() for v in value.split(",")] + else: + return value class Settings(ApiSettings): @@ -205,13 +210,13 @@ class Settings(ApiSettings): "*", ) cors_origin_regex: Optional[str] = None - cors_methods: Annotated[Sequence[str], BeforeValidator(str_to_list)] = ( + cors_methods: Annotated[Sequence[str], BeforeValidator(str_to_list), NoDecode] = ( "GET", "POST", "OPTIONS", ) cors_credentials: bool = False - cors_headers: Annotated[Sequence[str], BeforeValidator(str_to_list)] = ( + cors_headers: Annotated[Sequence[str], BeforeValidator(str_to_list), NoDecode] = ( "Content-Type", ) diff --git a/tests/test_config.py b/tests/test_config.py index 9df71e7f..195b776e 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -77,12 +77,58 @@ async def test_pg_settings_attributes(monkeypatch): ) -def test_cors_origins(monkeypatch: MonkeyPatch) -> None: +@pytest.mark.parametrize( + "cors_origins", + [ + "http://stac-fastapi-pgstac.test,http://stac-fastapi.test", + '["http://stac-fastapi-pgstac.test","http://stac-fastapi.test"]', + ], +) +def test_cors_origins(monkeypatch: MonkeyPatch, cors_origins: str) -> None: monkeypatch.setenv( - "CORS_ORIGINS", "http://stac-fastapi-pgstac.test,http://stac-fastapi.test" + "CORS_ORIGINS", + cors_origins, ) settings = Settings() assert settings.cors_origins == [ "http://stac-fastapi-pgstac.test", "http://stac-fastapi.test", ] + + +@pytest.mark.parametrize( + "cors_methods", + [ + "GET,POST", + '["GET","POST"]', + ], +) +def test_cors_methods(monkeypatch: MonkeyPatch, cors_methods: str) -> None: + monkeypatch.setenv( + "CORS_METHODS", + cors_methods, + ) + settings = Settings() + assert settings.cors_methods == [ + "GET", + "POST", + ] + + +@pytest.mark.parametrize( + "cors_headers", + [ + "Content-Type,X-Foo", + '["Content-Type","X-Foo"]', + ], +) +def test_cors_headers(monkeypatch: MonkeyPatch, cors_headers: str) -> None: + monkeypatch.setenv( + "CORS_HEADERS", + cors_headers, + ) + settings = Settings() + assert settings.cors_headers == [ + "Content-Type", + "X-Foo", + ] From 2398d6bff266008e5692a4b6c32417d2071bc02f Mon Sep 17 00:00:00 2001 From: Pete Gadomski Date: Thu, 20 Nov 2025 05:12:10 -0700 Subject: [PATCH 4/4] chore: update changelog --- CHANGES.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 1e0d1380..9d46bdbf 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -2,6 +2,10 @@ ## [Unreleased] +### Fixed + +- Parsing of `CORS_ORIGINS`, `CORS_HEADERS`, and `CORS_METHODS` from environment variables ([#313](https://github.com/stac-utils/stac-fastapi-pgstac/pull/313)) + ### Changed - Docker container runs as non-root user @@ -25,10 +29,6 @@ - aws lambda handler in `app.py` -### Fixed - -- Parsing of `CORS_ORIGINS` from environment variables ([#313](https://github.com/stac-utils/stac-fastapi-pgstac/pull/313)) - ## [6.0.2] - 2025-10-03 - add `CORS_ORIGIN_REGEX` settings ([#298](https://github.com/stac-utils/stac-fastapi-pgstac/pull/298))