From 8580670b6e58a638819c35f9854b29ca1d95a223 Mon Sep 17 00:00:00 2001 From: David Long Date: Tue, 30 Dec 2025 13:54:30 -0500 Subject: [PATCH] feat(api): add healthcheck endpoint for monitoring health from Docker/Podman (#2024) --- README.md | 6 +++++ .../config/security/SecurityConfig.java | 3 ++- .../controller/HealthcheckController.java | 22 +++++++++++++++++++ example-docker/docker-compose.yml | 6 +++++ example-podman/booklore.container | 6 +++++ 5 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 booklore-api/src/main/java/com/adityachandel/booklore/controller/HealthcheckController.java diff --git a/README.md b/README.md index f2711a7b..29763057 100644 --- a/README.md +++ b/README.md @@ -257,6 +257,12 @@ services: - ./data:/app/data - ./books:/books - ./bookdrop:/bookdrop + healthcheck: + test: wget -q -O - http://localhost:${BOOKLORE_PORT}/api/v1/healthcheck + interval: 60s + retries: 5 + start_period: 60s + timeout: 10s restart: unless-stopped mariadb: diff --git a/booklore-api/src/main/java/com/adityachandel/booklore/config/security/SecurityConfig.java b/booklore-api/src/main/java/com/adityachandel/booklore/config/security/SecurityConfig.java index 00ea62bf..5d418574 100644 --- a/booklore-api/src/main/java/com/adityachandel/booklore/config/security/SecurityConfig.java +++ b/booklore-api/src/main/java/com/adityachandel/booklore/config/security/SecurityConfig.java @@ -50,7 +50,8 @@ public class SecurityConfig { "/kobo/**", // Kobo API requests (auth handled in KoboAuthFilter) "/api/v1/auth/**", // Login and token refresh endpoints (must remain public) "/api/v1/public-settings", // Public endpoint for checking OIDC or other app settings - "/api/v1/setup/**" // Setup wizard endpoints (must remain accessible before initial setup) + "/api/v1/setup/**", // Setup wizard endpoints (must remain accessible before initial setup) + "/api/v1/healthcheck/**" // Healthcheck endpoints (must remain accessible for Docker healthchecks) }; private static final String[] COMMON_UNAUTHENTICATED_ENDPOINTS = { diff --git a/booklore-api/src/main/java/com/adityachandel/booklore/controller/HealthcheckController.java b/booklore-api/src/main/java/com/adityachandel/booklore/controller/HealthcheckController.java new file mode 100644 index 00000000..fe083090 --- /dev/null +++ b/booklore-api/src/main/java/com/adityachandel/booklore/controller/HealthcheckController.java @@ -0,0 +1,22 @@ +package com.adityachandel.booklore.controller; + +import com.adityachandel.booklore.model.dto.response.SuccessResponse; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequestMapping("/api/v1/healthcheck") +@Tag(name = "Healthcheck", description = "Endpoints for checking the healch of the application") +public class HealthcheckController { + + @Operation(summary = "Get a ping response", description = "Check if the application is responding to requests") + @ApiResponse(responseCode = "200", description = "Health status returned successfully") + @GetMapping + public ResponseEntity getPing() { + return ResponseEntity.ok(new SuccessResponse<>(200, "Pong")); + } +} \ No newline at end of file diff --git a/example-docker/docker-compose.yml b/example-docker/docker-compose.yml index 6aecdc05..28dc9a96 100644 --- a/example-docker/docker-compose.yml +++ b/example-docker/docker-compose.yml @@ -26,6 +26,12 @@ services: - ./data:/app/data # Application data (settings, metadata, cache, etc.). Persist this folder to retain your library state across container restarts. - ./books:/books # Primary book library folder. Mount your collection here so BookLore can access and organize your books. - ./bookdrop:/bookdrop # BookDrop folder. Files placed here are automatically detected and prepared for import. + healthcheck: + test: wget -q -O - http://localhost:6060/api/v1/healthcheck + interval: 60s + retries: 5 + start_period: 60s + timeout: 10s restart: unless-stopped mariadb: diff --git a/example-podman/booklore.container b/example-podman/booklore.container index 9af6b0df..f0e01daf 100644 --- a/example-podman/booklore.container +++ b/example-podman/booklore.container @@ -21,3 +21,9 @@ Secret=booklore_db_pass,type=env,target=DATABASE_PASSWORD Environment=DATABASE_URL=jdbc:mariadb://localhost:3306/booklore Environment=DATABASE_USERNAME=booklore Environment=BOOKLORE_PORT=6060 + +HealthCmd=wget -q -O - http://localhost:6060/api/v1/healthcheck +HealthInterval=1m +HealthRetries=5 +HealthStartPeriod=1m +HealthTimeout=10s \ No newline at end of file