package main import ( "context" "log/slog" "net" "net/http" "os" "os/signal" "syscall" "time" "github.com/telemt/telemt-api/internal/config" "github.com/telemt/telemt-api/internal/geoip" "github.com/telemt/telemt-api/internal/server" ) func main() { log := slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{Level: slog.LevelInfo})) cfgPath := os.Getenv("CONFIG_PATH") if cfgPath == "" { cfgPath = "/etc/telemt-gateway/config.yaml" } cfg, err := config.Load(cfgPath) if err != nil { log.Error("config load failed", "path", cfgPath, "err", err) os.Exit(1) } parsed, err := cfg.Parse() if err != nil { log.Error("config parse failed", "err", err) os.Exit(1) } geoDown := &http.Client{ Transport: &http.Transport{ DialContext: (&net.Dialer{Timeout: 30 * time.Second}).DialContext, ResponseHeaderTimeout: 5 * time.Minute, }, Timeout: 15 * time.Minute, } geo, err := geoip.FromConfig(parsed.Config.GeoIP, geoDown, log) if err != nil { log.Error("geoip init failed", "err", err) os.Exit(1) } gw, err := server.NewGateway(parsed, log, geo) if err != nil { log.Error("gateway init failed", "err", err) os.Exit(1) } srv := &http.Server{ Addr: parsed.Config.Listen, Handler: gw.Handler(), ReadHeaderTimeout: 10 * time.Second, ReadTimeout: 0, WriteTimeout: 0, IdleTimeout: 120 * time.Second, } go func() { log.Info("listening", "addr", parsed.Config.Listen) if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed { log.Error("server error", "err", err) os.Exit(1) } }() sig := make(chan os.Signal, 1) signal.Notify(sig, syscall.SIGINT, syscall.SIGTERM) <-sig log.Info("shutdown signal") ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second) defer cancel() _ = gw.Shutdown(ctx) if err := srv.Shutdown(ctx); err != nil { log.Error("shutdown error", "err", err) } }