-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathserver.go
More file actions
159 lines (134 loc) · 5.73 KB
/
server.go
File metadata and controls
159 lines (134 loc) · 5.73 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
/*
Server - Core HTTP Server Implementation for Everato
This file implements the HTTP server for the Everato platform, handling route setup,
middleware configuration, and server startup. It follows a clean architecture approach
with separate API and view routes.
*/
package main
import (
"net/http"
"strconv"
"github.com/gorilla/mux"
"github.com/dtg-lucifer/everato/config"
_ "github.com/dtg-lucifer/everato/internal/handlers"
"github.com/dtg-lucifer/everato/internal/handlers/v1/api"
"github.com/dtg-lucifer/everato/internal/middlewares"
"github.com/dtg-lucifer/everato/pkg"
)
// Server represents the HTTP server instance for the Everato application.
// It encapsulates the router and application configuration.
type Server struct {
Router *mux.Router // HTTP router that handles all incoming requests
Cfg *config.Config // Application configuration
}
// NewServer initializes and returns a new Server instance with the provided configuration.
// It sets up all necessary components like middlewares, routes, and static file handlers.
//
// Parameters:
// - cfg: Application configuration containing server settings, database details, etc.
//
// Returns:
// - A fully initialized Server instance ready to be started
func NewServer(cfg *config.Config) *Server {
router := mux.NewRouter()
logger := pkg.NewLogger()
defer logger.Close() // Ensure the logger is closed when the server is done
server := &Server{
Router: router,
Cfg: cfg,
}
server.initializeStaticFS() // Initialize the static file system to serve files
server.initializeMiddlewares() // Initialize the middlewares for the server
server.initializeRoutes() // Initialize the routes for the server
return server
}
// initializeMiddlewares configures all global middlewares for the server.
// These middlewares will be applied to all routes.
//
// Middleware chain:
// 1. RequestID - Adds a unique identifier to each request
// 2. CORS - Handles Cross-Origin Resource Sharing
// 3. Logger - Logs all HTTP requests
// 4. Timeout - Enforces request timeout limits from configuration
func (s *Server) initializeMiddlewares() {
s.Router.Use(middlewares.RequestIDMiddleware)
s.Router.Use(middlewares.CorsMiddleware)
s.Router.Use(middlewares.LoggerMiddleware)
// Add a timeout middleware based on the configuration
s.Router.Use(middlewares.TimeoutMiddleware(s.Cfg.RequestTimeout))
}
// initializeRoutes sets up all API routes for the application.
// Routes are grouped by functionality and registered with the appropriate handlers.
//
// Route groups:
// - General: Health check and metrics endpoints
// - Authentication: User registration, login, verification
// - Events: Event creation, management, and search
//
// All API routes are prefixed with the configured API prefix (e.g., /api/v1)
func (s *Server) initializeRoutes() {
// Setting up the API prefix
apivx := s.Router.PathPrefix(s.Cfg.ApiPrefix).Subrouter()
// Route Group: General
// Health check and monitoring endpoints
api.NewHealthCheckHandler().RegisterRoutes(apivx)
api.NewMetricsHandler().RegisterRoutes(apivx)
// Route Group: Admin
// Admin login, creation and RBAC control
api.NewAdminHandler(s.Cfg).RegisterRoutes(apivx)
// Route Group: Authentication
// User registration, login, verification, etc.
api.NewAuthHandler(s.Cfg).RegisterRoutes(apivx)
// Route Group: Events
// Event creation, management, search, etc.
api.NewEventHandler(s.Cfg).RegisterRoutes(apivx)
// Route Group: Dashboard
// Dashboard statistics and analytics
api.NewDashboardHandler(s.Cfg).RegisterRoutes(apivx)
// --------------------------------------------------------------
// @TODO: User routes - User profile, management, etc.
// --------------------------------------------------------------
// @TODO: Ticket routes - Ticket creation, validation, etc.
// @TODO: Notification routes - Email/push notifications, etc.
// Register the NotFound handler for unmatched routes
api.NewNotFoundHandler().RegisterRoutes(apivx)
}
// initializeStaticFS configures static file serving for the application.
// In development mode, it serves files directly from the filesystem.
// In production mode, it serves files from the embedded filesystem.
//
// Static files include CSS, JavaScript, images, and other assets.
func (s *Server) initializeStaticFS() {
// Serve static files from the public directory
// The PublicFS() function is defined differently in dev/prod builds
s.Router.PathPrefix("/public").Handler(http.StripPrefix("/public", PublicFS()))
// Serve the static UI from the dist directory
s.Router.PathPrefix("/www").Handler(http.StripPrefix("/www", ViewsFS()))
}
// Start begins listening for HTTP requests on the configured port.
// This method is blocking and will only return if there's an error starting the server.
//
// Returns:
// - An error if the server fails to start or encounters a fatal error while running
func (s *Server) Start() error {
logger := pkg.NewLogger()
defer logger.Close() // Ensure the logger is closed when the server is done
// Construct the server address from the configured port
addr := ":" + strconv.Itoa(s.Cfg.Server.Port)
logger.Info("Server started running on", "port", addr)
// Start the HTTP server with the configured router
// This call is blocking and will only return on error
return http.ListenAndServe(addr, s.Router)
}
// Stop gracefully stops the server.
//
// This will recieve a shutdown signal and perform any necessary cleanup.
//
// @TODO
func (s *Server) Stop(close_chan chan int) {
logger := pkg.NewLogger()
defer logger.Close() // Ensure the logger is closed when the server is done
// Perform any necessary cleanup here, such as closing database connections, etc.
logger.Info("Server is stopping gracefully")
// Currently, there's no specific cleanup logic, but this is where it would go
}