chore: add golangci-lint config and fix all lint issues
Enable 15 additional linters (gosec, errorlint, gocritic, modernize, misspell, bodyclose, sqlclosecheck, nilerr, unconvert, durationcheck, sloglint, wastedassign, usestdlibvars) with sensible exclusion rules. Fix all findings: errors.Is for error comparisons, run() pattern in main to avoid exitAfterDefer, ReadHeaderTimeout for Slowloris protection, bounds check in escape sequence reader, WaitGroup.Go, slices.Contains, range-over-int loops, and http.MethodGet constants. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -4,12 +4,14 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
"sync"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"git.t-juice.club/torjus/oubliette/internal/config"
|
||||
"git.t-juice.club/torjus/oubliette/internal/server"
|
||||
@@ -20,13 +22,19 @@ import (
|
||||
const Version = "0.2.0"
|
||||
|
||||
func main() {
|
||||
if err := run(); err != nil {
|
||||
slog.Error("fatal error", "err", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func run() error {
|
||||
configPath := flag.String("config", "oubliette.toml", "path to config file")
|
||||
flag.Parse()
|
||||
|
||||
cfg, err := config.Load(*configPath)
|
||||
if err != nil {
|
||||
slog.Error("failed to load config", "err", err)
|
||||
os.Exit(1)
|
||||
return fmt.Errorf("load config: %w", err)
|
||||
}
|
||||
|
||||
level := new(slog.LevelVar)
|
||||
@@ -53,8 +61,7 @@ func main() {
|
||||
|
||||
store, err := storage.NewSQLiteStore(cfg.Storage.DBPath)
|
||||
if err != nil {
|
||||
logger.Error("failed to open database", "err", err)
|
||||
os.Exit(1)
|
||||
return fmt.Errorf("open database: %w", err)
|
||||
}
|
||||
defer store.Close()
|
||||
|
||||
@@ -65,8 +72,7 @@ func main() {
|
||||
|
||||
srv, err := server.New(*cfg, store, logger)
|
||||
if err != nil {
|
||||
logger.Error("failed to create server", "err", err)
|
||||
os.Exit(1)
|
||||
return fmt.Errorf("create server: %w", err)
|
||||
}
|
||||
|
||||
var wg sync.WaitGroup
|
||||
@@ -75,23 +81,21 @@ func main() {
|
||||
if cfg.Web.Enabled {
|
||||
webHandler, err := web.NewServer(store, logger.With("component", "web"))
|
||||
if err != nil {
|
||||
logger.Error("failed to create web server", "err", err)
|
||||
os.Exit(1)
|
||||
return fmt.Errorf("create web server: %w", err)
|
||||
}
|
||||
|
||||
httpServer := &http.Server{
|
||||
Addr: cfg.Web.ListenAddr,
|
||||
Handler: webHandler,
|
||||
Addr: cfg.Web.ListenAddr,
|
||||
Handler: webHandler,
|
||||
ReadHeaderTimeout: 10 * time.Second,
|
||||
}
|
||||
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
wg.Go(func() {
|
||||
logger.Info("web server listening", "addr", cfg.Web.ListenAddr)
|
||||
if err := httpServer.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) {
|
||||
logger.Error("web server error", "err", err)
|
||||
}
|
||||
}()
|
||||
})
|
||||
|
||||
// Graceful shutdown on context cancellation.
|
||||
go func() {
|
||||
@@ -103,10 +107,10 @@ func main() {
|
||||
}
|
||||
|
||||
if err := srv.ListenAndServe(ctx); err != nil {
|
||||
logger.Error("server error", "err", err)
|
||||
os.Exit(1)
|
||||
return fmt.Errorf("server: %w", err)
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
logger.Info("server stopped")
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user