ulflow_phattt2901 f4ef71b63b
Some checks failed
CI Pipeline / Security Scan (push) Failing after 5m24s
CI Pipeline / Lint (push) Failing after 5m30s
CI Pipeline / Test (push) Has been skipped
CI Pipeline / Build (push) Has been skipped
CI Pipeline / Notification (push) Successful in 1s
feat: implement user authentication system with JWT and role-based access control
2025-05-24 11:24:19 +07:00

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
}