package server import ( "context" "fmt" "log" "net/http" "time" "github.com/jackc/pgx/v5/pgxpool" "github.com/panelhosting/panel/internal/handler" "github.com/panelhosting/panel/internal/repository" "github.com/panelhosting/panel/internal/setup" ) type Server struct { httpServer *http.Server } func New(pool *pgxpool.Pool, addr string) (*Server, error) { users := repository.NewUserRepository(pool) setupSvc := setup.NewService(users) setupHandler := handler.NewSetupHandler(setupSvc) setupRequired, err := setupSvc.Status(context.Background()) if err != nil { return nil, fmt.Errorf("check setup status: %w", err) } if setupRequired { log.Println("setup required: open / to create first admin") } mux := http.NewServeMux() mux.HandleFunc("GET /health", handler.Health) mux.HandleFunc("GET /api/v1/setup/status", setupHandler.Status) mux.HandleFunc("POST /api/v1/setup/register", setupHandler.Register) mux.HandleFunc("GET /{$}", handler.IndexPage(setupSvc)) return &Server{ httpServer: &http.Server{ Addr: addr, Handler: loggingMiddleware(mux), ReadTimeout: 15 * time.Second, WriteTimeout: 15 * time.Second, IdleTimeout: 60 * time.Second, }, }, nil } func (s *Server) Start() error { log.Printf("panel listening on %s", s.httpServer.Addr) return s.httpServer.ListenAndServe() } func (s *Server) Shutdown(ctx context.Context) error { return s.httpServer.Shutdown(ctx) } func loggingMiddleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { start := time.Now() next.ServeHTTP(w, r) log.Printf("%s %s %s", r.Method, r.URL.Path, time.Since(start).Round(time.Millisecond)) }) }