106 lines
2.4 KiB
Go
106 lines
2.4 KiB
Go
package http
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"net"
|
|
"net/http"
|
|
"time"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"gorm.io/gorm"
|
|
"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
|
|
db *gorm.DB
|
|
serverErr chan error
|
|
}
|
|
|
|
// NewServer creates a new HTTP server with the given configuration
|
|
func NewServer(cfg *config.Config, db *gorm.DB) *Server {
|
|
// Create a new Gin router
|
|
router := SetupRouter(cfg, db)
|
|
|
|
// 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,
|
|
db: db,
|
|
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
|
|
}
|