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:
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!
Since the
ResponseWriteris 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?
fmt.Printf("the response writer is a %T\n", responseWriter)in a handler. The code is in server.go.