package http import ( "context" "fmt" "net/http" "time" "github.com/go-logr/logr" "edge-infra.dev/pkg/lib/fog" graceful "edge-infra.dev/pkg/edge/datasync/internal/shutdown" ) type Server struct { server *http.Server onTeardown func(ctx context.Context) error shouldRun chan bool logger logr.Logger } // NewServer creates a common http server with graceful shutdown to be used by all data sync http servers func NewServer(port string, handler *http.ServeMux, shouldRun chan bool) *Server { newServer := &http.Server{ ReadHeaderTimeout: time.Minute * 1, Addr: fmt.Sprintf(":%s", port), Handler: handler, } logger := fog.New() onTeardown := func(ctx context.Context) error { err := newServer.Shutdown(ctx) if err != nil { logger.Error(err, "error while trying to shutdown http server") return err } // do all teardown work here... logger.Info("http server gracefully stopped") return nil } return &Server{ server: newServer, onTeardown: onTeardown, shouldRun: shouldRun, logger: logger, } } func (s *Server) ListenAndServe() { s.logger.Info("starting to listen to http requests", "address", s.server.Addr) graceful := graceful.NewGraceful() err := graceful.Serve(s.server.ListenAndServe, s.onTeardown) if err != nil { if err != http.ErrServerClosed { s.logger.Error(err, "failed to serve http", "address", s.server.Addr) } if err == http.ErrServerClosed { s.logger.Error(err, "http server was terminated", "address", s.server.Addr) } } s.logger.Info("stopping http server from running", "address", s.server.Addr) s.shouldRun <- false }