xrfang
xrfang

Reputation: 2333

check whether http connection is hijacked in go server

I am writing an HTTP server in Go, which uses the following pattern to handle API output:

func handler(w http.ResponsWriter, r *http.Request) {
    defer reply(w, r, L)() //L is a Logger
    //do things...
}

func reply(w http.ResponseWriter, r *http.Request, log Logger) func() {
    cid := []byte{0, 0, 0, 0}
    if log != nil {
        rand.Read(cid)
        log.Debug("[%x] %s %s", cid, r.Method, r.URL.String())
    }
    entry := time.Now()
    return func() {
        if log != nil {
            defer log.Debug("[%x] elapsed %d millis", cid, time.Since(entry).Milliseconds())
        }
        _, err := w.Write(nil)
        if err == http.ErrHijacked {
            return //API is a WEBSOCKET entry point, do nothing
        }
        //handle common output logic for normal HTTP APIs...
    }
}

The reason I do this, is that I found this comment in the standard library:

// ErrHijacked is returned by ResponseWriter.Write calls when
// the underlying connection has been hijacked using the
// Hijacker interface. A zero-byte write on a hijacked
// connection will return ErrHijacked without any other side
// effects.
ErrHijacked = errors.New("http: connection has been hijacked")

However following the Write() method, I got this comment:

// Write writes the data to the connection as part of an HTTP reply.
//
// If WriteHeader has not yet been called, Write calls
// WriteHeader(http.StatusOK) before writing the data. If the Header
// does not contain a Content-Type line, Write adds a Content-Type set
// to the result of passing the initial 512 bytes of written data to
// ...
Write([]byte) (int, error)

My questions are:

  1. Is it OK to use my code to safely detect if a HTTP connection is hijacked? I only want to check the connection is hijacked or not, but do NOT want it to add headers for me!

  2. Since the ResponseWriter is an interface, I cannot click through the source code to find out how the standard library implements that method. In general, how can I drill down to the standard library (or any open source code) to find out the implementation of an interface?

Upvotes: 2

Views: 780

Answers (1)

xrfang
xrfang

Reputation: 2333

Thanks to Cerise, I found the source code of the standard response.Writer:

func (w *response) write(lenData int, dataB []byte, dataS string) (n int, err error) {
    if w.conn.hijacked() {
        if lenData > 0 {
            caller := relevantCaller()
            w.conn.server.logf("http: response.Write on hijacked connection from %s (%s:%d)", caller.Function, path.Base(caller.File), caller.Line)
        }
        return 0, ErrHijacked
    }
    ... ....

So, as said in the document, there is NO side effect.

Upvotes: 1

Related Questions