Spaces:
Running
Running
Commit ·
d86dd21
1
Parent(s): eac9fcd
Allow public root/health while keeping API auth protected
Browse files- api/dependencies.py +11 -0
- tests/api/test_auth.py +33 -0
api/dependencies.py
CHANGED
|
@@ -127,6 +127,10 @@ def validate_request_api_key(request: Request, settings: Settings) -> None:
|
|
| 127 |
# No API key configured -> allow
|
| 128 |
return
|
| 129 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 130 |
# Allow Hugging Face private Space signed browser requests for UI pages.
|
| 131 |
# This keeps API routes protected while avoiding 401 on Space shell probes.
|
| 132 |
if _is_hf_signed_page_request(request):
|
|
@@ -202,6 +206,13 @@ def _is_hf_signed_page_request(request: Request) -> bool:
|
|
| 202 |
return "text/html" in accept or "*/*" in accept
|
| 203 |
|
| 204 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 205 |
def require_api_key(
|
| 206 |
request: Request, settings: Settings = Depends(get_settings)
|
| 207 |
) -> None:
|
|
|
|
| 127 |
# No API key configured -> allow
|
| 128 |
return
|
| 129 |
|
| 130 |
+
# Keep Space health/app shell reachable even when API auth is enabled.
|
| 131 |
+
if _is_public_probe_request(request):
|
| 132 |
+
return
|
| 133 |
+
|
| 134 |
# Allow Hugging Face private Space signed browser requests for UI pages.
|
| 135 |
# This keeps API routes protected while avoiding 401 on Space shell probes.
|
| 136 |
if _is_hf_signed_page_request(request):
|
|
|
|
| 206 |
return "text/html" in accept or "*/*" in accept
|
| 207 |
|
| 208 |
|
| 209 |
+
def _is_public_probe_request(request: Request) -> bool:
|
| 210 |
+
"""Return True for read-only public endpoints used by app shells/health checks."""
|
| 211 |
+
if request.method not in {"GET", "HEAD"}:
|
| 212 |
+
return False
|
| 213 |
+
return request.url.path in {"/", "/health"}
|
| 214 |
+
|
| 215 |
+
|
| 216 |
def require_api_key(
|
| 217 |
request: Request, settings: Settings = Depends(get_settings)
|
| 218 |
) -> None:
|
tests/api/test_auth.py
CHANGED
|
@@ -55,3 +55,36 @@ def test_anthropic_auth_token_accepts_bearer_authorization():
|
|
| 55 |
assert r.json()["input_tokens"] == 2
|
| 56 |
|
| 57 |
app.dependency_overrides.clear()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 55 |
assert r.json()["input_tokens"] == 2
|
| 56 |
|
| 57 |
app.dependency_overrides.clear()
|
| 58 |
+
|
| 59 |
+
|
| 60 |
+
def test_public_root_and_health_allowed_when_auth_enabled():
|
| 61 |
+
client = TestClient(app)
|
| 62 |
+
settings = Settings()
|
| 63 |
+
settings.anthropic_auth_token = "public-check"
|
| 64 |
+
app.dependency_overrides[get_settings] = lambda: settings
|
| 65 |
+
|
| 66 |
+
root_response = client.get("/")
|
| 67 |
+
assert root_response.status_code == 200
|
| 68 |
+
|
| 69 |
+
health_response = client.get("/health")
|
| 70 |
+
assert health_response.status_code == 200
|
| 71 |
+
assert health_response.json()["status"] == "healthy"
|
| 72 |
+
|
| 73 |
+
app.dependency_overrides.clear()
|
| 74 |
+
|
| 75 |
+
|
| 76 |
+
def test_api_routes_remain_protected_when_auth_enabled():
|
| 77 |
+
client = TestClient(app)
|
| 78 |
+
settings = Settings()
|
| 79 |
+
settings.anthropic_auth_token = "still-protected"
|
| 80 |
+
app.dependency_overrides[get_settings] = lambda: settings
|
| 81 |
+
|
| 82 |
+
payload = {
|
| 83 |
+
"model": "claude-3-sonnet",
|
| 84 |
+
"messages": [{"role": "user", "content": "hello"}],
|
| 85 |
+
}
|
| 86 |
+
|
| 87 |
+
response = client.post("/v1/messages/count_tokens", json=payload)
|
| 88 |
+
assert response.status_code == 401
|
| 89 |
+
|
| 90 |
+
app.dependency_overrides.clear()
|