Files
decypharr/cmd/healthcheck/main.go
Mukhtar Akere 5aa1c67544 - Add PROPFIND for root path
- Reduce signifcantly memoery footprint
- Fix minor bugs
2025-05-20 12:57:27 +01:00

150 lines
3.4 KiB
Go

package main
import (
"cmp"
"context"
"encoding/json"
"flag"
"fmt"
"github.com/sirrobot01/decypharr/internal/config"
"net/http"
"os"
"strings"
"time"
)
// HealthStatus represents the status of various components
type HealthStatus struct {
QbitAPI bool `json:"qbit_api"`
WebUI bool `json:"web_ui"`
WebDAVService bool `json:"webdav_service"`
OverallStatus bool `json:"overall_status"`
}
func main() {
var configPath string
flag.StringVar(&configPath, "config", "/data", "path to the data folder")
flag.Parse()
config.SetConfigPath(configPath)
cfg := config.Get()
// Get port from environment variable or use default
port := getEnvOrDefault("QBIT_PORT", cfg.Port)
webdavPath := ""
for _, debrid := range cfg.Debrids {
if debrid.UseWebDav {
webdavPath = debrid.Name
}
}
// Initialize status
status := HealthStatus{
QbitAPI: false,
WebUI: false,
WebDAVService: false,
OverallStatus: false,
}
// Create a context with timeout for all HTTP requests
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
baseUrl := cmp.Or(cfg.URLBase, "/")
if !strings.HasPrefix(baseUrl, "/") {
baseUrl = "/" + baseUrl
}
// Check qBittorrent API
if checkQbitAPI(ctx, baseUrl, port) {
status.QbitAPI = true
}
// Check Web UI
if checkWebUI(ctx, baseUrl, port) {
status.WebUI = true
}
// Check WebDAV if enabled
if webdavPath != "" {
if checkWebDAV(ctx, baseUrl, port, webdavPath) {
status.WebDAVService = true
}
} else {
// If WebDAV is not enabled, consider it healthy
status.WebDAVService = true
}
// Determine overall status
// Consider the application healthy if core services are running
status.OverallStatus = status.QbitAPI && status.WebUI
if webdavPath != "" {
status.OverallStatus = status.OverallStatus && status.WebDAVService
}
// Optional: output health status as JSON for logging
if os.Getenv("DEBUG") == "true" {
statusJSON, _ := json.MarshalIndent(status, "", " ")
fmt.Println(string(statusJSON))
}
// Exit with appropriate code
if status.OverallStatus {
os.Exit(0)
} else {
os.Exit(1)
}
}
func getEnvOrDefault(key, defaultValue string) string {
if value, exists := os.LookupEnv(key); exists {
return value
}
return defaultValue
}
func checkQbitAPI(ctx context.Context, baseUrl, port string) bool {
url := fmt.Sprintf("http://localhost:%s%sapi/v2/app/version", port, baseUrl)
req, err := http.NewRequestWithContext(ctx, "GET", url, nil)
if err != nil {
return false
}
resp, err := http.DefaultClient.Do(req)
if err != nil {
return false
}
defer resp.Body.Close()
return resp.StatusCode == http.StatusOK
}
func checkWebUI(ctx context.Context, baseUrl, port string) bool {
req, err := http.NewRequestWithContext(ctx, "GET", fmt.Sprintf("http://localhost:%s%s", port, baseUrl), nil)
if err != nil {
return false
}
resp, err := http.DefaultClient.Do(req)
if err != nil {
return false
}
defer resp.Body.Close()
return resp.StatusCode == http.StatusOK
}
func checkWebDAV(ctx context.Context, baseUrl, port, path string) bool {
url := fmt.Sprintf("http://localhost:%s%swebdav/%s", port, baseUrl, path)
req, err := http.NewRequestWithContext(ctx, "PROPFIND", url, nil)
if err != nil {
return false
}
resp, err := http.DefaultClient.Do(req)
if err != nil {
return false
}
defer resp.Body.Close()
return resp.StatusCode == 207 || resp.StatusCode == http.StatusOK
}