Description
Version 1.11.0 does not work anymore with github.com/coder/websocket, because it rejects writting headers before Hijack().
In github.com/coder/websocket a fix has been made in 2019 to work with Gin, which calls WriteHeaderNow() before Hijack() in its Accept() function.
But responseWriter.Hijack() first tests for w.Written(), which returns true as size is 0, and returns an error (errHijackAlreadyWritten).
So, for maximum compatibility, and unless there is a good reason to block this, I think you should change
if w.Written() { to if w.size>0 {.
Gin Version
1.11.0
Can you reproduce the bug?
Yes
Source Code
package main
import (
"context"
"log"
"time"
"github.com/coder/websocket"
"github.com/gin-gonic/gin"
)
func main() {
r := gin.Default()
r.Any("/ws", func(c *gin.Context) {
ws, err := websocket.Accept(c.Writer, c.Request, nil)
if err != nil {
// This is were we receive errHijackAlreadyWritten
log.Print("Websocket upgrade failed: ", err)
return
}
defer ws.Close(websocket.StatusNormalClosure, "")
})
go r.Run()
// Let the server start...
time.Sleep(time.Second)
// Try to open the websocket
ws, _, err := websocket.Dial(context.Background(), "ws://localhost:8080/ws", nil)
if err != nil {
log.Fatalf("FAILED to dial websocket: %v", err)
}
defer ws.Close(websocket.StatusGoingAway, "leaving")
}
Go Version
1.25.1
Operating System
UbuntU 24.04
Comment From: appleboy
See the PR: https://github.com/gin-gonic/gin/pull/4373