diff --git a/README.md b/README.md index 50825d3..fc9ac19 100644 --- a/README.md +++ b/README.md @@ -20,8 +20,9 @@ poetry run uvicorn fdhview.main:app --reload ## Endpoints -* GET `/admin` - upload form protected with Basic Auth. +* GET `/admin` - upload form protected with Basic Auth * POST `/admin/upload` - upload endpoint protected with Basic Auth +* GET `/health` - Health check endpoint * GET `/info` - serves desk info endpoint * GET `/api/screenings` - serves JSON with upcoming 10 films for today * GET `/api/screenings/prices` - serves JSON with pricing data diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index 65b151e..4864e1b 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -5,5 +5,11 @@ services: dockerfile: docker/Dockerfile ports: - "8000:8000" + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:8080/health"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 40s environment: SQL_FILE_NAME: ${SQL_FILE_NAME:-/data/app.db} diff --git a/fdhview/api/health.py b/fdhview/api/health.py new file mode 100644 index 0000000..491b76c --- /dev/null +++ b/fdhview/api/health.py @@ -0,0 +1,34 @@ +from fastapi import APIRouter, status +from pydantic import BaseModel + +router = APIRouter( + prefix="/health", + tags=["Health"] +) + + +class HealthCheck(BaseModel): + """Response model to validate and return when performing a health check.""" + + status: str = "OK" + + +@router.get( + "/", + tags=["healthcheck"], + summary="Perform a Health Check", + response_description="Return HTTP Status Code 200 (OK)", + status_code=status.HTTP_200_OK, + response_model=HealthCheck, +) +def get_health() -> HealthCheck: + """ + ## Perform a Health Check + Endpoint to perform a healthcheck on. This endpoint can primarily be used Docker + to ensure a robust container orchestration and management is in place. Other + services which rely on proper functioning of the API service will not deploy if this + endpoint returns any other HTTP status code except 200 (OK). + Returns: + HealthCheck: Returns a JSON response with the health status + """ + return HealthCheck(status="OK") diff --git a/fdhview/main.py b/fdhview/main.py index 946ca52..92547c1 100644 --- a/fdhview/main.py +++ b/fdhview/main.py @@ -8,6 +8,7 @@ from fastapi import FastAPI from fastapi.staticfiles import StaticFiles from fdhview.api.admin import router as admin_router +from fdhview.api.health import router as health_router from fdhview.api.info import router as info_router from fdhview.api.screenings import router as screenings_router from fdhview.core.database import init_db @@ -27,5 +28,6 @@ BASE_DIR = Path(__file__).resolve().parent app.mount("/static", StaticFiles(directory=BASE_DIR / "static"), name="static") app.include_router(admin_router) -app.include_router(screenings_router, prefix="/api") +app.include_router(health_router) app.include_router(info_router) +app.include_router(screenings_router, prefix="/api") diff --git a/tests/test_health.py b/tests/test_health.py new file mode 100644 index 0000000..f54628c --- /dev/null +++ b/tests/test_health.py @@ -0,0 +1,9 @@ +# SPDX-FileCopyrightText: 2026 Filmhuis Den Haag +# SPDX-License-Identifier: AGPL-3.0-or-later + +from fastapi.testclient import TestClient + + +def test_health(client: TestClient): + response = client.get("/health") + assert response.status_code == 200