Files
omega-server/local/utl/server/server.go
Fran Jurmanović 016728532c init bootstrap
2025-07-06 15:02:09 +02:00

158 lines
4.1 KiB
Go

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
}