Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I tell if net/http's ResponseWriter.Write() has been called?

Tags:

http

go

Suppose I have a chain of net/http Handlers, and an early one responds with an HTTP error (http.StatusInternalServerError, for instance). How can I detect this in the following handlers, and avoid sending additional data to the client?

Or is this entirely the wrong approach to the problem?

like image 882
Flimzy Avatar asked Dec 06 '25 17:12

Flimzy


1 Answers

http.ResponseWriter is an interface. So just compose a new instance of it:

type MyResponseWriter struct {
    http.ResponseWriter
    WroteHeader bool
}

func (w *MyResponseWriter) Write(b []byte) (int, error) {
    w.WroteHeader = true
    return w.ResponseWriter.Write(b)
}

func (w *MyResponseWriter) WriteHeader(code int) {
    w.WroteHeader = true
    w.ResponseWriter.WriteHeader(code)
}

And in your handlers:

//...
if w, ok := w.(*MyResponseWriter); ok && w.WroteHeader {
    log.Println("Already wrote, skipping")
    return
}

EDIT: Another thing to consider. Most of the time if you have a "chain" of handlers that means that a handler is called inside a handler. So if you have something like

type Handler1 struct { http.Handler }
type Handler2 struct { http.Handler }
type Handler3 struct { http.Handler }
var MyHandler http.Handler = Handler1{Handler2{Handler3{h}}}

as long as each of those call the inner handler as the last thing they do with w and r, you should be fine because then w and r won't even reach the inner handler. E.g.

func (h Handler2) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    if somethingBadHappened() {
        w.WriteHeader(http.StatusInternalServerError)
        return
    }
    h.ServeHTTP(w, r) // Not called if somethingBadHappened().
}
like image 149
Ainar-G Avatar answered Dec 08 '25 14:12

Ainar-G



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!