Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/settings.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ In version `6.0.0` we've renamed the PG configuration variable to match the offi
- `STAC_FASTAPI_LANDING_ID` (string) is a unique identifier for your Landing page
- `ROOT_PATH`: set application root-path (when using proxy)
- `CORS_ORIGINS`: A list of origins that should be permitted to make cross-origin requests. Defaults to `*`
- `CORS_ORIGIN_REGEX`: A regex string to match against origins that should be permitted to make cross-origin requests. eg. 'https://.*\.example\.org'.
- `CORS_METHODS`: A list of HTTP methods that should be allowed for cross-origin requests. Defaults to `"GET,POST,OPTIONS"`
- `CORS_CREDENTIALS`: Set to `true` to enable credentials via CORS requests. Note that you'll need to set `CORS_ORIGINS` to something other than `*`, because credentials are [disallowed](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CORS/Errors/CORSNotSupportingCredentials) for wildcard CORS origins.
- `CORS_HEADERS`: If `CORS_CREDENTIALS` are true and you're using an `Authorization` header, set this to `Content-Type,Authorization`. Alternatively, you can allow all headers by setting this to `*`.
Expand Down
1 change: 1 addition & 0 deletions stac_fastapi/pgstac/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@ async def lifespan(app: FastAPI):
Middleware(
CORSMiddleware,
allow_origins=settings.cors_origins,
allow_origin_regex=settings.cors_origin_regex,
allow_methods=settings.cors_methods,
allow_credentials=settings.cors_credentials,
allow_headers=settings.cors_headers,
Expand Down
47 changes: 28 additions & 19 deletions stac_fastapi/pgstac/config.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
"""Postgres API configuration."""

import warnings
from typing import Annotated, Any, List, Optional, Type
from typing import Annotated, Any, List, Optional, Sequence, Type
from urllib.parse import quote_plus as quote

from pydantic import BaseModel, Field, field_validator, model_validator
from pydantic import BaseModel, BeforeValidator, Field, model_validator
from pydantic_settings import BaseSettings, SettingsConfigDict
from stac_fastapi.types.config import ApiSettings
from typing_extensions import Self

from stac_fastapi.pgstac.types.base_item_cache import (
BaseItemCache,
Expand Down Expand Up @@ -155,6 +156,12 @@ def connection_string(self):
return f"postgresql://{self.pguser}:{quote(self.pgpassword)}@{self.pghost}:{self.pgport}/{self.pgdatabase}"


def str_to_list(value: Any) -> Any:
if isinstance(value, str):
return [v.strip() for v in value.split(",")]
return value


class Settings(ApiSettings):
"""API settings.

Expand All @@ -177,24 +184,26 @@ class Settings(ApiSettings):
Implies that the `Transactions` extension is enabled.
"""

cors_origins: str = "*"
cors_methods: str = "GET,POST,OPTIONS"
cors_origins: Annotated[Sequence[str], BeforeValidator(str_to_list)] = ("*",)
cors_origin_regex: Optional[str] = None
cors_methods: Annotated[Sequence[str], BeforeValidator(str_to_list)] = (
"GET",
"POST",
"OPTIONS",
)
cors_credentials: bool = False
cors_headers: str = "Content-Type"
cors_headers: Annotated[Sequence[str], BeforeValidator(str_to_list)] = (
"Content-Type",
)

testing: bool = False

@field_validator("cors_origins")
def parse_cors_origin(cls, v):
"""Parse CORS origins."""
return [origin.strip() for origin in v.split(",")]

@field_validator("cors_methods")
def parse_cors_methods(cls, v):
"""Parse CORS methods."""
return [method.strip() for method in v.split(",")]

@field_validator("cors_headers")
def parse_cors_headers(cls, v):
"""Parse CORS headers."""
return [header.strip() for header in v.split(",")]
@model_validator(mode="after")
def check_origins(self) -> Self:
if self.cors_origin_regex and "*" in self.cors_origins:
warnings.warn(
"Both `cors_origin_regex` and `*` found in `cors_origins`! `cors_origin_regex` will be ignored.",
UserWarning,
stacklevel=1,
)
return self
Loading