librapi/server/server.go
2025-01-03 10:06:54 +01:00

91 lines
1.7 KiB
Go

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()
}