• With issues:
  • Use the search tool before opening a new issue.
  • Please provide source code and commit sha if you found a bug.
  • Review existing issues and provide feedback or react to them.

  • go version: "go version go1.11.2 darwin/amd64"

  • gin version (or commit ref): "v1.3.0"
  • operating system: "macos mojave 10.14.2"

Description

I'm trying to use gin-gonic with https://github.com/googollee/go-socket.io . go-socket.io repo is using gorilla's websocket for handling connections etc and it uses hijack inside of it. Problem is, when I pass context (request and responseWriter) into go-socket.io's ServeHTTP method, gin still trying to write headers while upgrading connection. I'm getting "[GIN-debug] [WARNING] Headers were already written. Wanted to override status code 200 with 400" on every connection.

Here are the sample code:

var (
    srv *http.Server
    socketSrv *socketio.Server
)
func main() {
    socketSrv, err = socketio.NewServer(nil)
    if err != nil {
    log.Fatalf("failed to create new socketio server instance.")
    }

    gin.SetMode(gin.DebugMode)
    server := gin.New()
    server.Use(gin.Logger())

    root := server.Group("/")
    {
    root.GET("/", homeHandler)
    root.GET("/stats/", statsHandler)
    root.Handle ("GET", "/socket.io/", handler())
    root.Handle ("WS", "/socket.io/", handler())
    root.Handle ("WSS", "/socket.io/", handler())
    }

    go func() {
    if err := srv.ListenAndServe(); err != nil {
        log.Printf("%v", err)
    }
    }()

    Stop()
}

func Stop() {
    quit := make(chan os.Signal, 1)

    signal.Notify(quit, os.Interrupt, syscall.SIGTERM)

    <-quit

    ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)

    defer cancel()

    if err := srv.Shutdown(ctx); err != nil {
        log.Printf("Server shutdown error: %v", err)
        os.Exit(1)
    }

    log.Printf("Server successfuly stopped.")
}
func initws(c *gin.Context) {
    if c.IsWebsocket() {
        err := socketSrv.On("connection", func(so socketio.Socket) {
            log.Println("on connection")
            so.On("disconnection", func() {
                log.Println("on disconnect")
            })

        })
        if err != nil {
            log.Printf("error :%e", err)
        }
        err = socketSrv.On("error", func(so socketio.Socket, err error) {
            log.Println("error:", err)
        })
        if err != nil {
            log.Printf("error :%e", err)
        }

        socketSrv.ServeHTTP(c.Writer, c.Request)
        return
    }
}

func handler() gin.HandlerFunc {
    return func(context *gin.Context) {
        initws(context)
        context.Abort()
        return
    }
}

Output: [GIN] 2018/12/18 - 17:18:04 | 400 | 117.48µs | ::1 | GET /socket.io/?EIO=3&transport=websocket [GIN-debug] [WARNING] Headers were already written. Wanted to override status code 200 with 400

PS Socket and connection is working fine. Only problem is that log.

Screenshots

Comment From: iquad

Seems like go-socket.io was returning 400 itself then using same connection.

Comment From: doquangtan

Use can use this lib socket.io golang. It is socketio server version 4.x and it can using with client version 3.x, 4.x

import (
    "github.com/gin-gonic/gin"
    socketio "github.com/doquangtan/socket.io/v4"
)

func main() {
    io := socketio.New()

    io.OnConnection(func(socket *socketio.Socket) {
        // ...
    })

    router := gin.Default()
    router.GET("/socket.io/", gin.WrapH(io.HttpHandler()))
    router.Run(":3300")
}