package server import ( "omega-server/local/api" "omega-server/local/middleware/security" "omega-server/local/utl/logging" "os" "time" "github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2/middleware/cors" "github.com/gofiber/fiber/v2/middleware/helmet" "github.com/gofiber/fiber/v2/middleware/recover" "github.com/gofiber/swagger" "go.uber.org/dig" ) func Start(di *dig.Container) *fiber.App { app := fiber.New(fiber.Config{ AppName: "Omega Project Management", ServerHeader: "omega-server", EnablePrintRoutes: true, ReadTimeout: 30 * time.Second, WriteTimeout: 30 * time.Second, IdleTimeout: 120 * time.Second, BodyLimit: 10 * 1024 * 1024, // 10MB Prefork: false, CaseSensitive: false, StrictRouting: false, DisableKeepalive: false, ErrorHandler: func(c *fiber.Ctx, err error) error { // Custom error handler code := fiber.StatusInternalServerError if e, ok := err.(*fiber.Error); ok { code = e.Code } // Log error logging.Error("HTTP Error: %v, Path: %s, Method: %s, IP: %s", err, c.Path(), c.Method(), c.IP()) // Return JSON error response return c.Status(code).JSON(fiber.Map{ "error": err.Error(), "code": code, }) }, }) // Initialize security middleware securityMW := security.NewSecurityMiddleware() // Add recovery middleware first app.Use(recover.New(recover.Config{ EnableStackTrace: true, })) // Add security middleware stack app.Use(securityMW.SecurityHeaders()) app.Use(securityMW.LogSecurityEvents()) app.Use(securityMW.TimeoutMiddleware(30 * time.Second)) app.Use(securityMW.RequestSizeLimit(10 * 1024 * 1024)) // 10MB app.Use(securityMW.ValidateUserAgent()) app.Use(securityMW.ValidateContentType("application/json", "application/x-www-form-urlencoded", "multipart/form-data")) app.Use(securityMW.InputSanitization()) app.Use(securityMW.RateLimit(100, 1*time.Minute)) // 100 requests per minute global // Add Helmet middleware for security headers app.Use(helmet.New(helmet.Config{ XSSProtection: "1; mode=block", ContentTypeNosniff: "nosniff", XFrameOptions: "DENY", HSTSMaxAge: 31536000, HSTSPreloadEnabled: true, ContentSecurityPolicy: "default-src 'self'", ReferrerPolicy: "strict-origin-when-cross-origin", })) // Configure CORS allowedOrigin := os.Getenv("CORS_ALLOWED_ORIGIN") if allowedOrigin == "" { allowedOrigin = "http://localhost:5173" } app.Use(cors.New(cors.Config{ AllowOrigins: allowedOrigin, AllowHeaders: "Origin, Content-Type, Accept, Authorization, X-Requested-With", AllowMethods: "GET, POST, PUT, DELETE, OPTIONS, PATCH", AllowCredentials: true, MaxAge: 86400, // 24 hours })) // Add request logging middleware app.Use(func(c *fiber.Ctx) error { start := time.Now() // Process request err := c.Next() // Log request duration := time.Since(start) logging.InfoResponse( c.Method(), c.Path(), c.Response().StatusCode(), duration.String(), ) return err }) // Swagger documentation app.Get("/swagger/*", swagger.HandlerDefault) // Health check endpoint app.Get("/health", func(c *fiber.Ctx) error { return c.JSON(fiber.Map{ "status": "healthy", "timestamp": time.Now().UTC().Format(time.RFC3339), "version": "1.0.0", }) }) // Ping endpoint app.Get("/ping", func(c *fiber.Ctx) error { return c.SendString("pong") }) // Initialize API routes api.Init(di, app) // 404 handler app.Use(func(c *fiber.Ctx) error { return c.Status(fiber.StatusNotFound).JSON(fiber.Map{ "error": "Route not found", "path": c.Path(), }) }) // Get port from environment port := os.Getenv("PORT") if port == "" { port = "3000" // Default port } logging.Info("Starting server on port %s", port) logging.Info("Swagger documentation available at: http://localhost:%s/swagger/", port) logging.Info("Health check available at: http://localhost:%s/health", port) // Start server if err := app.Listen(":" + port); err != nil { logging.Error("Failed to start server: %v", err) os.Exit(1) } return app }