From f0e6c09bce84c6d147068f596f70ec18b05fe5ba Mon Sep 17 00:00:00 2001 From: db1234719 Date: Mon, 4 May 2026 08:15:46 +0330 Subject: [PATCH] feat: made it standard openapi and removed comments --- main.go | 85 +++++++++++++++++++++++++++------------------------------ 1 file changed, 40 insertions(+), 45 deletions(-) diff --git a/main.go b/main.go index 430f1e7..1f0300a 100644 --- a/main.go +++ b/main.go @@ -1,24 +1,8 @@ -// main.go — auth-gate entry point -// -// This file wires together configuration loading, the HTTP server, and the -// background processes (permanent-whitelist file watcher, temporary-whitelist -// cleanup). -// -// Why this structure? -// -// - Main keeps the wiring thin. Each component (config, auth, cleanup, watcher) -// owns its own logic so we can test and reason about them independently. -// - We don't embed the HTTP server logic inside main; instead main calls -// createAuthHandler(config) and server.Serve(). This makes the handler -// functionally pure (aside from config reads) and easier to mock. -// - The background goroutines are started explicitly so we can stop them on -// SIGTERM without leaking resources. - package main import ( "context" - "log" + "log/slog" "net/http" "os" "os/signal" @@ -28,48 +12,59 @@ import ( func main() { cfg := loadConfig() + slog.SetDefault(slog.New(slog.NewTextHandler(os.Stdout, nil))) - // Load the permanent whitelist from disk once at startup. - // We reload it periodically via watcher (see watcher.go). - loadPermanentWhitelist(cfg.PermanentWhitelistFile) + db, err := initDB(cfg.DBPath) + if err != nil { + slog.Error("failed to init database", "error", err) + os.Exit(1) + } + defer db.Close() - // Start the background watcher that reloads the permanent whitelist file. - // It only reloads when the file actually changes (mtime comparison), so - // frequent touch-operations don't cause unnecessary restarts. - w := newPermanentWhitelistWatcher(cfg.PermanentWhitelistFile, cfg.WatchInterval, cfg.PermanentWhitelist) - w.start() + perm := newPermanentWhitelist() + tw := newTempWhitelist() - // Start the cleanup goroutine that expires temporary whitelisted IPs - // whose TTL has elapsed. It runs every cfg.CleanupInterval. - go cleanupLoop(cfg.TemporaryWhitelist, cfg.CleanupInterval) + watcher := newPermanentWhitelistWatcher(cfg.PermanentWhitelistFile, cfg.WatchInterval, perm) + watcher.start() + + go cleanupLoop(tw, cfg.CleanupInterval) + + server := newAuthServer(cfg, tw, perm, db) - // Build the HTTP server. addr := ":" + cfg.Port - server := newAuthServer(cfg, addr) - - // Start serving in a goroutine so we can do graceful shutdown. go func() { - log.Printf("auth-gate listening on %s", addr) + slog.Info("starting server", "addr", addr) if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed { - log.Fatalf("server error: %v", err) + slog.Error("server error", "error", err) + os.Exit(1) } }() - // Graceful shutdown on SIGTERM / SIGINT. - // - // We wait for a signal, then call server.Shutdown(ctx) which: - // 1. Stops accepting new connections - // 2. Closes idle connections - // 3. Waits for in-flight requests to complete (up to 30s) - // - // This is important for Docker deployments: without it the container - // would be killed mid-request and clients would see connection errors. quit := make(chan os.Signal, 1) signal.Notify(quit, syscall.SIGTERM, syscall.SIGINT) <-quit - log.Println("shutting down...") + slog.Info("shutting down...") ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() - server.Shutdown(ctx) + if err := server.Shutdown(ctx); err != nil { + slog.Error("shutdown error", "error", err) + } } + +func newAuthServer(cfg Config, tw *tempWhitelist, perm *PermanentWhitelist, db *sql.DB) *http.Server { + mux := http.NewServeMux() + mux.HandleFunc("/auth", authHandler(cfg, tw, perm)) + mux.HandleFunc("/api/whitelist/temp", tw.whitelistTempHandler(cfg, db)) + mux.HandleFunc("/api/whitelist", tw.whitelistListHandler(cfg)) + mux.HandleFunc("/api/whitelist/{ip}", tw.whitelistDeleteHandler(cfg, db)) + mux.HandleFunc("/api/logs", logsHandler(cfg, db)) + mux.HandleFunc("/status", statusHandler) + + return &http.Server{ + Addr: ":" + cfg.Port, + Handler: mux, + ReadTimeout: 10 * time.Second, + WriteTimeout: 30 * time.Second, + } +} \ No newline at end of file