Spaces:
Sleeping
Sleeping
| from __future__ import annotations | |
| from fastapi.testclient import TestClient | |
| from app.main import create_app | |
| from tests.conftest import FakeModelManager, build_test_settings | |
| def test_security_headers_and_request_id_are_present(client: TestClient) -> None: | |
| response = client.get("/api/v1/health/live") | |
| assert response.status_code == 200 | |
| assert response.headers["X-Request-ID"] | |
| assert response.headers["X-Content-Type-Options"] == "nosniff" | |
| assert response.headers["X-Frame-Options"] == "DENY" | |
| assert response.headers["Cache-Control"] == "no-store" | |
| def test_docs_endpoint_remains_renderable_under_csp(client: TestClient) -> None: | |
| response = client.get("/docs") | |
| assert response.status_code == 200 | |
| assert "Swagger UI" in response.text | |
| assert "cdn.jsdelivr.net" in response.headers["Content-Security-Policy"] | |
| def test_huggingface_space_docs_allow_embedding_in_app_tab(client: TestClient) -> None: | |
| response = client.get("/docs", headers={"Host": "demo-space.hf.space"}) | |
| assert response.status_code == 200 | |
| assert "X-Frame-Options" not in response.headers | |
| assert "frame-ancestors https://huggingface.co https://*.huggingface.co" in response.headers[ | |
| "Content-Security-Policy" | |
| ] | |
| def test_rate_limit_blocks_excess_requests(tmp_path) -> None: | |
| settings = build_test_settings( | |
| f"sqlite:///{tmp_path / 'rate_limit.db'}", | |
| rate_limit_requests=1, | |
| rate_limit_window_seconds=60, | |
| ) | |
| app = create_app(settings=settings, model_manager=FakeModelManager()) | |
| with TestClient(app) as client: | |
| first_response = client.post( | |
| "/api/v1/auth/register", | |
| json={ | |
| "email": "limit@example.com", | |
| "full_name": "Limit User", | |
| "password": "StrongPass!123", | |
| }, | |
| ) | |
| second_response = client.post( | |
| "/api/v1/auth/register", | |
| json={ | |
| "email": "limit2@example.com", | |
| "full_name": "Limit User Two", | |
| "password": "StrongPass!123", | |
| }, | |
| ) | |
| assert first_response.status_code == 201 | |
| assert second_response.status_code == 429 | |
| assert second_response.json()["error"]["code"] == "rate_limit_exceeded" | |
| def test_trusted_host_middleware_rejects_invalid_hosts(client: TestClient) -> None: | |
| response = client.get("/api/v1/health/live", headers={"Host": "evil.example.com"}) | |
| assert response.status_code == 400 | |
| def test_allowed_hosts_configuration_normalizes_full_urls(tmp_path) -> None: | |
| settings = build_test_settings( | |
| f"sqlite:///{tmp_path / 'trusted_hosts.db'}", | |
| allowed_hosts=[ | |
| "localhost/docs", | |
| "127.0.0.1:8000/docs", | |
| "https://demo-space.hf.space/docs", | |
| ], | |
| ) | |
| app = create_app(settings=settings, model_manager=FakeModelManager()) | |
| with TestClient(app) as client: | |
| localhost_response = client.get("/api/v1/health/live", headers={"Host": "localhost:8000"}) | |
| space_response = client.get("/api/v1/health/live", headers={"Host": "demo-space.hf.space"}) | |
| assert localhost_response.status_code == 200 | |
| assert space_response.status_code == 200 | |