Fix CORS_ORIGINS env parsing crash (pydantic-settings NoDecode), bump 0.1.1
list[str] settings fed from env were JSON-decoded by pydantic-settings before the field validator ran, so a plain string like CORS_ORIGINS=http://host:5009 raised JSONDecodeError on startup. Annotate list env fields with NoDecode and parse CSV/JSON in the validator. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
21f2852259
commit
7775128c07
+16
-6
@@ -3,9 +3,10 @@ from __future__ import annotations
|
|||||||
|
|
||||||
import secrets
|
import secrets
|
||||||
from functools import lru_cache
|
from functools import lru_cache
|
||||||
|
from typing import Annotated
|
||||||
|
|
||||||
from pydantic import field_validator
|
from pydantic import field_validator
|
||||||
from pydantic_settings import BaseSettings, SettingsConfigDict
|
from pydantic_settings import BaseSettings, NoDecode, SettingsConfigDict
|
||||||
|
|
||||||
|
|
||||||
class Settings(BaseSettings):
|
class Settings(BaseSettings):
|
||||||
@@ -25,18 +26,22 @@ class Settings(BaseSettings):
|
|||||||
UPDATE_CHECK_INTERVAL_MINUTES: int = 60
|
UPDATE_CHECK_INTERVAL_MINUTES: int = 60
|
||||||
|
|
||||||
# Notifications (webhook URLs)
|
# Notifications (webhook URLs)
|
||||||
NOTIFY_WEBHOOKS: list[str] = []
|
NOTIFY_WEBHOOKS: Annotated[list[str], NoDecode] = []
|
||||||
|
|
||||||
# Docker
|
# Docker
|
||||||
DOCKER_SOCKET: str = "/var/run/docker.sock"
|
DOCKER_SOCKET: str = "/var/run/docker.sock"
|
||||||
HOST_PROC_PATH: str = "/host_proc"
|
HOST_PROC_PATH: str = "/host_proc"
|
||||||
|
|
||||||
# Host browser sandbox roots
|
# Host browser sandbox roots
|
||||||
ALLOWED_BROWSE_ROOTS: list[str] = ["/", "/mnt", "/media", "/srv", "/opt"]
|
ALLOWED_BROWSE_ROOTS: Annotated[list[str], NoDecode] = [
|
||||||
|
"/", "/mnt", "/media", "/srv", "/opt",
|
||||||
|
]
|
||||||
HOST_ROOT_PREFIX: str = "" # e.g. "/host_root" when host / is bind-mounted
|
HOST_ROOT_PREFIX: str = "" # e.g. "/host_root" when host / is bind-mounted
|
||||||
|
|
||||||
# CORS
|
# CORS
|
||||||
CORS_ORIGINS: list[str] = ["http://localhost:5009", "http://localhost:5173"]
|
CORS_ORIGINS: Annotated[list[str], NoDecode] = [
|
||||||
|
"http://localhost:5009", "http://localhost:5173",
|
||||||
|
]
|
||||||
|
|
||||||
# Server
|
# Server
|
||||||
PORT: int = 5008
|
PORT: int = 5008
|
||||||
@@ -55,8 +60,13 @@ class Settings(BaseSettings):
|
|||||||
v = v.strip()
|
v = v.strip()
|
||||||
if not v:
|
if not v:
|
||||||
return []
|
return []
|
||||||
if v.startswith("["): # JSON list
|
if v.startswith("["): # tolerate a JSON list too
|
||||||
return v
|
import json
|
||||||
|
|
||||||
|
try:
|
||||||
|
return json.loads(v)
|
||||||
|
except json.JSONDecodeError:
|
||||||
|
pass
|
||||||
return [item.strip() for item in v.split(",") if item.strip()]
|
return [item.strip() for item in v.split(",") if item.strip()]
|
||||||
return v
|
return v
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -31,7 +31,7 @@ async def lifespan(app: FastAPI):
|
|||||||
yield
|
yield
|
||||||
|
|
||||||
|
|
||||||
app = FastAPI(title="StackPilot", version="0.1.0", lifespan=lifespan)
|
app = FastAPI(title="StackPilot", version="0.1.1", lifespan=lifespan)
|
||||||
|
|
||||||
app.add_middleware(
|
app.add_middleware(
|
||||||
CORSMiddleware,
|
CORSMiddleware,
|
||||||
|
|||||||
Reference in New Issue
Block a user