init bootstrap
This commit is contained in:
157
local/utl/server/server.go
Normal file
157
local/utl/server/server.go
Normal file
@@ -0,0 +1,157 @@
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user