package server import ( "context" "errors" "librapi/services" "net/http" "strconv" "time" "github.com/rs/zerolog/log" ) const ( ServerShutdownTimeout = 10 * time.Second ServerReadTimeout = 5 * time.Second ) type Handler struct { url string fnHandle func(http.ResponseWriter, *http.Request) } func NewHandler(url string, fnHandle func(http.ResponseWriter, *http.Request)) Handler { return Handler{url: url, fnHandle: fnHandle} } type Server struct { *http.Server ctx context.Context } type ServerOption func() func NewServer(ctx context.Context, port int, handlers ...Handler) Server { if port == 0 { log.Warn().Int("port", services.GetEnv().GetPort()).Msg("no port detected, set to default") port = services.GetEnv().GetPort() } srvmux := http.NewServeMux() for _, h := range handlers { srvmux.HandleFunc(h.url, h.fnHandle) } srv := http.Server{ Addr: ":" + strconv.Itoa(port), Handler: srvmux, ReadTimeout: ServerReadTimeout, } server := Server{ Server: &srv, ctx: ctx, } go func() { <-ctx.Done() if err := server.Stop(); err != nil { log.Err(err).Msg("unable to stop the server correctly") } }() return server } func (srv *Server) Serve() { log.Info().Str("addr", srv.Addr).Msg("http server listening") if err := srv.ListenAndServe(); err != nil { if !errors.Is(err, http.ErrServerClosed) { log.Err(err).Msg("error occurred while serving server") return } log.Info().Msg("server stopped") } } func (srv *Server) Stop() error { log.Info().Msg("stopping server...") shutdownCtx, fnCancel := context.WithTimeout(srv.ctx, ServerShutdownTimeout) defer fnCancel() return srv.Shutdown(shutdownCtx) } func (srv *Server) Done() <-chan struct{} { return srv.ctx.Done() }