Skip to content

Commit 0c6edf7

Browse files
committed
fix: add auth header to LiteLLM health check
1 parent cea76af commit 0c6edf7

2 files changed

Lines changed: 72 additions & 1 deletion

File tree

app/api/routes/health.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,10 @@ async def health_check() -> HealthResponse:
2828
try:
2929
async with httpx.AsyncClient(timeout=5.0) as client:
3030
url = f"{settings.LITELLM_BASE_URL.rstrip('/')}/health"
31-
response = await client.get(url)
31+
headers = {}
32+
if settings.LITELLM_API_KEY:
33+
headers["Authorization"] = f"Bearer {settings.LITELLM_API_KEY}"
34+
response = await client.get(url, headers=headers)
3235
litellm_available = response.status_code == 200
3336
except Exception as e:
3437
logger.warning(f"LiteLLM health check failed: {e}")

tests/test_health.py

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
from unittest.mock import AsyncMock, MagicMock, patch
2+
3+
import pytest
4+
5+
6+
@pytest.mark.asyncio
7+
async def test_health_check_sends_auth_header():
8+
"""
9+
Test that health check sends Authorization header to LiteLLM.
10+
"""
11+
with patch("app.api.routes.health.settings") as mock_settings:
12+
mock_settings.LITELLM_BASE_URL = "http://litellm:4000"
13+
mock_settings.LITELLM_API_KEY = "sk-test-key"
14+
mock_settings.openai_available = False
15+
mock_settings.gemini_available = False
16+
17+
mock_response = MagicMock()
18+
mock_response.status_code = 200
19+
20+
mock_client_instance = MagicMock()
21+
mock_client_instance.get = AsyncMock(return_value=mock_response)
22+
23+
mock_client = MagicMock()
24+
mock_client.__aenter__ = AsyncMock(return_value=mock_client_instance)
25+
mock_client.__aexit__ = AsyncMock(return_value=None)
26+
27+
with patch("app.api.routes.health.httpx.AsyncClient", return_value=mock_client):
28+
from app.api.routes.health import health_check
29+
30+
await health_check()
31+
32+
# Verify auth header was sent
33+
mock_client_instance.get.assert_called_once()
34+
call_args = mock_client_instance.get.call_args
35+
assert "headers" in call_args.kwargs
36+
assert call_args.kwargs["headers"]["Authorization"] == "Bearer sk-test-key"
37+
38+
39+
@pytest.mark.asyncio
40+
async def test_health_check_no_auth_when_no_key():
41+
"""
42+
Test that health check doesn't send auth header when LITELLM_API_KEY is not set.
43+
"""
44+
with patch("app.api.routes.health.settings") as mock_settings:
45+
mock_settings.LITELLM_BASE_URL = "http://litellm:4000"
46+
mock_settings.LITELLM_API_KEY = None
47+
mock_settings.openai_available = False
48+
mock_settings.gemini_available = False
49+
50+
mock_response = MagicMock()
51+
mock_response.status_code = 200
52+
53+
mock_client_instance = MagicMock()
54+
mock_client_instance.get = AsyncMock(return_value=mock_response)
55+
56+
mock_client = MagicMock()
57+
mock_client.__aenter__ = AsyncMock(return_value=mock_client_instance)
58+
mock_client.__aexit__ = AsyncMock(return_value=None)
59+
60+
with patch("app.api.routes.health.httpx.AsyncClient", return_value=mock_client):
61+
from app.api.routes.health import health_check
62+
63+
await health_check()
64+
65+
# Verify empty headers were sent (no auth)
66+
mock_client_instance.get.assert_called_once()
67+
call_args = mock_client_instance.get.call_args
68+
assert call_args.kwargs["headers"] == {}

0 commit comments

Comments
 (0)