Allow private-network CORS origins in development
This commit is contained in:
@@ -38,3 +38,4 @@ TYPESENSE_API_KEY=replace-with-random-typesense-api-key
|
||||
TYPESENSE_COLLECTION_NAME=documents
|
||||
PUBLIC_BASE_URL=http://localhost:8000
|
||||
CORS_ALLOW_CREDENTIALS=false
|
||||
CORS_ALLOW_DEVELOPMENT_PRIVATE_NETWORK_ORIGINS=true
|
||||
|
||||
@@ -73,6 +73,7 @@ class Settings(BaseSettings):
|
||||
public_base_url: str = "http://localhost:8000"
|
||||
cors_origins: list[str] = Field(default_factory=lambda: ["http://localhost:5173", "http://localhost:3000"])
|
||||
cors_allow_credentials: bool = False
|
||||
cors_allow_development_private_network_origins: bool = True
|
||||
|
||||
|
||||
LOCAL_HOSTNAME_SUFFIXES = (".local", ".internal", ".home.arpa")
|
||||
|
||||
@@ -19,6 +19,15 @@ from app.services.typesense_index import ensure_typesense_collection
|
||||
settings = get_settings()
|
||||
UPLOAD_ENDPOINT_PATH = "/api/v1/documents/upload"
|
||||
UPLOAD_ENDPOINT_METHOD = "POST"
|
||||
CORS_DEVELOPMENT_PRIVATE_ORIGIN_REGEX = (
|
||||
r"^https?://("
|
||||
r"localhost"
|
||||
r"|127\.0\.0\.1"
|
||||
r"|10\.\d{1,3}\.\d{1,3}\.\d{1,3}"
|
||||
r"|192\.168\.\d{1,3}\.\d{1,3}"
|
||||
r"|172\.(1[6-9]|2\d|3[0-1])\.\d{1,3}\.\d{1,3}"
|
||||
r")(?::\d{1,5})?$"
|
||||
)
|
||||
|
||||
|
||||
def _is_upload_size_guard_target(request: Request) -> bool:
|
||||
@@ -31,14 +40,28 @@ def _is_upload_size_guard_target(request: Request) -> bool:
|
||||
return request.method.upper() == UPLOAD_ENDPOINT_METHOD and request.url.path == UPLOAD_ENDPOINT_PATH
|
||||
|
||||
|
||||
def _resolve_cors_origin_regex() -> str | None:
|
||||
"""Returns development-only private-network origin regex when explicitly enabled."""
|
||||
|
||||
app_env = settings.app_env.strip().lower()
|
||||
if app_env not in {"development", "dev"}:
|
||||
return None
|
||||
allow_private_dev_origins = bool(getattr(settings, "cors_allow_development_private_network_origins", False))
|
||||
if not allow_private_dev_origins:
|
||||
return None
|
||||
return CORS_DEVELOPMENT_PRIVATE_ORIGIN_REGEX
|
||||
|
||||
|
||||
def create_app() -> FastAPI:
|
||||
"""Builds and configures the FastAPI application instance."""
|
||||
|
||||
app = FastAPI(title="DCM DMS API", version="0.1.0")
|
||||
allowed_origins = [origin.strip() for origin in settings.cors_origins if isinstance(origin, str) and origin.strip()]
|
||||
allowed_origin_regex = _resolve_cors_origin_regex()
|
||||
app.add_middleware(
|
||||
CORSMiddleware,
|
||||
allow_origins=allowed_origins,
|
||||
allow_origin_regex=allowed_origin_regex,
|
||||
allow_credentials=bool(getattr(settings, "cors_allow_credentials", False)),
|
||||
allow_methods=["*"],
|
||||
allow_headers=["*"],
|
||||
|
||||
Reference in New Issue
Block a user