Files
nexarch/cmd/statuspage-devserver/main.go
T
patrickandClaude Sonnet 5 8327a25278
CI / Web-Barrierefreiheitspruefung (axe, Tastatur, Reflow, Textabstaende) (push) Canceled after 0s
CI / Core-Modul (Build/Vet/Test) (push) Canceled after 0s
CI / DMS Security-Test-Gate (AC5, Merge-Gate) (push) Canceled after 0s
CI / DMS-Modul (Lint/Build/Test/Coverage/Artefakt) (push) Canceled after 0s
CI / DMS-Modul Supply-Chain-Scan (govulncheck) (push) Canceled after 0s
CI / Web (dms-browser) (push) Canceled after 0s
CI / Web (pdf-viewer) (push) Canceled after 0s
CI / Web (shl) (push) Canceled after 0s
Core-Schnittstellen-Vertragstests / contract-tests (push) Canceled after 0s
Supply-Chain-Scan (Go) / govulncheck (push) Canceled after 0s
OPS-10: F-24 einheitliche Lauschadressen (127.0.0.1), F-22 Webhook-Ziel-Pruefung (SSRF) und verschluesseltes Signaturgeheimnis
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-22 10:21:25 +02:00

68 lines
2.0 KiB
Go

// statuspage-devserver stellt das OPS-02-Backend (internal/statuspage) fuer
// die Next.js-Statusseite bereit und startet den periodischen Poller.
// Getrennt von cmd/core aus demselben Grund wie die anderen *-devserver.
package main
import (
"context"
"log"
"net/http"
"os"
"strconv"
"time"
"gitea.perlbach24.de/scripte/nexarch/internal/db"
"gitea.perlbach24.de/scripte/nexarch/internal/httpharden"
"gitea.perlbach24.de/scripte/nexarch/internal/statuspage"
)
func main() {
dsn := os.Getenv("NEXARCH_REGISTRY_DSN")
if dsn == "" {
log.Fatal("NEXARCH_REGISTRY_DSN nicht gesetzt")
}
addr := os.Getenv("NEXARCH_STATUSPAGE_LISTEN_ADDR")
if addr == "" {
addr = "127.0.0.1:8084"
}
intervalSeconds := 10
if v := os.Getenv("NEXARCH_STATUSPAGE_POLL_INTERVAL_SECONDS"); v != "" {
if parsed, err := strconv.Atoi(v); err == nil {
intervalSeconds = parsed
}
}
ctx := context.Background()
pool, err := db.Connect(ctx, dsn)
if err != nil {
log.Fatalf("db: %v", err)
}
defer pool.Close()
store := statuspage.NewStore(pool)
checker := statuspage.NewHTTPChecker(2 * time.Second)
poller := statuspage.NewPoller(store, checker)
go poller.Run(ctx, time.Duration(intervalSeconds)*time.Second)
mux := http.NewServeMux()
mux.HandleFunc("/status/overview", withCORS(store.OverviewHandler))
mux.HandleFunc("/status/history", withCORS(store.HistoryHandler))
mux.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) })
log.Printf("statuspage-devserver listening on %s (poll-intervall: %ds)", addr, intervalSeconds)
log.Fatal(httpharden.ListenAndServe(addr, mux))
}
func withCORS(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Methods", "GET, OPTIONS")
w.Header().Set("Access-Control-Allow-Headers", "Content-Type")
if r.Method == http.MethodOptions {
w.WriteHeader(http.StatusOK)
return
}
next(w, r)
}
}