package main import ( // "flag" // "fmt" "embed" "fmt" "net/http" "strings" "github.com/gin-contrib/gzip" "github.com/gin-gonic/gin" "github.com/google/uuid" "github.com/gorilla/websocket" ) //go:embed toe var staticFiles embed.FS var waitingPlayers = make(map[string][]*websocket.Conn) func SetCustomContentType() gin.HandlerFunc { return func(c *gin.Context) { requestPath := c.Request.URL.Path if strings.Contains(requestPath, ".") { c.Header("Cache-Control", "public, max-age=31536000, immutable") } if strings.HasPrefix(requestPath, "/tic/tac/toe") && !strings.Contains(requestPath, ".") { c.Header("Content-Type", "text/html; charset=UTF-8") } else if strings.HasSuffix(requestPath, ".ico") { c.Header("Content-Type", "image/svg+xml") } else if strings.HasSuffix(requestPath, ".js") { c.Header("Content-Type", "application/javascript") } else if strings.HasSuffix(requestPath, ".css") { c.Header("Content-Type", "text/css") } c.Next() } } func multiplayerHandler(c *gin.Context) { if c.GetHeader("Accept") == "*/*" { c.String(http.StatusTeapot, "Preload not allowed") } if c.Query("g") == "" { u, err := uuid.NewV7() if err != nil { fmt.Println("Error:", err) return } c.Redirect(http.StatusPermanentRedirect, "/multiplayer?g="+u.String()) } c.Header("Content-Type", "text/html; charset=UTF-8") c.String(http.StatusOK, "") } var upgrader = websocket.Upgrader{ CheckOrigin: func(r *http.Request) bool { origin := r.Header.Get("Origin") host := r.Host return origin == "http://"+host || origin == "https://"+host }, } func wsHandler(c *gin.Context) { game_id := c.Query("g") if game_id == "" { c.String(http.StatusTeapot, "No game id") return } conn, err := upgrader.Upgrade(c.Writer, c.Request, nil) if err != nil { fmt.Println("Upgrade error:", err) return } fmt.Println("New client connected") waitingPlayers[game_id] = append(waitingPlayers[game_id], conn) defer func() { conn.Close() fmt.Println("Client disconnected") }() for { messageType, message, err := conn.ReadMessage() if err != nil { fmt.Println("Read error:", err) break } fmt.Printf("Received: %s\n", message) // Рассылка всем клиентам for _, c := range waitingPlayers[game_id] { if c != conn { err := c.WriteMessage(messageType, message) if err != nil { fmt.Println("Broadcast error:", err) } } } } } var favicon = "" func main() { embeddedFilesSystem := http.FS(staticFiles) router := gin.Default() router.Use(SetCustomContentType()) router.Use(gzip.Gzip(gzip.DefaultCompression)) router.GET("/", func(c *gin.Context) { c.Redirect(http.StatusMovedPermanently, "/tic/tac/toe/index") }) router.GET("/favicon.ico", func(c *gin.Context) { c.String(http.StatusOK, favicon) }) router.GET("/ws", wsHandler) router.GET("/multiplayer", multiplayerHandler) router.StaticFS("/tic/tac", embeddedFilesSystem) router.Run(":8080") }