2025-05-21 12:39:40 +07:00

103 lines
2.3 KiB
Go

package http
import (
"context"
"errors"
"fmt"
"net"
"net/http"
"time"
"github.com/gin-gonic/gin"
"starter-kit/internal/helper/config"
"starter-kit/internal/helper/logger"
)
// ErrServerClosed is returned by the Server's Start method after a call to Shutdown
var ErrServerClosed = errors.New("http: Server closed")
// Server represents the HTTP server
type Server struct {
server *http.Server
config *config.Config
router *gin.Engine
listener net.Listener
serverErr chan error
}
// NewServer creates a new HTTP server with the given configuration
func NewServer(cfg *config.Config) *Server {
// Create a new Gin router
router := SetupRouter(cfg)
// Create the HTTP server
server := &http.Server{
Addr: fmt.Sprintf("%s:%d", cfg.Server.Host, cfg.Server.Port),
Handler: router,
ReadTimeout: time.Duration(cfg.Server.ReadTimeout) * time.Second,
WriteTimeout: time.Duration(cfg.Server.WriteTimeout) * time.Second,
}
return &Server{
server: server,
config: cfg,
router: router,
serverErr: make(chan error, 1),
}
}
// Start starts the HTTP server
func (s *Server) Start() error {
// Create a listener
listener, err := net.Listen("tcp", s.server.Addr)
if err != nil {
return fmt.Errorf("failed to create listener: %w", err)
}
s.listener = listener
// Log server start
logger.WithFields(logger.Fields{
"address": s.server.Addr,
}).Info("Starting HTTP server")
// Start the server in a goroutine
go func() {
s.serverErr <- s.server.Serve(s.listener)
close(s.serverErr)
}()
// Check if server started successfully
select {
case err := <-s.serverErr:
return fmt.Errorf("server failed to start: %w", err)
case <-time.After(100 * time.Millisecond):
logger.Info("HTTP server started successfully")
return nil
}
}
// Shutdown gracefully shuts down the server
func (s *Server) Shutdown(ctx context.Context) error {
logger.Info("Shutting down HTTP server...")
// Try to gracefully shutdown
err := s.server.Shutdown(ctx)
if err != nil {
logger.WithError(err).Error("Error during server shutdown")
return err
}
logger.Info("HTTP server stopped")
return nil
}
// GetRouter returns the underlying router
func (s *Server) GetRouter() *gin.Engine {
return s.router
}
// GetConfig returns the server configuration
func (s *Server) GetConfig() *config.Config {
return s.config
}