import pytest from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware from fastapi.testclient import TestClient from app.core.config import Settings ALLOWED_ORIGINS = [ "https://next-demo.waternetwork.cn", "http://192.168.1.133", "https://192.168.1.133", "http://192.168.1.110", "https://192.168.1.110", ] @pytest.mark.parametrize("origins", ["*", " *, http://localhost:5173", "http://localhost:5173,*"]) def test_wildcard_origins_are_rejected(origins: str): with pytest.raises(ValueError, match="must list explicit origins"): Settings(_env_file=None, CORS_ALLOWED_ORIGINS=origins).cors_allowed_origins @pytest.mark.parametrize( "origin", ALLOWED_ORIGINS + [ "http://192.168.1.114", "http://192.168.1.133:5173", "https://demo.waternetwork.cn", "http://192.168.1.133.evil.example", "null", ], ) def test_explicit_origin_preflight(origin: str): settings = Settings(_env_file=None, CORS_ALLOWED_ORIGINS=", ".join(ALLOWED_ORIGINS)) app = FastAPI() app.add_middleware( CORSMiddleware, allow_origins=settings.cors_allowed_origins, allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) with TestClient(app) as client: response = client.options( "/api/v1/projects", headers={ "Origin": origin, "Access-Control-Request-Method": "GET", "Access-Control-Request-Headers": "authorization,x-project-id", }, ) allowed = origin in ALLOWED_ORIGINS assert response.status_code == (200 if allowed else 400) assert response.headers.get("access-control-allow-origin") == (origin if allowed else None) if allowed: assert response.headers["access-control-allow-credentials"] == "true" assert "authorization" in response.headers["access-control-allow-headers"] def test_default_origins_are_explicit_local_sources(monkeypatch): monkeypatch.delenv("CORS_ALLOWED_ORIGINS", raising=False) settings = Settings(_env_file=None) assert settings.cors_allowed_origins == [ "http://127.0.0.1:5173", "http://localhost:5173", "http://127.0.0.1:15173", "http://localhost:15173", ] def test_environment_controls_origins(monkeypatch): monkeypatch.setenv("CORS_ALLOWED_ORIGINS", "http://192.168.1.133,https://192.168.1.110") settings = Settings(_env_file=None) assert settings.cors_allowed_origins == ["http://192.168.1.133", "https://192.168.1.110"]