goshort/internal/server/server.go
2023-08-21 22:39:33 -03:00

79 lines
1.7 KiB
Go

package server
import (
"context"
"fmt"
"net"
"net/http"
"git.maronato.dev/maronato/goshort/internal/config"
servermiddleware "git.maronato.dev/maronato/goshort/internal/server/middleware"
"github.com/go-chi/chi/v5"
"github.com/go-chi/chi/v5/middleware"
"golang.org/x/sync/errgroup"
)
type Server struct {
srv *http.Server
Mux *chi.Mux
}
func NewServer(cfg *config.Config) *Server {
// Parse the address
addr := net.JoinHostPort(cfg.Host, cfg.Port)
// Create the mux
mux := chi.NewRouter()
// Register default middlewares
mux.Use(middleware.RequestID)
mux.Use(middleware.RealIP)
mux.Use(middleware.Logger)
mux.Use(middleware.Recoverer)
mux.Use(servermiddleware.SessionManager(cfg))
mux.Use(middleware.Timeout(config.RequestTimeout))
mux.Mount("/debug", middleware.Profiler())
// Create the server
srv := &http.Server{
Addr: addr,
Handler: mux,
ReadHeaderTimeout: config.ReadHeaderTimeout,
ReadTimeout: config.ReadTimeout,
WriteTimeout: config.WriteTimeout,
IdleTimeout: config.IdleTimeout,
}
return &Server{
srv: srv,
Mux: mux,
}
}
func (s *Server) ListenAndServe(ctx context.Context) error {
// Create the errorgroup that will manage the server execution
eg, egCtx := errgroup.WithContext(ctx)
// Start the server
eg.Go(func() error {
return s.srv.ListenAndServe()
})
// Gracefully shutdown the server when the context is done
eg.Go(func() error {
// Wait for the context to be done
<-egCtx.Done()
return s.srv.Shutdown(
context.Background(),
)
})
// Ignore the error if the context was canceled
if err := eg.Wait(); err != nil && ctx.Err() == nil {
return fmt.Errorf("server exited with error: %w", err)
}
return nil
}