b6ecd613d4
- Project structure: cmd/boosapi, internal/, pkg/ - Config loader (all env vars from Node.js original) - Database layer with SQLite/MySQL/Postgres support - Migration runner (sequential SQL files) - Health check endpoint (GET /healthz) - HTTP middleware: logger, auth, CORS, panic recovery - chi router with /admin, /v1, /api route groups - Graceful shutdown (SIGINT/SIGTERM) - Multi-stage Dockerfile (alpine, ~20MB image) - Initial schema migration (users, api_keys, sites, usage_logs) Signed-off-by: Boos4721 <boos4721@icloud.com>
56 lines
1.2 KiB
Go
56 lines
1.2 KiB
Go
package handler
|
|
|
|
import (
|
|
"database/sql"
|
|
"encoding/json"
|
|
"net/http"
|
|
"time"
|
|
)
|
|
|
|
// HealthHandler returns the service health status.
|
|
type HealthHandler struct {
|
|
db *sql.DB
|
|
startedAt time.Time
|
|
version string
|
|
}
|
|
|
|
// NewHealthHandler creates a new health handler.
|
|
func NewHealthHandler(db *sql.DB, version string) *HealthHandler {
|
|
return &HealthHandler{
|
|
db: db,
|
|
startedAt: time.Now(),
|
|
version: version,
|
|
}
|
|
}
|
|
|
|
type healthResponse struct {
|
|
Status string `json:"status"`
|
|
Version string `json:"version,omitempty"`
|
|
Uptime string `json:"uptime,omitempty"`
|
|
Database string `json:"database"`
|
|
Timestamp string `json:"timestamp"`
|
|
}
|
|
|
|
// ServeHTTP handles GET /healthz
|
|
func (h *HealthHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|
dbStatus := "ok"
|
|
if err := h.db.Ping(); err != nil {
|
|
dbStatus = "error: " + err.Error()
|
|
}
|
|
|
|
resp := healthResponse{
|
|
Status: "ok",
|
|
Version: h.version,
|
|
Uptime: time.Since(h.startedAt).Round(time.Second).String(),
|
|
Database: dbStatus,
|
|
Timestamp: time.Now().UTC().Format(time.RFC3339),
|
|
}
|
|
|
|
if dbStatus != "ok" {
|
|
resp.Status = "degraded"
|
|
}
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
json.NewEncoder(w).Encode(resp)
|
|
}
|