All checks were successful
Dynamic Branch Deploy / build-and-deploy (push) Successful in 7m3s
114 lines
3.2 KiB
Go
114 lines
3.2 KiB
Go
package main
|
|
|
|
import (
|
|
"log"
|
|
"net/http"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/nats-io/nats.go"
|
|
)
|
|
|
|
// SetupGinServer erstellt und konfiguriert den Gin-Server
|
|
func SetupGinServer(ec *nats.EncodedConn, port string) *gin.Engine {
|
|
// Production mode für bessere Performance
|
|
gin.SetMode(gin.ReleaseMode)
|
|
|
|
r := gin.Default()
|
|
|
|
// Logging Middleware (bereits in gin.Default())
|
|
// Custom Logger für bessere Übersicht
|
|
r.Use(gin.LoggerWithFormatter(func(param gin.LogFormatterParams) string {
|
|
return "🌐 " + param.TimeStamp.Format("2006-01-02 15:04:05") +
|
|
" | " + param.Method +
|
|
" | " + string(rune(param.StatusCode)) +
|
|
" | " + param.Latency.String() +
|
|
" | " + param.ClientIP +
|
|
" | " + param.Path + "\n"
|
|
}))
|
|
|
|
// Recovery Middleware
|
|
r.Use(gin.Recovery())
|
|
|
|
// Cache Control Middleware für statische Assets
|
|
r.Use(func(c *gin.Context) {
|
|
path := c.Request.URL.Path
|
|
// Assets (Bilder, Audio, etc.) - 1 Jahr cachen
|
|
if len(path) > 7 && path[:8] == "/assets/" {
|
|
c.Header("Cache-Control", "public, max-age=31536000, immutable")
|
|
}
|
|
// WASM und JS Dateien - nur cachen wenn mit ?v= Parameter
|
|
if (path == "/main.wasm" || path == "/game.js" || path == "/wasm_exec.js") && c.Query("v") != "" {
|
|
c.Header("Cache-Control", "public, max-age=31536000, immutable")
|
|
}
|
|
// CSS und Hintergrundbild - 1 Tag cachen
|
|
if path == "/style.css" || path == "/background.jpg" {
|
|
c.Header("Cache-Control", "public, max-age=86400")
|
|
}
|
|
// HTML - immer neu laden (enthält BUILD_VERSION für Cache-Busting der JS/WASM)
|
|
if path == "/" || path == "/index.html" {
|
|
c.Header("Cache-Control", "no-cache")
|
|
}
|
|
c.Next()
|
|
})
|
|
|
|
// Health Check Endpoint
|
|
r.GET("/health", func(c *gin.Context) {
|
|
c.JSON(200, gin.H{
|
|
"status": "ok",
|
|
"service": "EscapeFromTeacher",
|
|
"version": "1.0.0",
|
|
})
|
|
})
|
|
|
|
// Metrics Endpoint (optional für Kubernetes)
|
|
r.GET("/metrics", func(c *gin.Context) {
|
|
mu.RLock()
|
|
roomCount := len(rooms)
|
|
playerCount := len(playerSessions)
|
|
mu.RUnlock()
|
|
|
|
c.JSON(200, gin.H{
|
|
"rooms": roomCount,
|
|
"players": playerCount,
|
|
})
|
|
})
|
|
|
|
// WebSocket Endpoint
|
|
r.GET("/ws", func(c *gin.Context) {
|
|
handleWebSocketGin(c.Writer, c.Request, ec)
|
|
})
|
|
|
|
// Static Files - Serve Web Client
|
|
r.Static("/assets", "./cmd/client/web/assets")
|
|
r.StaticFile("/", "./cmd/client/web/index.html")
|
|
r.StaticFile("/index.html", "./cmd/client/web/index.html")
|
|
r.StaticFile("/game.js", "./cmd/client/web/game.js")
|
|
r.StaticFile("/style.css", "./cmd/client/web/style.css")
|
|
r.StaticFile("/wasm_exec.js", "./cmd/client/web/wasm_exec.js")
|
|
r.StaticFile("/main.wasm", "./cmd/client/web/main.wasm")
|
|
r.StaticFile("/background.jpg", "./cmd/client/web/background.jpg")
|
|
|
|
// Admin Panel
|
|
RegisterAdminRoutes(r)
|
|
|
|
// 404 Handler
|
|
r.NoRoute(func(c *gin.Context) {
|
|
c.JSON(404, gin.H{
|
|
"error": "Route not found",
|
|
})
|
|
})
|
|
|
|
log.Printf("🚀 Gin-Server konfiguriert auf Port %s", port)
|
|
log.Printf("📁 Statische Dateien: ./cmd/client/web/")
|
|
log.Printf("🌐 WebSocket Endpoint: /ws")
|
|
log.Printf("❤️ Health Check: /health")
|
|
|
|
return r
|
|
}
|
|
|
|
// handleWebSocketGin verwaltet WebSocket-Verbindungen über Gin
|
|
func handleWebSocketGin(w http.ResponseWriter, r *http.Request, ec *nats.EncodedConn) {
|
|
// Verwende die handleWebSocket Funktion aus websocket_gateway.go
|
|
handleWebSocket(w, r, ec)
|
|
}
|