Use dependency injection for health status and add health router regression test

This commit is contained in:
2026-04-07 20:05:54 +02:00
parent e21f153946
commit 59a56f2e4f
2 changed files with 18 additions and 8 deletions

View File

@@ -6,16 +6,16 @@ state so monitoring tools and Docker health checks can observe daemon status
without probing the socket directly. without probing the socket directly.
""" """
from fastapi import APIRouter, Request from fastapi import APIRouter
from fastapi.responses import JSONResponse from fastapi.responses import JSONResponse
from app.models.server import ServerStatus from app.dependencies import ServerStatusDep
router: APIRouter = APIRouter(prefix="/api", tags=["Health"]) router: APIRouter = APIRouter(prefix="/api", tags=["Health"])
@router.get("/health", summary="Application health check") @router.get("/health", summary="Application health check")
async def health_check(request: Request) -> JSONResponse: async def health_check(server_status: ServerStatusDep) -> JSONResponse:
"""Return 200 with application and fail2ban status. """Return 200 with application and fail2ban status.
HTTP 200 is always returned so Docker health checks do not restart the HTTP 200 is always returned so Docker health checks do not restart the
@@ -23,15 +23,12 @@ async def health_check(request: Request) -> JSONResponse:
``fail2ban`` field in the body indicates the daemon's current state. ``fail2ban`` field in the body indicates the daemon's current state.
Args: Args:
request: FastAPI request (used to read cached server status). server_status: Injected cached server status snapshot.
Returns: Returns:
A JSON object with ``{"status": "ok", "fail2ban": "online"|"offline"}``. A JSON object with ``{"status": "ok", "fail2ban": "online"|"offline"}``.
""" """
cached: ServerStatus = getattr(
request.app.state, "server_status", ServerStatus(online=False)
)
return JSONResponse(content={ return JSONResponse(content={
"status": "ok", "status": "ok",
"fail2ban": "online" if cached.online else "offline", "fail2ban": "online" if server_status.online else "offline",
}) })

View File

@@ -3,6 +3,8 @@
import pytest import pytest
from httpx import AsyncClient from httpx import AsyncClient
from app.models.server import ServerStatus
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_health_check_returns_200(client: AsyncClient) -> None: async def test_health_check_returns_200(client: AsyncClient) -> None:
@@ -25,3 +27,14 @@ async def test_health_check_content_type_is_json(client: AsyncClient) -> None:
"""``GET /api/health`` must set the ``Content-Type`` header to JSON.""" """``GET /api/health`` must set the ``Content-Type`` header to JSON."""
response = await client.get("/api/health") response = await client.get("/api/health")
assert "application/json" in response.headers.get("content-type", "") assert "application/json" in response.headers.get("content-type", "")
@pytest.mark.asyncio
async def test_health_check_respects_cached_server_status(client: AsyncClient) -> None:
"""The health response should reflect the injected cached server status."""
client._transport.app.state.server_status = ServerStatus(online=True)
response = await client.get("/api/health")
assert response.status_code == 200
assert response.json()["fail2ban"] == "online"