Response does not implement http.Hijacker
Asked Answered
C

2

5

I'm using Go and trying to implement WebSocket in my project. while implementing this. I get "WebSocket: response does not implement HTTP.Hijacker" error. I'm new to this technology. Can anyone help me resolve this?

var upgrader = websocket.Upgrader{
    ReadBufferSize:  1024,
    WriteBufferSize: 1024,
    CheckOrigin: func(r *http.Request) bool {
        return true
    },
} 

func HandleConnections(w http.ResponseWriter, r *http.Request) {
    ws, err := upgrader.Upgrade(w, r, nil)
    if err != nil {
        log.Println("err", err)
        return
    }

    log.Println("hello client")
} 
Claytor answered 19/7, 2020 at 12:16 Comment(0)
H
10

The application is using "middleware" that wraps the net/http server's ResponseWriter implementation. The middleware wrapper does not implement the Hijacker interface.

There are two fixes for the problem:

  • Remove the offending middleware.

  • Implement the Hijacker interface on the middleware wrapper by delegating through to the underlying response. The method implementation will look something like this:

    func (w *wrapper) Hijack() (net.Conn, *bufio.ReadWriter, error) {
        h, ok := w.underlyingResponseWriter.(http.Hijacker)
        if !ok {
            return nil, nil, errors.New("hijack not supported")
        }
        return h.Hijack()
    }
    

If you don't know what the response writer wrapper is, add a statement to print the type from the handler:

func HandleConnections(w http.ResponseWriter, r *http.Request) {
    fmt.Printf("w's type is %T\n", w)
    ...
Hola answered 26/7, 2020 at 6:8 Comment(0)
R
0

To cite the docs on http.Hijacker:

~$ go doc http.Hijacker

package http // import "net/http"

type Hijacker interface {
  // Hijack lets the caller take over the connection.
  // After a call to Hijack the HTTP server library
  // will not do anything else with the connection.
  //
  // It becomes the caller's responsibility to manage
  // and close the connection.
  //
  // The returned net.Conn may have read or write deadlines
  // already set, depending on the configuration of the
  // Server. It is the caller's responsibility to set
  // or clear those deadlines as needed.
  //
  // The returned bufio.Reader may contain unprocessed buffered
  // data from the client.
  //
  // After a call to Hijack, the original Request.Body must not
  // be used. The original Request's Context remains valid and
  // is not canceled until the Request's ServeHTTP method
  // returns.
  Hijack() (net.Conn, *bufio.ReadWriter, error)
}

The Hijacker interface is implemented by ResponseWriters that allow an HTTP handler to take over the connection.

The default ResponseWriter for HTTP/1.x connections supports Hijacker, but HTTP/2 connections intentionally do not. ResponseWriter wrappers may also not support Hijacker. Handlers should always test for this ability at runtime.

So, I see several possibilities for your problem to happen:

  • You're trying to turn an HTTP/2 connection to a Websocket.
  • You're using some "middleware" which wraps whatever object the stock net/http package passes to your handler as net/http.ResponseWriter with something which does not bother to implement the proper Hijack method to support the net/http.Hijacker interface.
Rapper answered 19/7, 2020 at 13:24 Comment(1)
The HTTP/2 scenario is very unlikely because the Gorilla package checks for the WebSocket handshake headers before hijacking the connection. The only way hijack can fail this way is for a client to purposefully send the handshake over HTTP/2 instead of HTTP/1.1 as required by the protocol.Pent

© 2022 - 2024 — McMap. All rights reserved.