Is there a way to hook onto a flush/end event on an http.ResponseWriter in order to execute a handler which writes more to the writer just before sending.
You could create your own http.ResponseWriter
to do that, or you could just use a "middleware pattern":
// foo is the main handler
type foo struct{}
func (foo) ServeHTTP(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("foo"))
}
// bar writes after foo
type bar struct {
h http.Handler
}
func (b bar) ServeHTTP(w http.ResponseWriter, r *http.Request) {
b.h.ServeHTTP(w, r)
w.Write([]byte("BAR"))
}
Playground: http://play.golang.org/p/fB2OXNSTIe.
You can simply wrap your HandleFunc
, and after the wrapped handler returns, you can write further data to the ResponseWriter
:
func myhandler(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Hello"))
}
func wrapper(w http.ResponseWriter, r *http.Request) {
myhandler(w, r) // Call original
w.Write([]byte(" World")) // Write further data to output
}
func main() {
http.HandleFunc("/", wrapper)
http.ListenAndServe("", nil)
}
Visiting any URL will result in response:
Hello World
Things to keep in mind in production environment:
"Content-length"
header is set by the wrapped handler, writing more data will render it invalid (as the content will be bigger than indicated in the header).One possible "protection" against this might be to pass a custom ResponseWriter
implementation which writes only to a buffer (e.g. bytes.Buffer
) and the wrapper will append to this and set "Content-length"
according to the new length, and then write the content of the buffer to the "real" output.