package main import ( "context" "log" "net/http" "strings" "time" "github.com/jackc/pgx/v5/pgxpool" "github.com/vasyakrg/dns-autoresolver/internal/api" "github.com/vasyakrg/dns-autoresolver/internal/auth" "github.com/vasyakrg/dns-autoresolver/internal/config" "github.com/vasyakrg/dns-autoresolver/internal/crypto" "github.com/vasyakrg/dns-autoresolver/internal/provider/registry" "github.com/vasyakrg/dns-autoresolver/internal/provider/selectel" "github.com/vasyakrg/dns-autoresolver/internal/service" "github.com/vasyakrg/dns-autoresolver/internal/store" "github.com/vasyakrg/dns-autoresolver/internal/web" ) // sessionTTL is how long a login session cookie remains valid before the // user must re-authenticate. const sessionTTL = 720 * time.Hour // isAPIPath reports whether path must be routed to the API router rather // than the SPA. "/api" (no trailing slash) counts as an API path too — // only strings.HasPrefix(path, "/api/") would otherwise miss it and fall // through to the SPA fallback. func isAPIPath(path string) bool { return path == "/api" || strings.HasPrefix(path, "/api/") } func main() { ctx := context.Background() cfg, err := config.Load() if err != nil { log.Fatalf("config: %v", err) } if err := store.Migrate(ctx, cfg.DBDSN); err != nil { log.Fatalf("migrate: %v", err) } pool, err := pgxpool.New(ctx, cfg.DBDSN) if err != nil { log.Fatalf("pool: %v", err) } defer pool.Close() cipher, err := crypto.NewCipher(cfg.EncKey) if err != nil { log.Fatalf("cipher: %v", err) } st := store.New(pool) sessions := auth.NewSessions(st, sessionTTL) reg := registry.New() reg.Register(selectel.New()) svc := service.New(st, st, reg, cipher) a := &api.API{Svc: svc, Store: st, Cipher: cipher, Reg: reg, Auth: st, Sessions: sessions} apiRouter := api.NewRouter(a) webHandler, err := web.Handler() if err != nil { log.Printf("web: static UI unavailable: %v", err) } mux := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if isAPIPath(r.URL.Path) { apiRouter.ServeHTTP(w, r) return } if webHandler != nil { webHandler.ServeHTTP(w, r) return } http.NotFound(w, r) }) log.Printf("listening on %s", cfg.ListenAddr) if err := http.ListenAndServe(cfg.ListenAddr, mux); err != nil { log.Fatal(err) } }