server.go 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. package app
  2. import (
  3. "context"
  4. "fmt"
  5. "net/http"
  6. "os"
  7. "os/signal"
  8. "strconv"
  9. "sync"
  10. "syscall"
  11. "time"
  12. "git.linuxforward.com/byop/byop-engine/auth"
  13. "git.linuxforward.com/byop/byop-engine/config"
  14. "git.linuxforward.com/byop/byop-engine/dbmanager"
  15. "git.linuxforward.com/byop/byop-engine/dbstore"
  16. "git.linuxforward.com/byop/byop-engine/handlers"
  17. mw "git.linuxforward.com/byop/byop-engine/middleware"
  18. "git.linuxforward.com/byop/byop-engine/services"
  19. "github.com/gin-gonic/gin"
  20. "github.com/pkg/errors"
  21. "github.com/sirupsen/logrus"
  22. )
  23. type App struct {
  24. entry *logrus.Entry
  25. cnf *config.Config
  26. ctx context.Context
  27. cancelFunc context.CancelFunc
  28. rtr *gin.Engine
  29. // Database
  30. dbManager dbmanager.DbManager
  31. // Services
  32. authService auth.Service
  33. tokenStore auth.TokenStore
  34. // Modules
  35. authHandler *handlers.AuthHandler
  36. userModule *UserModule
  37. clientModule *ClientModule
  38. componentModule *ComponentModule // formerly appModule
  39. blueprintModule *BlueprintModule // formerly templateModule
  40. deploymentModule *DeploymentModule
  41. // Resource Handlers
  42. providerHandler *handlers.ProviderHandler
  43. // ticketHandler *handlers.TicketHandler
  44. stopped bool
  45. wg sync.WaitGroup
  46. // monitoringHandler *handlers.MonitoringHandler
  47. }
  48. type UserModule struct {
  49. Store *dbstore.UserStore
  50. Service *services.UserService
  51. Handler *handlers.UserHandler
  52. }
  53. type ClientModule struct {
  54. Store *dbstore.ClientStore
  55. Service *services.ClientService
  56. Handler *handlers.ClientHandler
  57. }
  58. type ComponentModule struct {
  59. Store *dbstore.ComponentStore
  60. Service *services.ComponentService
  61. Handler *handlers.ComponentHandler
  62. }
  63. type BlueprintModule struct {
  64. Store *dbstore.BlueprintStore
  65. Service *services.BlueprintService
  66. Handler *handlers.BlueprintHandler
  67. }
  68. type DeploymentModule struct {
  69. Store *dbstore.DeploymentStore
  70. Service *services.DeploymentService
  71. Handler *handlers.DeploymentHandler
  72. }
  73. func NewApp(cnf *config.Config) (*App, error) {
  74. ctx, cancelFunc := context.WithCancel(context.Background())
  75. app := &App{
  76. entry: logrus.WithField("component", "app"),
  77. cnf: cnf,
  78. ctx: ctx,
  79. cancelFunc: cancelFunc,
  80. }
  81. // Initialize router first
  82. if cnf.Debug {
  83. gin.SetMode(gin.DebugMode)
  84. } else {
  85. // Set gin to release mode for production
  86. // This will disable debug logs and enable performance optimizations
  87. gin.SetMode(gin.ReleaseMode)
  88. }
  89. app.rtr = gin.New()
  90. // Disable automatic redirection of trailing slashes
  91. // This prevents 301 redirects that can cause CORS issues
  92. app.rtr.RedirectTrailingSlash = false
  93. app.rtr.RedirectFixedPath = false
  94. app.rtr.Use(gin.Recovery())
  95. app.rtr.Use(mw.Logger)
  96. // Add CORS middleware to handle cross-origin requests
  97. app.rtr.Use(mw.CORS())
  98. // Initialize services and handlers
  99. if err := app.initCommonServices(); err != nil {
  100. return nil, errors.Wrap(err, "initialize services")
  101. }
  102. if err := app.initHandlers(); err != nil {
  103. return nil, errors.Wrap(err, "initialize handlers")
  104. }
  105. // Set up routes after all handlers are initialized
  106. app.setupRoutes()
  107. return app, nil
  108. }
  109. func (a *App) Run() error {
  110. srv := &http.Server{
  111. Addr: fmt.Sprintf(":%s", strconv.Itoa(a.cnf.Server.Port)),
  112. Handler: a.rtr,
  113. }
  114. go func() {
  115. a.entry.WithField("address", srv.Addr).Info("Starting server on port " + strconv.Itoa(a.cnf.Server.Port))
  116. // Handle TLS if configured
  117. if a.cnf.Server.Tls.Enabled {
  118. a.entry.Info("Starting server with TLS...")
  119. err := srv.ListenAndServeTLS(a.cnf.Server.Tls.CertFile, a.cnf.Server.Tls.KeyFile)
  120. if err != nil && err != http.ErrServerClosed {
  121. a.entry.WithError(err).Fatal("Failed to start server")
  122. }
  123. } else {
  124. err := srv.ListenAndServe()
  125. if err != nil && err != http.ErrServerClosed {
  126. a.entry.WithError(err).Fatal("Failed to start server")
  127. }
  128. }
  129. a.entry.Info("Server stopped")
  130. }()
  131. quit := make(chan os.Signal, 1)
  132. signal.Notify(quit, os.Interrupt, syscall.SIGTERM)
  133. <-quit
  134. a.entry.Info("Stopping server...")
  135. ctxTimeout, cancelFunc := context.WithTimeout(context.Background(), 30*time.Second)
  136. defer cancelFunc()
  137. err := srv.Shutdown(ctxTimeout)
  138. if err != nil {
  139. return fmt.Errorf("shutdown server: %w", err)
  140. }
  141. a.entry.Info("Server stopped successfully")
  142. return nil
  143. }